diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 1aabbaea..eb5d6755 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.98 2006-08-20 15:49:06 bacon Exp $ + * $Id: awk.h,v 1.99 2006-08-22 15:10:48 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -76,7 +76,8 @@ enum XP_AWK_IO_CLOSE = 1, XP_AWK_IO_READ = 2, XP_AWK_IO_WRITE = 3, - XP_AWK_IO_NEXT = 4 + XP_AWK_IO_FLUSH = 4, + XP_AWK_IO_NEXT = 5 }; enum diff --git a/ase/awk/extio.c b/ase/awk/extio.c index 73e0c40c..247d064a 100644 --- a/ase/awk/extio.c +++ b/ase/awk/extio.c @@ -1,5 +1,5 @@ /* - * $Id: extio.c,v 1.27 2006-08-10 16:02:15 bacon Exp $ + * $Id: extio.c,v 1.28 2006-08-22 15:10:48 bacon Exp $ */ #include @@ -242,7 +242,6 @@ static int __writeextio ( { xp_awk_extio_t* p = run->extio.chain; xp_awk_io_t handler; - xp_str_t buf; xp_char_t* str; xp_size_t len; int extio_type, extio_mode, extio_mask, n; @@ -264,23 +263,20 @@ static int __writeextio ( return -1; } - if (v->type != XP_AWK_VAL_STR) + if (v->type == XP_AWK_VAL_STR) + { + str = ((xp_awk_val_str_t*)v)->buf; + len = ((xp_awk_val_str_t*)v)->len; + } + else { - /* TODO: optimize the buffer management. - * each xp_awk_run_t may have a buffer for this. */ - if (xp_str_open (&buf, 256) == XP_NULL) - { - *errnum = XP_AWK_ENOMEM; - return -1; - } - /* convert the value to string representation first */ - if (xp_awk_valtostr ( - v, errnum, xp_true, &buf, XP_NULL) == XP_NULL) - { - xp_str_close (&buf); - return -1; - } + + /* TOOD: consider using a shared buffer when calling + * xp_awk_valtostr. maybe run->shared_buf.extio */ + str = xp_awk_valtostr ( + v, errnum, xp_true, NULL, &len); + if (str == XP_NULL) return -1; } /* look for the corresponding extio for name */ @@ -307,7 +303,7 @@ static int __writeextio ( p = (xp_awk_extio_t*) xp_malloc (xp_sizeof(xp_awk_extio_t)); if (p == XP_NULL) { - if (v->type != XP_AWK_VAL_STR) xp_str_close (&buf); + if (v->type != XP_AWK_VAL_STR) xp_free (str); *errnum = XP_AWK_ENOMEM; return -1; } @@ -316,7 +312,7 @@ static int __writeextio ( if (p->name == XP_NULL) { xp_free (p); - if (v->type != XP_AWK_VAL_STR) xp_str_close (&buf); + if (v->type != XP_AWK_VAL_STR) xp_free (str); *errnum = XP_AWK_ENOMEM; return -1; } @@ -331,7 +327,7 @@ static int __writeextio ( { xp_free (p->name); xp_free (p); - if (v->type != XP_AWK_VAL_STR) xp_str_close (&buf); + if (v->type != XP_AWK_VAL_STR) xp_free (str); /* TODO: use meaningful error code */ xp_awk_setglobal (run, @@ -354,24 +350,13 @@ static int __writeextio ( /* TODO: if write handler returns less than the request, loop */ /* TODO: */ /* TODO: */ - if (v->type != XP_AWK_VAL_STR) - { - str = XP_STR_BUF(&buf); - len = XP_STR_LEN(&buf); - } - else - { - str = ((xp_awk_val_str_t*)v)->buf; - len = ((xp_awk_val_str_t*)v)->len; - } - if (len > 0) { n = handler (XP_AWK_IO_WRITE, p, str, len); if (n == -1) { - if (v->type != XP_AWK_VAL_STR) xp_str_close (&buf); + if (v->type != XP_AWK_VAL_STR) xp_free (str); /* TODO: use meaningful error code */ xp_awk_setglobal (run, @@ -382,12 +367,12 @@ static int __writeextio ( if (n == 0) { - if (v->type != XP_AWK_VAL_STR) xp_str_close (&buf); + if (v->type != XP_AWK_VAL_STR) xp_free (str); return 0; } } - if (v->type != XP_AWK_VAL_STR) xp_str_close (&buf); + if (v->type != XP_AWK_VAL_STR) xp_free (str); if (nl) { @@ -408,6 +393,62 @@ static int __writeextio ( return 1; } +int xp_awk_flushextio ( + xp_awk_run_t* run, int out_type, const xp_char_t* name, int* errnum) +{ + xp_awk_extio_t* p = run->extio.chain; + xp_awk_io_t handler; + int extio_type, extio_mode, extio_mask, n; + + xp_assert (out_type >= 0 && out_type <= xp_countof(__out_type_map)); + xp_assert (out_type >= 0 && out_type <= xp_countof(__out_mode_map)); + xp_assert (out_type >= 0 && out_type <= xp_countof(__out_mask_map)); + + /* translate the out_type into the relevant extio type and mode */ + extio_type = __out_type_map[out_type]; + extio_mode = __out_mode_map[out_type]; + extio_mask = __out_mask_map[out_type]; + + handler = run->extio.handler[extio_type]; + if (handler == XP_NULL) + { + /* no io handler provided */ + *errnum = XP_AWK_EIOIMPL; /* TODO: change the error code */ + return -1; + } + + /* look for the corresponding extio for name */ + while (p != XP_NULL) + { + if (p->type == (extio_type | extio_mask) && + xp_strcmp (p->name, name) == 0) break; + p = p->next; + } + + /* there is not corresponding extio for name */ + if (p == XP_NULL) + { + /* TODO: use meaningful error code. but is this needed? */ + xp_awk_setglobal (run, + XP_AWK_GLOBAL_ERRNO, xp_awk_val_one); + *errnum = XP_AWK_ENOERR; + return -1; + } + + n = handler (XP_AWK_IO_FLUSH, p, XP_NULL, 0); + + if (n == -1) + { + /* TODO: use meaningful error code */ + xp_awk_setglobal (run, + XP_AWK_GLOBAL_ERRNO, xp_awk_val_one); + *errnum = XP_AWK_ENOERR; + return -1; + } + + return 0; +} + int xp_awk_nextextio_read ( xp_awk_run_t* run, int in_type, const xp_char_t* name, int* errnum) { diff --git a/ase/awk/extio.h b/ase/awk/extio.h index 04b4a645..eaad0d5e 100644 --- a/ase/awk/extio.h +++ b/ase/awk/extio.h @@ -1,5 +1,5 @@ /* - * $Id: extio.h,v 1.9 2006-08-03 09:53:43 bacon Exp $ + * $Id: extio.h,v 1.10 2006-08-22 15:10:48 bacon Exp $ */ #ifndef _XP_AWK_EXTIO_H_ @@ -25,6 +25,9 @@ int xp_awk_writeextio_nl ( xp_awk_run_t* run, int out_type, const xp_char_t* name, xp_awk_val_t* v, int* errnum); +int xp_awk_flushextio ( + xp_awk_run_t* run, int out_type, const xp_char_t* name, int* errnum); + int xp_awk_nextextio_read ( xp_awk_run_t* run, int in_type, const xp_char_t* name, int* errnum); diff --git a/ase/awk/func.c b/ase/awk/func.c index 8c4d5d4e..180abda4 100644 --- a/ase/awk/func.c +++ b/ase/awk/func.c @@ -1,5 +1,5 @@ /* - * $Id: func.c,v 1.25 2006-08-21 14:49:08 bacon Exp $ + * $Id: func.c,v 1.26 2006-08-22 15:10:48 bacon Exp $ */ #include @@ -227,7 +227,7 @@ static int __bfn_fflush (xp_awk_t* awk, void* run) xp_awk_val_t* a0; xp_char_t* str0; xp_size_t len0; - int errnum, n; + int errnum, n, n2; nargs = xp_awk_getnargs (run); xp_assert (nargs >= 0 && nargs <= 1); @@ -235,10 +235,18 @@ static int __bfn_fflush (xp_awk_t* awk, void* run) if (nargs == 0) { /* flush the console output */ - n = 0; + n = xp_awk_flushextio (run, + XP_AWK_OUT_CONSOLE, XP_T(""), &errnum); + if (n == -1 && errnum != XP_AWK_ENOERR) + { + xp_awk_seterrnum (run, errnum); + return -1; + } } else { + xp_char_t* ptr, * end; + a0 = xp_awk_getarg (run, 0); if (a0->type == XP_AWK_VAL_STR) { @@ -254,22 +262,78 @@ static int __bfn_fflush (xp_awk_t* awk, void* run) xp_awk_seterrnum (run, errnum); return -1; } + + } + + /* the target name contains a null character. + * make fflush return -1 and set ERRNO accordingly */ + ptr = str0; end = str0 + len0; + while (ptr < end) + { + if (*ptr == XP_T('\0')) + { + if (a0->type != XP_AWK_VAL_STR) xp_free (str0); + n = -1; + goto skip_flush; + } + + ptr++; } if (len0 == 0) { /* flush all open files and pipes */ + /* TODO: */ } else { /* flush the given extio */ + n = 0; + + /* TODO: no file -> error, at least on file -> not an error */ + n2 = xp_awk_flushextio (run, + XP_AWK_OUT_FILE, str0, &errnum); + if (n2 == -1) + { + if (errnum != XP_AWK_ENOERR) + { + xp_awk_seterrnum (run, errnum); + return -1; + } + n = -1; + } + + n2 = xp_awk_flushextio (run, + XP_AWK_OUT_PIPE, str0, &errnum); + if (n2 == -1) + { + if (errnum != XP_AWK_ENOERR) + { + xp_awk_seterrnum (run, errnum); + return -1; + } + n = -1; + } +/* TODO: include this */ +#if 0 + n2 = xp_awk_flushextio (run, + XP_AWK_OUT_COPROC, str0, &errnum); + if (n2 == -1) + { + if (errnum != XP_AWK_ENOERR) + { + xp_awk_seterrnum (run, errnum); + return -1; + } + n = -1; + } +#endif } if (a0->type != XP_AWK_VAL_STR) xp_free (str0); - - n = 0; } +skip_flush: a0 = xp_awk_makeintval (run, (xp_long_t)n); if (a0 == XP_NULL) { diff --git a/ase/awk/run.c b/ase/awk/run.c index 3dbb7c3b..a31b810c 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.173 2006-08-21 02:53:42 bacon Exp $ + * $Id: run.c,v 1.174 2006-08-22 15:10:48 bacon Exp $ */ #include @@ -1649,6 +1649,7 @@ static int __run_print (xp_awk_run_t* run, xp_awk_nde_print_t* nde) /* the output destination name contains a null * character. */ xp_free (out); + n = -1; goto skip_write; /* TODO: how to handle error??? * make print return -1??? not possible. @@ -4349,6 +4350,7 @@ static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde) { /* the input source name contains a null * character. make getline return -1 */ + /* TODO: set ERRNO */ xp_free (in); n = -1; goto skip_read; diff --git a/ase/test/awk/awk.c b/ase/test/awk/awk.c index edd41464..ffb7c6a0 100644 --- a/ase/test/awk/awk.c +++ b/ase/test/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.72 2006-08-13 16:05:04 bacon Exp $ + * $Id: awk.c,v 1.73 2006-08-22 15:11:13 bacon Exp $ */ #include @@ -136,35 +136,30 @@ static xp_ssize_t process_source ( struct src_io* src_io = (struct src_io*)arg; xp_char_t c; - switch (cmd) + if (cmd == XP_AWK_IO_OPEN) { - case XP_AWK_IO_OPEN: - { - if (src_io->input_file == XP_NULL) return 0; - src_io->input_handle = fopen_t (src_io->input_file, XP_T("r")); - if (src_io->input_handle == NULL) return -1; - return 1; - } - - case XP_AWK_IO_CLOSE: - { - if (src_io->input_file == XP_NULL) return 0; - fclose ((FILE*)src_io->input_handle); - return 0; - } - - case XP_AWK_IO_READ: - { - if (size <= 0) return -1; - #ifdef XP_CHAR_IS_MCHAR - c = fgetc ((FILE*)src_io->input_handle); - #else - c = fgetwc ((FILE*)src_io->input_handle); - #endif - if (c == XP_CHAR_EOF) return 0; - *data = c; - return 1; - } + if (src_io->input_file == XP_NULL) return 0; + src_io->input_handle = fopen_t (src_io->input_file, XP_T("r")); + if (src_io->input_handle == NULL) return -1; + return 1; + } + else if (cmd == XP_AWK_IO_CLOSE) + { + if (src_io->input_file == XP_NULL) return 0; + fclose ((FILE*)src_io->input_handle); + return 0; + } + else if (cmd == XP_AWK_IO_READ) + { + if (size <= 0) return -1; + #ifdef XP_CHAR_IS_MCHAR + c = fgetc ((FILE*)src_io->input_handle); + #else + c = fgetwc ((FILE*)src_io->input_handle); + #endif + if (c == XP_CHAR_EOF) return 0; + *data = c; + return 1; } return -1; @@ -175,37 +170,24 @@ static xp_ssize_t dump_source ( { struct src_io* src_io = (struct src_io*)arg; - switch (cmd) + if (cmd == XP_AWK_IO_OPEN || cmd == XP_AWK_IO_CLOSE) return 0; + else if (cmd == XP_AWK_IO_WRITE) { - case XP_AWK_IO_OPEN: + xp_size_t i; + for (i = 0; i < size; i++) { - return 0; - } - - case XP_AWK_IO_CLOSE: - { - return 0; - } - - case XP_AWK_IO_WRITE: - { - xp_size_t i; - for (i = 0; i < size; i++) - { - #ifdef XP_CHAR_IS_MCHAR - fputc (data[i], stdout); - #else - fputwc (data[i], stdout); - #endif - } - return size; + #ifdef XP_CHAR_IS_MCHAR + fputc (data[i], stdout); + #else + fputwc (data[i], stdout); + #endif } + return size; } return -1; } - static xp_ssize_t process_extio_pipe ( int cmd, void* arg, xp_char_t* data, xp_size_t size) { @@ -255,6 +237,11 @@ xp_printf (XP_TEXT("closing %s of type (pipe) %d\n"), epa->name, epa->type); return -1; } + case XP_AWK_IO_FLUSH: + { + return -1; + } + case XP_AWK_IO_NEXT: { return -1; @@ -310,7 +297,13 @@ xp_printf (XP_TEXT("closing %s of type %d (file)\n"), epa->name, epa->type); { /* TODO: how to return error or 0 */ fputs_t (data, /*size,*/ (FILE*)epa->handle); - return -1; + return size; + } + + case XP_AWK_IO_FLUSH: + { + if (fflush ((FILE*)epa->handle) == EOF) return -1; + return 0; } case XP_AWK_IO_NEXT: @@ -409,6 +402,11 @@ xp_printf (XP_TEXT("open the next console [%s]\n"), infiles[infile_no]); /*MessageBox (NULL, data, data, MB_OK);*/ return size; } + else if (cmd == XP_AWK_IO_FLUSH) + { + if (fflush ((FILE*)epa->handle) == EOF) return -1; + return 0; + } else if (cmd == XP_AWK_IO_NEXT) { return next_extio_console (epa); diff --git a/ase/test/awk/t12.awk b/ase/test/awk/t12.awk index 7af3b8fd..6e97bbbe 100644 --- a/ase/test/awk/t12.awk +++ b/ase/test/awk/t12.awk @@ -1,5 +1,4 @@ -BEGIN -{ +BEGIN { /* print "line 1" >> "1"; print "line 2" > "1"; @@ -31,6 +30,7 @@ BEGIN } print x > "def"; + print "fflush() = ", fflush ("def"); // print (1 (2 getline j) j); // print "abc" 1 + 2 3 + 49 2 / 3; diff --git a/ase/test/awk/t9.awk b/ase/test/awk/t9.awk index 9f5d9f9a..bf5b5414 100644 --- a/ase/test/awk/t9.awk +++ b/ase/test/awk/t9.awk @@ -1,5 +1,4 @@ -BEGIN -{ +BEGIN { while (("xxx /p" | getline var) > 0) ; while (("dir /w" | getline var) > 0) ; while ((getline var < "t9.awk") > 0) ;