From b51edf37c4271bf5ec5dcad9d35169f55e38efa9 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Tue, 20 Mar 2012 10:46:03 -0400 Subject: - Add new environment variable AWKLIBPATH to use when searching for shared libraries. - Instead of hardcoding the default ".so" suffix for shared libraries, use autoconf to get the right value for this platform. - Build and install some of the bundled shared library extensions so that they will now be available using the default AWKLIBPATH. --- io.c | 84 ++++++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 37 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 25f32e21..5a110e02 100644 --- a/io.c +++ b/io.c @@ -2311,35 +2311,45 @@ do_getline(int intovar, IOBUF *iop) return make_number((AWKNUM) 1.0); } +typedef struct { + const char *envname; + char **dfltp; + char try_cwd; /* always search current directory? */ + char **awkpath; /* array containing library search paths */ + int max_pathlen; /* length of the longest item in awkpath */ +} path_info; + +static path_info pi_awkpath = { + .envname = "AWKPATH", + .dfltp = &defpath, + .try_cwd = TRUE, +}; -static char **awkpath = NULL; /* array containing library search paths */ -static int max_pathlen; /* length of the longest item in awkpath */ +static path_info pi_awklibpath = { + .envname = "AWKLIBPATH", + .dfltp = &deflibpath, + .try_cwd = FALSE, +}; /* init_awkpath --- split path(=$AWKPATH) into components */ static void -init_awkpath(char *path) +init_awkpath(path_info *pi) { + char *path; char *start, *end, *p; int len, i; - static int max_path = 0; + int max_path; /* (# of allocated paths)-1 */ #define INC_PATH 5 - max_pathlen = 0; - if (path == NULL || *path == '\0') - path = defpath; - - for (i = 0; i < max_path && awkpath[i]; i++) { - efree(awkpath[i]); - awkpath[i] = NULL; - } + pi->max_pathlen = 0; + if ((path = getenv(pi->envname)) == NULL || *path == '\0') + path = *(pi->dfltp); - if (max_path == 0) { - max_path = INC_PATH; - emalloc(awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath"); - memset(awkpath, 0, (max_path + 1) * sizeof(char *)); - } + max_path = INC_PATH; + emalloc(pi->awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath"); + memset(pi->awkpath, 0, (max_path + 1) * sizeof(char *)); end = start = path; i = 0; @@ -2358,12 +2368,12 @@ init_awkpath(char *path) if (i == max_path) { max_path += INC_PATH; - erealloc(awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath"); - memset(awkpath + i, 0, (INC_PATH + 1) * sizeof(char *)); + erealloc(pi->awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath"); + memset(pi->awkpath + i, 0, (INC_PATH + 1) * sizeof(char *)); } - awkpath[i++] = p; - if (len > max_pathlen) - max_pathlen = len; + pi->awkpath[i++] = p; + if (len > pi->max_pathlen) + pi->max_pathlen = len; } /* skip one or more envsep char */ @@ -2371,7 +2381,7 @@ init_awkpath(char *path) end++; start = end; } - awkpath[i] = NULL; + pi->awkpath[i] = NULL; #undef INC_PATH } @@ -2403,7 +2413,7 @@ get_cwd () /* do_find_source --- search $AWKPATH for file, return NULL if not found */ static char * -do_find_source(const char *src, struct stat *stb, int *errcode) +do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi) { char *path; int i; @@ -2422,7 +2432,7 @@ do_find_source(const char *src, struct stat *stb, int *errcode) } /* try current directory before $AWKPATH search */ - if (stat(src, stb) == 0) { + if (pi->try_cwd && (stat(src, stb) == 0)) { path = get_cwd(); if (path == NULL) { *errcode = errno; @@ -2434,16 +2444,15 @@ do_find_source(const char *src, struct stat *stb, int *errcode) return path; } - if (awkpath == NULL) - init_awkpath(getenv("AWKPATH")); + if (pi->awkpath == NULL) + init_awkpath(pi); - emalloc(path, char *, max_pathlen + strlen(src) + 1, "do_find_source"); - for (i = 0; awkpath[i] != NULL; i++) { - if (strcmp(awkpath[i], "./") == 0 || strcmp(awkpath[i], ".") == 0) { - /* FIXME: already tried CWD above; Why do it again ? */ + emalloc(path, char *, pi->max_pathlen + strlen(src) + 1, "do_find_source"); + for (i = 0; pi->awkpath[i] != NULL; i++) { + if (strcmp(pi->awkpath[i], "./") == 0 || strcmp(pi->awkpath[i], ".") == 0) *path = '\0'; - } else - strcpy(path, awkpath[i]); + else + strcpy(path, pi->awkpath[i]); strcat(path, src); if (stat(path, stb) == 0) return path; @@ -2461,11 +2470,12 @@ char * find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) { char *path; + path_info *pi = (is_extlib ? &pi_awklibpath : &pi_awkpath); *errcode = 0; if (src == NULL || *src == '\0') return NULL; - path = do_find_source(src, stb, errcode); + path = do_find_source(src, stb, errcode, pi); if (path == NULL && is_extlib) { char *file_ext; @@ -2473,7 +2483,7 @@ find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) size_t src_len; size_t suffix_len; -#define EXTLIB_SUFFIX ".so" +#define EXTLIB_SUFFIX "." SHLIBEXT src_len = strlen(src); suffix_len = strlen(EXTLIB_SUFFIX); @@ -2485,7 +2495,7 @@ find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) save_errno = errno; emalloc(file_ext, char *, src_len + suffix_len + 1, "find_source"); sprintf(file_ext, "%s%s", src, EXTLIB_SUFFIX); - path = do_find_source(file_ext, stb, errcode); + path = do_find_source(file_ext, stb, errcode, pi); efree(file_ext); if (path == NULL) errno = save_errno; @@ -2505,7 +2515,7 @@ find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) emalloc(file_awk, char *, strlen(src) + sizeof(DEFAULT_FILETYPE) + 1, "find_source"); sprintf(file_awk, "%s%s", src, DEFAULT_FILETYPE); - path = do_find_source(file_awk, stb, errcode); + path = do_find_source(file_awk, stb, errcode, pi); efree(file_awk); if (path == NULL) { errno = save_errno; -- cgit v1.2.3 From 85a195f6f9901e98abe9306f1e05e25107e61955 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sat, 24 Mar 2012 11:16:23 -0400 Subject: Fix some coding style issues and a typo in a comment. --- io.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 5a110e02..79bc8682 100644 --- a/io.c +++ b/io.c @@ -2312,23 +2312,23 @@ do_getline(int intovar, IOBUF *iop) } typedef struct { - const char *envname; - char **dfltp; - char try_cwd; /* always search current directory? */ - char **awkpath; /* array containing library search paths */ - int max_pathlen; /* length of the longest item in awkpath */ + const char *envname; + char **dfltp; /* pointer to address of default path */ + char try_cwd; /* always search current directory? */ + char **awkpath; /* array containing library search paths */ + int max_pathlen; /* length of the longest item in awkpath */ } path_info; static path_info pi_awkpath = { - .envname = "AWKPATH", - .dfltp = &defpath, - .try_cwd = TRUE, + /* envname */ "AWKPATH", + /* dfltp */ & defpath, + /* try_cwd */ TRUE, }; static path_info pi_awklibpath = { - .envname = "AWKLIBPATH", - .dfltp = &deflibpath, - .try_cwd = FALSE, + /* envname */ "AWKLIBPATH", + /* dfltp */ & deflibpath, + /* try_cwd */ FALSE, }; /* init_awkpath --- split path(=$AWKPATH) into components */ @@ -2432,7 +2432,7 @@ do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi) } /* try current directory before $AWKPATH search */ - if (pi->try_cwd && (stat(src, stb) == 0)) { + if (pi->try_cwd && stat(src, stb) == 0) { path = get_cwd(); if (path == NULL) { *errcode = errno; @@ -2470,7 +2470,7 @@ char * find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) { char *path; - path_info *pi = (is_extlib ? &pi_awklibpath : &pi_awkpath); + path_info *pi = (is_extlib ? & pi_awklibpath : & pi_awkpath); *errcode = 0; if (src == NULL || *src == '\0') -- cgit v1.2.3 From 15635ff21b6f1a0951f0ff5de6ddaf0edab8edd7 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 26 Mar 2012 21:36:37 +0200 Subject: Some minor style edits in code and doc. --- io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index 79bc8682..e3327f17 100644 --- a/io.c +++ b/io.c @@ -2345,7 +2345,7 @@ init_awkpath(path_info *pi) pi->max_pathlen = 0; if ((path = getenv(pi->envname)) == NULL || *path == '\0') - path = *(pi->dfltp); + path = pi->dfltp[0]; max_path = INC_PATH; emalloc(pi->awkpath, char **, (max_path + 1) * sizeof(char *), "init_awkpath"); -- cgit v1.2.3 From 3438b2129cd933e430349a6bd66a1933071c92c2 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 1 Apr 2012 17:07:45 -0400 Subject: Update ERRNO API. --- io.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index e3327f17..b2d29825 100644 --- a/io.c +++ b/io.c @@ -230,7 +230,6 @@ extern int output_is_tty; extern NODE *ARGC_node; extern NODE *ARGV_node; extern NODE *ARGIND_node; -extern NODE *ERRNO_node; extern NODE **fields_arr; @@ -308,7 +307,7 @@ after_beginfile(IOBUF **curfile) errcode = iop->errcode; iop->errcode = 0; errno = 0; - update_ERRNO(); + update_ERRNO_int(errno); iop_close(iop); *curfile = NULL; if (errcode == EISDIR && ! do_traditional) { @@ -382,7 +381,7 @@ nextfile(IOBUF **curfile, int skipping) fd = devopen(fname, binmode("r")); errcode = errno; if (! do_traditional) - update_ERRNO(); + update_ERRNO_int(errno); /* This is a kludge. */ unref(FILENAME_node->var_value); @@ -404,7 +403,7 @@ nextfile(IOBUF **curfile, int skipping) /* FNR is init'ed to 0 */ errno = 0; if (! do_traditional) - update_ERRNO(); + update_ERRNO_int(errno); unref(FILENAME_node->var_value); FILENAME_node->var_value = make_string("-", 1); FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */ @@ -415,7 +414,7 @@ nextfile(IOBUF **curfile, int skipping) if (iop->fd == INVALID_HANDLE) { errcode = errno; errno = 0; - update_ERRNO(); + update_ERRNO_int(errno); (void) iop_close(iop); *curfile = NULL; fatal(_("cannot open file `%s' for reading (%s)"), @@ -462,7 +461,7 @@ inrec(IOBUF *iop, int *errcode) if (cnt == EOF) { retval = 1; if (*errcode > 0) - update_ERRNO_saved(*errcode); + update_ERRNO_int(*errcode); } else { NR += 1; FNR += 1; @@ -990,8 +989,7 @@ do_close(int nargs) if (! do_traditional) { /* update ERRNO manually, using errno = ENOENT is a stretch. */ cp = _("close of redirection that was never opened"); - unref(ERRNO_node->var_value); - ERRNO_node->var_value = make_string(cp, strlen(cp)); + update_ERRNO_string(cp, DONT_TRANSLATE); } DEREF(tmp); @@ -1111,7 +1109,7 @@ close_redir(struct redirect *rp, int exitwarn, two_way_close_type how) if (! do_traditional) { /* set ERRNO too so that program can get at it */ - update_ERRNO_saved(save_errno); + update_ERRNO_int(save_errno); } } @@ -2228,7 +2226,7 @@ do_getline_redir(int intovar, int redirtype) if (rp == NULL) { if (redir_error) { /* failed redirect */ if (! do_traditional) - update_ERRNO_saved(redir_error); + update_ERRNO_int(redir_error); } return make_number((AWKNUM) -1.0); } @@ -2240,7 +2238,7 @@ do_getline_redir(int intovar, int redirtype) cnt = get_a_record(&s, iop, &errcode); if (errcode != 0) { if (! do_traditional && (errcode != -1)) - update_ERRNO_saved(errcode); + update_ERRNO_int(errcode); return make_number((AWKNUM) -1.0); } @@ -2288,7 +2286,7 @@ do_getline(int intovar, IOBUF *iop) cnt = get_a_record(&s, iop, &errcode); if (errcode != 0) { if (! do_traditional && (errcode != -1)) - update_ERRNO_saved(errcode); + update_ERRNO_int(errcode); if (intovar) (void) POP_ADDRESS(); return make_number((AWKNUM) -1.0); -- cgit v1.2.3 From 920b87dfab2e0504c8a1eb26eb6f130bcb748218 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 1 Apr 2012 17:07:56 -0400 Subject: Update ERRNO API. --- io.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index e3327f17..b2d29825 100644 --- a/io.c +++ b/io.c @@ -230,7 +230,6 @@ extern int output_is_tty; extern NODE *ARGC_node; extern NODE *ARGV_node; extern NODE *ARGIND_node; -extern NODE *ERRNO_node; extern NODE **fields_arr; @@ -308,7 +307,7 @@ after_beginfile(IOBUF **curfile) errcode = iop->errcode; iop->errcode = 0; errno = 0; - update_ERRNO(); + update_ERRNO_int(errno); iop_close(iop); *curfile = NULL; if (errcode == EISDIR && ! do_traditional) { @@ -382,7 +381,7 @@ nextfile(IOBUF **curfile, int skipping) fd = devopen(fname, binmode("r")); errcode = errno; if (! do_traditional) - update_ERRNO(); + update_ERRNO_int(errno); /* This is a kludge. */ unref(FILENAME_node->var_value); @@ -404,7 +403,7 @@ nextfile(IOBUF **curfile, int skipping) /* FNR is init'ed to 0 */ errno = 0; if (! do_traditional) - update_ERRNO(); + update_ERRNO_int(errno); unref(FILENAME_node->var_value); FILENAME_node->var_value = make_string("-", 1); FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */ @@ -415,7 +414,7 @@ nextfile(IOBUF **curfile, int skipping) if (iop->fd == INVALID_HANDLE) { errcode = errno; errno = 0; - update_ERRNO(); + update_ERRNO_int(errno); (void) iop_close(iop); *curfile = NULL; fatal(_("cannot open file `%s' for reading (%s)"), @@ -462,7 +461,7 @@ inrec(IOBUF *iop, int *errcode) if (cnt == EOF) { retval = 1; if (*errcode > 0) - update_ERRNO_saved(*errcode); + update_ERRNO_int(*errcode); } else { NR += 1; FNR += 1; @@ -990,8 +989,7 @@ do_close(int nargs) if (! do_traditional) { /* update ERRNO manually, using errno = ENOENT is a stretch. */ cp = _("close of redirection that was never opened"); - unref(ERRNO_node->var_value); - ERRNO_node->var_value = make_string(cp, strlen(cp)); + update_ERRNO_string(cp, DONT_TRANSLATE); } DEREF(tmp); @@ -1111,7 +1109,7 @@ close_redir(struct redirect *rp, int exitwarn, two_way_close_type how) if (! do_traditional) { /* set ERRNO too so that program can get at it */ - update_ERRNO_saved(save_errno); + update_ERRNO_int(save_errno); } } @@ -2228,7 +2226,7 @@ do_getline_redir(int intovar, int redirtype) if (rp == NULL) { if (redir_error) { /* failed redirect */ if (! do_traditional) - update_ERRNO_saved(redir_error); + update_ERRNO_int(redir_error); } return make_number((AWKNUM) -1.0); } @@ -2240,7 +2238,7 @@ do_getline_redir(int intovar, int redirtype) cnt = get_a_record(&s, iop, &errcode); if (errcode != 0) { if (! do_traditional && (errcode != -1)) - update_ERRNO_saved(errcode); + update_ERRNO_int(errcode); return make_number((AWKNUM) -1.0); } @@ -2288,7 +2286,7 @@ do_getline(int intovar, IOBUF *iop) cnt = get_a_record(&s, iop, &errcode); if (errcode != 0) { if (! do_traditional && (errcode != -1)) - update_ERRNO_saved(errcode); + update_ERRNO_int(errcode); if (intovar) (void) POP_ADDRESS(); return make_number((AWKNUM) -1.0); -- cgit v1.2.3 From 67db3f45748d22ff23c03d1887cb0aac341f81bb Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 26 Apr 2012 23:18:01 +0300 Subject: Cleanups in io.c and improve RS as regexp. --- io.c | 483 ++++++++++++++++++++++++++++++++----------------------------------- 1 file changed, 233 insertions(+), 250 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 721b1ab7..7e46cd9a 100644 --- a/io.c +++ b/io.c @@ -72,11 +72,15 @@ #include #endif /* HAVE_NETDB_H */ +#if defined(HAVE_POPEN_H) +#include "popen.h" +#endif + #ifndef HAVE_GETADDRINFO #include "missing_d/getaddrinfo.h" #endif -#ifndef AI_ADDRCONFIG /* This is a recent symbol, not everyone has it */ +#ifndef AI_ADDRCONFIG /* not everyone has this symbol */ #define AI_ADDRCONFIG 0 #endif /* AI_ADDRCONFIG */ @@ -142,44 +146,47 @@ typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type; -/* Several macros make the code a bit clearer: */ -/* */ -/* */ -/* = */ +/* Several macros to make the code a bit clearer. */ #define at_eof(iop) (((iop)->flag & IOP_AT_EOF) != 0) #define has_no_data(iop) ((iop)->dataend == NULL) #define no_data_left(iop) ((iop)->off >= (iop)->dataend) -/* The key point to the design is to split out the code that searches through */ -/* a buffer looking for the record and the terminator into separate routines, */ -/* with a higher-level routine doing the reading of data and buffer management. */ -/* This makes the code easier to manage; the buffering code is the same independent */ -/* of how we find a record. Communication is via the return value: */ -/* */ -/* */ -/* = */ + +/* + * The key point to the design is to split out the code that searches through + * a buffer looking for the record and the terminator into separate routines, + * with a higher-level routine doing the reading of data and buffer management. + * This makes the code easier to manage; the buffering code is the same + * independent of how we find a record. Communication is via the return + * value: + */ + typedef enum recvalues { REC_OK, /* record and terminator found, recmatch struct filled in */ NOTERM, /* no terminator found, give me more input data */ TERMATEND, /* found terminator at end of buffer */ - TERMNEAREND /* found terminator close to end of buffer, for RE might be bigger */ + TERMNEAREND /* found terminator close to end of buffer, for when + the RE might be match more data further in + the file. */ } RECVALUE; -/* Between calls to a scanning routine, the state is stored in */ -/* an [[enum scanstate]] variable. Not all states apply to all */ -/* variants, but the higher code doesn't really care. */ -/* */ -/* */ -/* = */ + +/* + * Between calls to a scanning routine, the state is stored in + * an enum scanstate variable. Not all states apply to all + * variants, but the higher code doesn't really care. + */ + typedef enum scanstate { NOSTATE, /* scanning not started yet (all) */ INLEADER, /* skipping leading data (RS = "") */ INDATA, /* in body of record (all) */ INTERM /* scanning terminator (RS = "", RS = regexp) */ } SCANSTATE; -/* When a record is seen ([[REC_OK]] or [[TERMATEND]]), the following */ -/* structure is filled in. */ -/* */ -/* */ -/* = */ + +/* + * When a record is seen (REC_OK or TERMATEND), the following + * structure is filled in. + */ + struct recmatch { char *start; /* record start */ size_t len; /* length of record */ @@ -218,28 +225,21 @@ static NODE *in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx); static long get_read_timeout(IOBUF *iop); static ssize_t read_with_timeout(int fd, char *buf, size_t size); -#if defined(HAVE_POPEN_H) -#include "popen.h" -#endif - static int read_can_timeout = FALSE; static long read_timeout; static long read_default_timeout; static struct redirect *red_head = NULL; static NODE *RS = NULL; -static Regexp *RS_re_yes_case; -static Regexp *RS_re_no_case; +static Regexp *RS_re_yes_case; /* regexp for RS when ignoring case */ +static Regexp *RS_re_no_case; /* regexp for RS when not ignoring case */ static Regexp *RS_regexp; int RS_is_null; -extern int output_is_tty; extern NODE *ARGC_node; extern NODE *ARGV_node; extern NODE *ARGIND_node; -extern NODE *ERRNO_node; -extern NODE **fields_arr; /* init_io --- set up timeout related variables */ @@ -301,6 +301,8 @@ static int vmsrtl_fileno(fp) FILE *fp; { return fileno(fp); } #define fileno(FP) (((FP) && *(FP)) ? vmsrtl_fileno(FP) : -1) #endif /* VMS */ +/* after_beginfile --- reset necessary state after BEGINFILE has run */ + void after_beginfile(IOBUF **curfile) { @@ -347,14 +349,14 @@ nextfile(IOBUF **curfile, int skipping) static IOBUF mybuf; const char *fname; int fd = INVALID_HANDLE; - int errcode; + int errcode = 0; IOBUF *iop = *curfile; long argc; if (skipping) { /* for 'nextfile' call */ errcode = 0; if (iop != NULL) { - errcode = iop->errcode; + errcode = iop->errcode; (void) iop_close(iop); } *curfile = NULL; @@ -396,7 +398,6 @@ nextfile(IOBUF **curfile, int skipping) if (! do_traditional) update_ERRNO(); - /* This is a kludge. */ unref(FILENAME_node->var_value); FILENAME_node->var_value = dupnode(arg); #ifdef HAVE_MPFR @@ -404,7 +405,7 @@ nextfile(IOBUF **curfile, int skipping) mpz_set_ui(MFNR, 0); #endif FNR = 0; - iop = *curfile = iop_alloc(fd, fname, &mybuf, FALSE); + iop = *curfile = iop_alloc(fd, fname, & mybuf, FALSE); if (fd == INVALID_HANDLE) iop->errcode = errcode; else @@ -425,7 +426,7 @@ nextfile(IOBUF **curfile, int skipping) FILENAME_node->var_value = make_string("-", 1); FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */ fname = "-"; - iop = *curfile = iop_alloc(fileno(stdin), fname, &mybuf, FALSE); + iop = *curfile = iop_alloc(fileno(stdin), fname, & mybuf, FALSE); iop->flag |= IOP_NOFREE_OBJ; if (iop->fd == INVALID_HANDLE) { @@ -487,7 +488,7 @@ inrec(IOBUF *iop, int *errcode) else if ((iop->flag & IOP_CLOSED) != 0) cnt = EOF; else - cnt = get_a_record(&begin, iop, errcode); + cnt = get_a_record(& begin, iop, errcode); if (cnt == EOF) { retval = 1; @@ -518,7 +519,7 @@ remap_std_file(int oldfd) if (newfd == INVALID_HANDLE) newfd = open("/dev/null", O_RDWR); if (newfd >= 0) { - /* dup2() will close oldfd for us first. */ + /* if oldfd is open, dup2() will close oldfd for us first. */ ret = dup2(newfd, oldfd); if (ret == 0) close(newfd); @@ -561,7 +562,7 @@ iop_close(IOBUF *iop) ret = close(iop->fd); if (iop->close_func != NULL) - (*iop->close_func)(iop); + iop->close_func(iop); if (ret == -1) warning(_("close of fd %d (`%s') failed (%s)"), iop->fd, @@ -581,7 +582,7 @@ iop_close(IOBUF *iop) unref(fields_arr[0]); fields_arr[0] = t; /* - * 1/27/2003: This used to be here: + * This used to be here: * * reset_record(); * @@ -689,11 +690,11 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"), str, what); +#ifdef HAVE_SOCKETS /* - * XXX: Use /inet4 and /inet6 with plain /inet being whatever - * we get back from the system. + * Use /inet4 to force IPv4, /inet6 to force IPv6, and plain + * /inet will be whatever we get back from the system. */ -#ifdef HAVE_SOCKETS if (inetfile(str, & len, NULL)) { tflag |= RED_SOCKET; if (strncmp(str + len, "tcp/", 4) == 0) @@ -709,7 +710,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) * if at all possible. Messing with signal() for * SIGCLD leads to lots of headaches. However, if * we've gotten EOF from a child input pipeline, it's - * good bet that the child has died. So recover it. + * a good bet that the child has died. So recover it. */ if ((rp->flag & RED_EOF) && redirtype == redirect_pipein) { if (rp->pid != -1) @@ -759,7 +760,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) while (rp->fp == NULL && rp->iop == NULL) { if (! new_rp && rp->flag & RED_EOF) { /* - * encountered EOF on file or pipe -- must be cleared + * Encountered EOF on file or pipe -- must be cleared * by explicit close() before reading more */ save_rp = NULL; @@ -869,7 +870,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) /* too many files open -- close one and try again */ if (errno == EMFILE || errno == ENFILE) close_one(); -#if defined __MINGW32__ || defined __sun +#if defined __MINGW32__ else if (errno == 0) /* HACK! */ close_one(); #endif @@ -892,9 +893,8 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) */ if (errflg != NULL) *errflg = errno; - if (redirtype == redirect_output - || redirtype == redirect_append - ) { + if ( redirtype == redirect_output + || redirtype == redirect_append) { /* multiple messages make life easier for translators */ if (*direction == 'f') fatal(_("can't redirect from `%s' (%s)"), @@ -966,7 +966,7 @@ close_one() if ((rp->flag & (RED_FILE|RED_WRITE)) == (RED_FILE|RED_WRITE)) { rp->flag |= RED_USED; errno = 0; - if (/* do_lint && */ fclose(rp->fp) != 0) + if (fclose(rp->fp) != 0) warning(_("close of `%s' failed (%s)."), rp->value, strerror(errno)); rp->fp = NULL; @@ -1039,7 +1039,7 @@ do_close(int nargs) */ if (do_posix) { unref(tmp); - return make_number((AWKNUM) 0); + tmp = make_number((AWKNUM) 0); } return tmp; } @@ -1081,7 +1081,8 @@ close_rp(struct redirect *rp, two_way_close_type how) rp->iop = NULL; } - } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) { /* write to pipe */ + } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) { + /* write to pipe */ status = pclose(rp->fp); if ((BINMODE & 1) != 0) os_setbinmode(fileno(stdin), O_BINARY); @@ -1121,14 +1122,15 @@ close_redir(struct redirect *rp, int exitwarn, two_way_close_type how) status = close_rp(rp, how); - /* SVR4 awk checks and warns about status of close */ if (status != 0) { int save_errno = errno; char *s = strerror(save_errno); /* - * Too many people have complained about this. - * As of 2.15.6, it is now under lint control. + * BWK's awk, as far back as SVR4 (1989) would check + * and warn about the status of close. However, when + * we did this we got too many complaints, so we moved + * it to be under lint control. */ if (do_lint) { if ((rp->flag & RED_PIPE) != 0) @@ -1233,7 +1235,7 @@ close_io(int *stdio_problem) for (rp = red_head; rp != NULL; rp = next) { next = rp->next; /* - * close_redir() will print a message if needed + * close_redir() will print a message if needed. * if do_lint, warn about lack of explicit close */ if (close_redir(rp, do_lint, CLOSE_ALL)) @@ -1241,7 +1243,7 @@ close_io(int *stdio_problem) rp = NULL; } /* - * Some of the non-Unix os's have problems doing an fclose + * Some of the non-Unix os's have problems doing an fclose() * on stdout and stderr. Since we don't really need to close * them, we just flush them, and do that across the board. */ @@ -1311,34 +1313,34 @@ socketopen(int family, int type, const char *localpname, struct addrinfo *rres, *rres0; struct addrinfo rhints; - int lerror; - int rerror; + int lerror, rerror; int socket_fd = INVALID_HANDLE; int any_remote_host = (strcmp(remotehostname, "0") == 0); - memset (&lhints, '\0', sizeof (lhints)); + memset(& lhints, '\0', sizeof (lhints)); lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; lhints.ai_socktype = type; lhints.ai_family = family; - lerror = getaddrinfo (NULL, localpname, &lhints, &lres); + lerror = getaddrinfo(NULL, localpname, & lhints, & lres); if (lerror) { if (strcmp(localpname, "0") != 0) fatal(_("local port %s invalid in `/inet'"), localpname); lres0 = NULL; - lres = &lhints; + lres = & lhints; } else lres0 = lres; while (lres != NULL) { - memset (&rhints, '\0', sizeof (rhints)); + memset (& rhints, '\0', sizeof (rhints)); rhints.ai_flags = lhints.ai_flags; rhints.ai_socktype = lhints.ai_socktype; rhints.ai_family = lhints.ai_family; rhints.ai_protocol = lhints.ai_protocol; - rerror = getaddrinfo (any_remote_host ? NULL : remotehostname, remotepname, &rhints, &rres); + rerror = getaddrinfo(any_remote_host ? NULL : remotehostname, + remotepname, & rhints, & rres); if (rerror) { if (lres0 != NULL) freeaddrinfo(lres0); @@ -1362,7 +1364,8 @@ socketopen(int family, int type, const char *localpname, (char *) & on, sizeof(on)); #ifdef SO_LINGER linger.l_onoff = 1; - linger.l_linger = 30; /* linger for 30/100 second */ + /* linger for 30/100 second */ + linger.l_linger = 30; setsockopt(socket_fd, SOL_SOCKET, SO_LINGER, (char *) & linger, sizeof(linger)); #endif @@ -1378,12 +1381,12 @@ socketopen(int family, int type, const char *localpname, int clientsocket_fd = INVALID_HANDLE; struct sockaddr_storage remote_addr; - socklen_t namelen = sizeof (remote_addr); + socklen_t namelen = sizeof(remote_addr); if (listen(socket_fd, 1) >= 0 && (clientsocket_fd = accept(socket_fd, - (struct sockaddr *) &remote_addr, - &namelen)) >= 0) { + (struct sockaddr *) & remote_addr, + & namelen)) >= 0) { close(socket_fd); socket_fd = clientsocket_fd; break; @@ -1392,15 +1395,15 @@ socketopen(int family, int type, const char *localpname, #ifdef MSG_PEEK char buf[10]; struct sockaddr_storage remote_addr; - socklen_t readle; + socklen_t read_len; if (recvfrom(socket_fd, buf, 1, MSG_PEEK, (struct sockaddr *) & remote_addr, - & readle) >= 0 - && readle + & read_len) >= 0 + && read_len && connect(socket_fd, - (struct sockaddr *)& remote_addr, - readle) == 0) + (struct sockaddr *) & remote_addr, + read_len) == 0) break; #endif } @@ -1441,11 +1444,10 @@ devopen(const char *name, const char *mode) int len; int family; - flag = str2mode(mode); - if (strcmp(name, "-") == 0) return fileno(stdin); + flag = str2mode(mode); openfd = INVALID_HANDLE; if (do_traditional) @@ -1469,9 +1471,9 @@ devopen(const char *name, const char *mode) struct stat sbuf; cp += 3; - openfd = (int) strtoul(cp, &ptr, 10); + openfd = (int) strtoul(cp, & ptr, 10); if (openfd <= INVALID_HANDLE || ptr == cp - || fstat(openfd, &sbuf) < 0) + || fstat(openfd, & sbuf) < 0) openfd = INVALID_HANDLE; } /* do not set close-on-exec for inherited fd's */ @@ -1534,7 +1536,7 @@ devopen(const char *name, const char *mode) cp++; /* * The remote port ends the special file name. - * This means there already is a 0 at the end of the string. + * This means there already is a '\0' at the end of the string. * Therefore no need to patch any string ending. * * Here too, require a port, let them explicitly put 0 if @@ -1548,48 +1550,48 @@ devopen(const char *name, const char *mode) { #define DEFAULT_RETRIES 20 - static unsigned long def_retries = DEFAULT_RETRIES; - static int first_time = TRUE; - unsigned long retries = 0; - static long msleep = 1000; - - if (first_time) { - char *cp, *end; - unsigned long count = 0; - char *ms2; - - first_time = FALSE; - if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) { - count = strtoul(cp, &end, 10); - if (end != cp && count > 0) - def_retries = count; - } - - /* - * Env var is in milliseconds, paramter to usleep() - * is microseconds, make the conversion. Default is - * 1 millisecond. - */ - if ((ms2 = getenv("GAWK_MSEC_SLEEP")) != NULL) { - msleep = strtol(ms2, &end, 10); - if (end == ms2 || msleep < 0) - msleep = 1000; - else - msleep *= 1000; - } + static unsigned long def_retries = DEFAULT_RETRIES; + static int first_time = TRUE; + unsigned long retries = 0; + static long msleep = 1000; + + if (first_time) { + char *cp, *end; + unsigned long count = 0; + char *ms2; + + first_time = FALSE; + if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) { + count = strtoul(cp, & end, 10); + if (end != cp && count > 0) + def_retries = count; } - retries = def_retries; - do { - openfd = socketopen(family, protocol, localpname, cp, hostname); - retries--; - } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0); + /* + * Env var is in milliseconds, paramter to usleep() + * is microseconds, make the conversion. Default is + * 1 millisecond. + */ + if ((ms2 = getenv("GAWK_MSEC_SLEEP")) != NULL) { + msleep = strtol(ms2, & end, 10); + if (end == ms2 || msleep < 0) + msleep = 1000; + else + msleep *= 1000; + } } + retries = def_retries; - *localpnamelastcharp = '/'; - *hostnameslastcharp = '/'; + do { + openfd = socketopen(family, protocol, localpname, cp, hostname); + retries--; + } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0); + } + + *localpnamelastcharp = '/'; + *hostnameslastcharp = '/'; #else /* ! HAVE_SOCKETS */ - fatal(_("TCP/IP communications are not supported")); + fatal(_("TCP/IP communications are not supported")); #endif /* HAVE_SOCKETS */ } @@ -1601,8 +1603,8 @@ strictopen: /* on OS/2 directory access via open() is not permitted */ struct stat buf; - if (stat(name, &buf) == 0 && S_ISDIR(buf.st_mode)) - errno = EISDIR; + if (stat(name, & buf) == 0 && S_ISDIR(buf.st_mode)) + errno = EISDIR; } #endif if (openfd != INVALID_HANDLE) { @@ -1648,9 +1650,11 @@ two_way_open(const char *str, struct redirect *rp) fclose(rp->fp); return FALSE; } + os_close_on_exec(fd, str, "socket", "to/from"); os_close_on_exec(newfd, str, "socket", "to/from"); rp->iop = iop_alloc(newfd, str, NULL, TRUE); if (rp->iop == NULL) { + close(newfd); fclose(rp->fp); return FALSE; } @@ -1675,20 +1679,20 @@ two_way_open(const char *str, struct redirect *rp) pid_t pid; struct stat statb; struct termios st; - /* Use array of chars to avoid ascii / ebcdic issues */ + /* Use array of chars to avoid ASCII / EBCDIC issues */ static char pty_chars[] = "pqrstuvwxyzabcdefghijklmno"; int i; if (! initialized) { initialized = TRUE; #ifdef HAVE_GRANTPT - have_dev_ptmx = (stat("/dev/ptmx", &statb) >= 0); + have_dev_ptmx = (stat("/dev/ptmx", & statb) >= 0); #endif i = 0; do { c = pty_chars[i++]; sprintf(slavenam, "/dev/pty%c0", c); - if (stat(slavenam, &statb) >= 0) { + if (stat(slavenam, & statb) >= 0) { first_pty_letter = c; break; } @@ -1716,8 +1720,9 @@ two_way_open(const char *str, struct redirect *rp) if (first_pty_letter) { /* * Assume /dev/ptyXNN and /dev/ttyXN naming system. - * The FIRST_PTY_LETTER gives the first X to try. We try in the - * sequence FIRST_PTY_LETTER, .., 'z', 'a', .., FIRST_PTY_LETTER. + * The FIRST_PTY_LETTER gives the first X to try. + * We try in the sequence FIRST_PTY_LETTER, .., + * 'z', 'a', .., FIRST_PTY_LETTER. * Is this worthwhile, or just over-zealous? */ c = first_pty_letter; @@ -1727,7 +1732,7 @@ two_way_open(const char *str, struct redirect *rp) for (i = 0; i < 16; i++) { sprintf(slavenam, "/dev/pty%c%x", c, i); - if (stat(slavenam, &statb) < 0) { + if (stat(slavenam, & statb) < 0) { no_ptys = TRUE; /* bypass all this next time */ goto use_pipes; } @@ -1769,7 +1774,7 @@ two_way_open(const char *str, struct redirect *rp) ioctl(slave, I_PUSH, "ldterm"); #endif - tcgetattr(slave, &st); + tcgetattr(slave, & st); st.c_iflag &= ~(ISTRIP | IGNCR | INLCR | IXOFF); st.c_iflag |= (ICRNL | IGNPAR | BRKINT | IXON); st.c_oflag &= ~OPOST; @@ -1777,10 +1782,6 @@ two_way_open(const char *str, struct redirect *rp) st.c_cflag |= CREAD | CS8 | CLOCAL; st.c_lflag &= ~(ECHO | ECHOE | ECHOK | NOFLSH | TOSTOP); st.c_lflag |= ISIG; -#if 0 - st.c_cc[VMIN] = 1; - st.c_cc[VTIME] = 0; -#endif /* Set some control codes to default values */ #ifdef VINTR @@ -1798,9 +1799,9 @@ two_way_open(const char *str, struct redirect *rp) #ifdef VEOF st.c_cc[VEOF] = '\004'; /* ^d */ #endif - tcsetattr(slave, TCSANOW, &st); + tcsetattr(slave, TCSANOW, & st); - switch (pid = fork ()) { + switch (pid = fork()) { case 0: /* Child process */ setsid(); @@ -1840,9 +1841,9 @@ two_way_open(const char *str, struct redirect *rp) } /* parent */ - if (close(slave)) { + if (close(slave) != 0) { close(master); - (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */ + (void) kill(pid, SIGKILL); fatal(_("close of slave pty failed (%s)"), strerror(errno)); } @@ -1850,7 +1851,7 @@ two_way_open(const char *str, struct redirect *rp) rp->iop = iop_alloc(master, str, NULL, TRUE); if (rp->iop == NULL) { (void) close(master); - (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */ + (void) kill(pid, SIGKILL); return FALSE; } @@ -1863,7 +1864,7 @@ two_way_open(const char *str, struct redirect *rp) iop_close(rp->iop); rp->iop = NULL; (void) close(master); - (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */ + (void) kill(pid, SIGKILL); if (dup_master > 0) (void) close(dup_master); return FALSE; @@ -1903,7 +1904,7 @@ use_pipes: save_stdout = dup(1); /* duplicate stdout */ if (save_stdout == -1 || save_stdin == -1) { - /* if an error occurrs close all open file handles */ + /* if an error occurs close all open file handles */ save_errno = errno; if (save_stdin != -1) close(save_stdin); @@ -2006,7 +2007,7 @@ use_pipes: (void) close(ctop[1]); (void) close(ptoc[0]); (void) close(ptoc[1]); - (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */ + (void) kill(pid, SIGKILL); return FALSE; } @@ -2018,7 +2019,7 @@ use_pipes: (void) close(ctop[1]); (void) close(ptoc[0]); (void) close(ptoc[1]); - (void) kill(pid, SIGKILL); /* overkill? (pardon pun) */ + (void) kill(pid, SIGKILL); return FALSE; } @@ -2060,9 +2061,9 @@ wait_any(int interesting) /* pid of interest, if any */ qstat = signal(SIGQUIT, SIG_IGN); for (;;) { #ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */ - pid = wait(&status); + pid = wait(& status); #else - pid = wait((union wait *)&status); + pid = wait((union wait *) & status); #endif if (interesting && pid == interesting) { break; @@ -2095,27 +2096,31 @@ gawk_popen(const char *cmd, struct redirect *rp) #endif /* - * used to wait for any children to synchronize input and output, + * We used to wait for any children to synchronize input and output, * but this could cause gawk to hang when it is started in a pipeline - * and thus has a child process feeding it input (shell dependent) + * and thus has a child process feeding it input (shell dependent). + * + * (void) wait_any(0); // wait for outstanding processes */ - /*(void) wait_any(0);*/ /* wait for outstanding processes */ if (pipe(p) < 0) fatal(_("cannot open pipe `%s' (%s)"), cmd, strerror(errno)); #ifdef __EMX__ - save_stdout = dup(1); /* save stdout */ rp->iop = NULL; + save_stdout = dup(1); /* save stdout */ if (save_stdout == -1) { - close(p[0]); close(p[1]); - return rp->iop; /* failed */ + close(p[0]); + close(p[1]); + return NULL; /* failed */ } close(1); /* close stdout */ if (dup(p[1]) != 1) { - close(p[0]); close(p[1]); - fatal(_("moving pipe to stdout in child failed (dup: %s)"), strerror(errno)); + close(p[0]); + close(p[1]); + fatal(_("moving pipe to stdout in child failed (dup: %s)"), + strerror(errno)); } /* none of these handles must be inherited by the child process */ @@ -2236,7 +2241,7 @@ gawk_pclose(struct redirect *rp) /* do_getline --- read in a line, into var and with redirection */ NODE * -do_getline_redir(int intovar, int redirtype) +do_getline_redir(int into_variable, enum redirval redirtype) { struct redirect *rp = NULL; IOBUF *iop; @@ -2247,12 +2252,12 @@ do_getline_redir(int intovar, int redirtype) NODE **lhs = NULL; int redir_error = 0; - if (intovar) + if (into_variable) lhs = POP_ADDRESS(); - assert(redirtype != 0); + assert(redirtype != redirect_none); redir_exp = TOP(); - rp = redirect(redir_exp, redirtype, &redir_error); + rp = redirect(redir_exp, redirtype, & redir_error); DEREF(redir_exp); decr_sp(); if (rp == NULL) { @@ -2267,9 +2272,9 @@ do_getline_redir(int intovar, int redirtype) return make_number((AWKNUM) 0.0); errcode = 0; - cnt = get_a_record(&s, iop, &errcode); + cnt = get_a_record(& s, iop, & errcode); if (errcode != 0) { - if (! do_traditional && (errcode != -1)) + if (! do_traditional && errcode != -1) update_ERRNO_saved(errcode); return make_number((AWKNUM) -1.0); } @@ -2302,24 +2307,24 @@ do_getline_redir(int intovar, int redirtype) /* do_getline --- read in a line, into var and without redirection */ NODE * -do_getline(int intovar, IOBUF *iop) +do_getline(int into_variable, IOBUF *iop) { int cnt = EOF; char *s = NULL; int errcode; if (iop == NULL) { /* end of input */ - if (intovar) + if (into_variable) (void) POP_ADDRESS(); return make_number((AWKNUM) 0.0); } errcode = 0; - cnt = get_a_record(&s, iop, &errcode); + cnt = get_a_record(& s, iop, & errcode); if (errcode != 0) { - if (! do_traditional && (errcode != -1)) + if (! do_traditional && errcode != -1) update_ERRNO_saved(errcode); - if (intovar) + if (into_variable) (void) POP_ADDRESS(); return make_number((AWKNUM) -1.0); } @@ -2329,7 +2334,7 @@ do_getline(int intovar, IOBUF *iop) INCREMENT_REC(NR); INCREMENT_REC(FNR); - if (! intovar) /* no optional var. */ + if (! into_variable) /* no optional var. */ set_record(s, cnt); else { /* assignment to variable */ NODE **lhs; @@ -2382,7 +2387,7 @@ init_awkpath(char *path) memcpy(p, start, len); /* add directory punctuation if necessary */ - if (! isdirpunct(*(end - 1))) + if (! isdirpunct(end[-1])) p[len++] = '/'; p[len] = '\0'; @@ -2556,23 +2561,12 @@ int srcopen(SRCFILE *s) { if (s->stype == SRC_STDIN) - return (0); + return fileno(stdin); if (s->stype == SRC_FILE || s->stype == SRC_INC) return devopen(s->fullpath, "r"); return INVALID_HANDLE; } -#ifdef TEST -int bufsize = 8192; - -void -fatal(const char *s) -{ - printf("%s\n", s); - exit(EXIT_FAILURE); -} -#endif - /* open hooks, mainly for use by extension functions */ static struct open_hook { @@ -2659,12 +2653,12 @@ iop_alloc(int fd, const char *name, IOBUF *iop, int do_openhooks) (void)(! do_traditional && (unref(RT_node->var_value), \ RT_node->var_value = make_string(str, len))) -/* grow must increase size of buffer, set end, make sure off and dataend point at */ -/* right spot. */ -/* */ -/* */ -/* = */ -/* grow_iop_buffer --- grow the buffer */ +/* + * grow_iop_buffer: + * + * grow must increase size of buffer, set end, make sure off and dataend + * point at the right spot. + */ static void grow_iop_buffer(IOBUF *iop) @@ -2698,10 +2692,8 @@ grow_iop_buffer(IOBUF *iop) iop->end = iop->buf + iop->size; } -/* Here are the routines. */ -/* */ -/* */ -/* = */ +/* Here are the routines. */ + /* rs1scan --- scan for a single character record terminator */ static RECVALUE @@ -2782,19 +2774,19 @@ rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) int len = iop->dataend - bp; int found = 0; - memset(&mbs, 0, sizeof(mbstate_t)); + memset(& mbs, 0, sizeof(mbstate_t)); do { if (*bp == rs) found = 1; if (is_valid_character(*bp)) mbclen = 1; else - mbclen = mbrlen(bp, len, &mbs); - if ( (mbclen == 1) - || (mbclen == (size_t) -1) - || (mbclen == (size_t) -2) - || (mbclen == 0)) { - /* We treat it as a singlebyte character. */ + mbclen = mbrlen(bp, len, & mbs); + if ( mbclen == 1 + || mbclen == (size_t) -1 + || mbclen == (size_t) -2 + || mbclen == 0) { + /* We treat it as a single-byte character. */ mbclen = 1; } len -= mbclen; @@ -2804,8 +2796,8 @@ rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) /* Check that newline found isn't the sentinel. */ if (found && (bp - mbclen) < iop->dataend) { /* - * set len to what we have so far, in case this is - * all there is + * Set len to what we have so far, in case this is + * all there is. */ recm->len = bp - recm->start - mbclen; recm->rt_start = bp - mbclen; @@ -2839,7 +2831,6 @@ rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) } } -/* = */ /* rsrescan --- search for a regex match in the buffer */ static RECVALUE @@ -2929,21 +2920,15 @@ again: * This matches the "xyz" and ends up putting the * "abc" into the front of the next record. Ooops. * - * The remaybelong() function looks to see if the + * The re->maybe_long member is true if the * regex contains one of: + * ? |. This is a very * simple heuristic, but in combination with the * "end of match within a few bytes of end of buffer" * check, should keep things reasonable. */ - /* - * XXX: The reisstring and remaybelong tests should - * really be done once when RS is assigned to and - * then tested as flags here. Maybe one day. - */ - /* succession of tests is easier to trace in GDB. */ - if (remaybelong(RS->stptr, RS->stlen)) { + if (RSre->maybe_long) { char *matchend = iop->off + reend; if (iop->dataend - matchend < RS->stlen) @@ -2953,7 +2938,6 @@ again: return REC_OK; } -/* = */ /* rsnullscan --- handle RS = "" */ static RECVALUE @@ -3030,7 +3014,6 @@ find_longest_terminator: return REC_OK; } -/* = */ /* get_a_record --- read a record from IOP into out, return length of EOF, set RT */ static int @@ -3052,9 +3035,9 @@ get_a_record(char **out, /* pointer to pointer to data */ read_timeout = get_read_timeout(iop); if (iop->get_record != NULL) - return (*iop->get_record)(out, iop, errcode); + return iop->get_record(out, iop, errcode); - /* = */ + /* fill initial buffer */ if (has_no_data(iop) || no_data_left(iop)) { iop->count = iop->read_func(iop->fd, iop->buf, iop->readsize); if (iop->count == 0) { @@ -3071,10 +3054,12 @@ get_a_record(char **out, /* pointer to pointer to data */ } } - /* = */ + /* loop through file to find a record */ state = NOSTATE; for (;;) { size_t dataend_off; + size_t room_left; + size_t amt_to_read; ret = (*matchrec)(iop, & recm, & state); iop->flag &= ~IOP_AT_START; @@ -3082,64 +3067,62 @@ get_a_record(char **out, /* pointer to pointer to data */ break; /* need to add more data to buffer */ - /* = */ + /* shift data down in buffer */ dataend_off = iop->dataend - iop->off; memmove(iop->buf, iop->off, dataend_off); iop->off = iop->buf; iop->dataend = iop->buf + dataend_off; - /* = */ + /* adjust recm contents */ recm.start = iop->off; if (recm.rt_start != NULL) recm.rt_start = iop->off + recm.len; - /* = */ - { + /* read more data, break if EOF */ #define min(x, y) (x < y ? x : y) - /* subtract one in read count to leave room for sentinel */ - size_t room_left = iop->end - iop->dataend - 1; - size_t amt_to_read = min(iop->readsize, room_left); - - if (amt_to_read < iop->readsize) { - grow_iop_buffer(iop); - /* = */ - recm.start = iop->off; - if (recm.rt_start != NULL) - recm.rt_start = iop->off + recm.len; - - /* recalculate amt_to_read */ - room_left = iop->end - iop->dataend - 1; - amt_to_read = min(iop->readsize, room_left); - } - while (amt_to_read + iop->readsize < room_left) - amt_to_read += iop->readsize; + /* subtract one in read count to leave room for sentinel */ + room_left = iop->end - iop->dataend - 1; + amt_to_read = min(iop->readsize, room_left); + + if (amt_to_read < iop->readsize) { + grow_iop_buffer(iop); + /* adjust recm contents */ + recm.start = iop->off; + if (recm.rt_start != NULL) + recm.rt_start = iop->off + recm.len; + + /* recalculate amt_to_read */ + room_left = iop->end - iop->dataend - 1; + amt_to_read = min(iop->readsize, room_left); + } + while (amt_to_read + iop->readsize < room_left) + amt_to_read += iop->readsize; #ifdef SSIZE_MAX - /* - * POSIX limits read to SSIZE_MAX. There are (bizarre) - * systems where this amount is small. - */ - amt_to_read = min(amt_to_read, SSIZE_MAX); + /* + * POSIX limits read to SSIZE_MAX. There are (bizarre) + * systems where this amount is small. + */ + amt_to_read = min(amt_to_read, SSIZE_MAX); #endif - iop->count = iop->read_func(iop->fd, iop->dataend, amt_to_read); - if (iop->count == -1) { - *errcode = errno; - iop->flag |= IOP_AT_EOF; - break; - } else if (iop->count == 0) { - /* - * hit EOF before matching RS, so end - * the record and set RT to "" - */ - iop->flag |= IOP_AT_EOF; - break; - } else - iop->dataend += iop->count; - } + iop->count = iop->read_func(iop->fd, iop->dataend, amt_to_read); + if (iop->count == -1) { + *errcode = errno; + iop->flag |= IOP_AT_EOF; + break; + } else if (iop->count == 0) { + /* + * hit EOF before matching RS, so end + * the record and set RT to "" + */ + iop->flag |= IOP_AT_EOF; + break; + } else + iop->dataend += iop->count; } - /* = */ + /* set record, RT, return right value */ /* * rtval is not a static pointer to avoid dangling pointer problems -- cgit v1.2.3 From e5353c0f447a8628985722296f57fc02dd2e0063 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 11 May 2012 15:05:35 +0300 Subject: Move to use of bool type, true, false, everywhere. --- io.c | 146 +++++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 73 insertions(+), 73 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 6c5d990b..1e8870ec 100644 --- a/io.c +++ b/io.c @@ -198,12 +198,12 @@ struct recmatch { static int iop_close(IOBUF *iop); struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg); static void close_one(void); -static int close_redir(struct redirect *rp, int exitwarn, two_way_close_type how); +static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how); #ifndef PIPES_SIMULATED static int wait_any(int interesting); #endif static IOBUF *gawk_popen(const char *cmd, struct redirect *rp); -static IOBUF *iop_alloc(int fd, const char *name, IOBUF *buf, int do_openhooks); +static IOBUF *iop_alloc(int fd, const char *name, IOBUF *buf, bool do_openhooks); static int gawk_pclose(struct redirect *rp); static int str2mode(const char *mode); static int two_way_open(const char *str, struct redirect *rp); @@ -225,7 +225,7 @@ static NODE *in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx); static long get_read_timeout(IOBUF *iop); static ssize_t read_with_timeout(int fd, char *buf, size_t size); -static int read_can_timeout = FALSE; +static bool read_can_timeout = false; static long read_timeout; static long read_default_timeout; @@ -235,7 +235,7 @@ static Regexp *RS_re_yes_case; /* regexp for RS when ignoring case */ static Regexp *RS_re_no_case; /* regexp for RS when not ignoring case */ static Regexp *RS_regexp; -int RS_is_null; +bool RS_is_null; extern NODE *ARGC_node; extern NODE *ARGV_node; @@ -258,7 +258,7 @@ init_io() tmout = getenv_long("GAWK_READ_TIMEOUT"); if (tmout > 0) { read_default_timeout = tmout; - read_can_timeout = TRUE; + read_can_timeout = true; } /* @@ -266,7 +266,7 @@ init_io() * We can't be any more specific than this. */ if (PROCINFO_node != NULL) - read_can_timeout = TRUE; + read_can_timeout = true; } @@ -342,10 +342,10 @@ after_beginfile(IOBUF **curfile) /* nextfile --- move to the next input data file */ int -nextfile(IOBUF **curfile, int skipping) +nextfile(IOBUF **curfile, bool skipping) { static long i = 1; - static int files = FALSE; + static bool files = false; NODE *arg, *tmp; static IOBUF mybuf; const char *fname; @@ -390,8 +390,8 @@ nextfile(IOBUF **curfile, int skipping) ARGIND_node->var_value = make_number((AWKNUM) i); } - if (! arg_assign(arg->stptr, FALSE)) { - files = TRUE; + if (! arg_assign(arg->stptr, false)) { + files = true; fname = arg->stptr; errno = 0; fd = devopen(fname, binmode("r")); @@ -406,7 +406,7 @@ nextfile(IOBUF **curfile, int skipping) mpz_set_ui(MFNR, 0); #endif FNR = 0; - iop = *curfile = iop_alloc(fd, fname, & mybuf, FALSE); + iop = *curfile = iop_alloc(fd, fname, & mybuf, false); if (fd == INVALID_HANDLE) iop->errcode = errcode; else @@ -416,8 +416,8 @@ nextfile(IOBUF **curfile, int skipping) } } - if (files == FALSE) { - files = TRUE; + if (files == false) { + files = true; /* no args. -- use stdin */ /* FNR is init'ed to 0 */ errno = 0; @@ -427,7 +427,7 @@ nextfile(IOBUF **curfile, int skipping) FILENAME_node->var_value = make_string("-", 1); FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */ fname = "-"; - iop = *curfile = iop_alloc(fileno(stdin), fname, & mybuf, FALSE); + iop = *curfile = iop_alloc(fileno(stdin), fname, & mybuf, false); iop->flag |= IOP_NOFREE_OBJ; if (iop->fd == INVALID_HANDLE) { @@ -636,7 +636,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) const char *mode; int fd; const char *what = NULL; - int new_rp = FALSE; + bool new_rp = false; int len; /* used with /inet */ static struct redirect *save_rp = NULL; /* hold onto rp that should * be freed for reuse @@ -739,7 +739,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) } if (rp == NULL) { - new_rp = TRUE; + new_rp = true; if (save_rp != NULL) { rp = save_rp; efree(rp->value); @@ -805,7 +805,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) /* do not free rp, saving it for reuse (save_rp = rp) */ return NULL; } - rp->iop = iop_alloc(fd, str, NULL, TRUE); + rp->iop = iop_alloc(fd, str, NULL, true); break; case redirect_twoway: direction = "to/from"; @@ -948,10 +948,10 @@ close_one() struct redirect *rp; struct redirect *rplast = NULL; - static short warned = FALSE; + static bool warned = false; if (do_lint && ! warned) { - warned = TRUE; + warned = true; lintwarn(_("reached system limit for open files: starting to multiplex file descriptors")); } @@ -1029,7 +1029,7 @@ do_close(int nargs) } DEREF(tmp); fflush(stdout); /* synchronize regular output */ - tmp = make_number((AWKNUM) close_redir(rp, FALSE, how)); + tmp = make_number((AWKNUM) close_redir(rp, false, how)); rp = NULL; /* * POSIX says close() returns 0 on success, non-zero otherwise. @@ -1107,7 +1107,7 @@ close_rp(struct redirect *rp, two_way_close_type how) /* close_redir --- close an open file or pipe */ static int -close_redir(struct redirect *rp, int exitwarn, two_way_close_type how) +close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how) { int status = 0; @@ -1225,7 +1225,7 @@ flush_io() /* close_io --- close all open files, called when exiting */ int -close_io(int *stdio_problem) +close_io(bool *stdio_problem) { struct redirect *rp; struct redirect *next; @@ -1247,16 +1247,16 @@ close_io(int *stdio_problem) * on stdout and stderr. Since we don't really need to close * them, we just flush them, and do that across the board. */ - *stdio_problem = FALSE; + *stdio_problem = false; if (fflush(stdout)) { warning(_("error writing standard output (%s)"), strerror(errno)); status++; - *stdio_problem = TRUE; + *stdio_problem = true; } if (fflush(stderr)) { warning(_("error writing standard error (%s)"), strerror(errno)); status++; - *stdio_problem = TRUE; + *stdio_problem = true; } return status; } @@ -1551,7 +1551,7 @@ devopen(const char *name, const char *mode) { #define DEFAULT_RETRIES 20 static unsigned long def_retries = DEFAULT_RETRIES; - static int first_time = TRUE; + static bool first_time = true; unsigned long retries = 0; static long msleep = 1000; @@ -1560,7 +1560,7 @@ devopen(const char *name, const char *mode) unsigned long count = 0; char *ms2; - first_time = FALSE; + first_time = false; if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) { count = strtoul(cp, & end, 10); if (end != cp && count > 0) @@ -1630,7 +1630,7 @@ strictopen: static int two_way_open(const char *str, struct redirect *rp) { - static int no_ptys = FALSE; + static bool no_ptys = false; #ifdef HAVE_SOCKETS /* case 1: socket */ @@ -1639,34 +1639,34 @@ two_way_open(const char *str, struct redirect *rp) fd = devopen(str, "rw"); if (fd == INVALID_HANDLE) - return FALSE; + return false; rp->fp = fdopen(fd, "w"); if (rp->fp == NULL) { close(fd); - return FALSE; + return false; } newfd = dup(fd); if (newfd < 0) { fclose(rp->fp); - return FALSE; + return false; } os_close_on_exec(fd, str, "socket", "to/from"); os_close_on_exec(newfd, str, "socket", "to/from"); - rp->iop = iop_alloc(newfd, str, NULL, TRUE); + rp->iop = iop_alloc(newfd, str, NULL, true); if (rp->iop == NULL) { close(newfd); fclose(rp->fp); - return FALSE; + return false; } rp->flag |= RED_SOCKET; - return TRUE; + return true; } #endif /* HAVE_SOCKETS */ #if defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS) /* case 2: use ptys for two-way communications to child */ if (! no_ptys && pty_vs_pipe(str)) { - static int initialized = FALSE; + static bool initialized = false; static char first_pty_letter; #ifdef HAVE_GRANTPT static int have_dev_ptmx; @@ -1684,7 +1684,7 @@ two_way_open(const char *str, struct redirect *rp) int i; if (! initialized) { - initialized = TRUE; + initialized = true; #ifdef HAVE_GRANTPT have_dev_ptmx = (stat("/dev/ptmx", & statb) >= 0); #endif @@ -1733,7 +1733,7 @@ two_way_open(const char *str, struct redirect *rp) for (i = 0; i < 16; i++) { sprintf(slavenam, "/dev/pty%c%x", c, i); if (stat(slavenam, & statb) < 0) { - no_ptys = TRUE; /* bypass all this next time */ + no_ptys = true; /* bypass all this next time */ goto use_pipes; } @@ -1753,7 +1753,7 @@ two_way_open(const char *str, struct redirect *rp) c = *cp; } while (c != first_pty_letter); } else - no_ptys = TRUE; + no_ptys = true; /* Couldn't find a pty. Fall back to using pipes. */ goto use_pipes; @@ -1836,7 +1836,7 @@ two_way_open(const char *str, struct redirect *rp) save_errno = errno; close(master); errno = save_errno; - return FALSE; + return false; } @@ -1848,11 +1848,11 @@ two_way_open(const char *str, struct redirect *rp) } rp->pid = pid; - rp->iop = iop_alloc(master, str, NULL, TRUE); + rp->iop = iop_alloc(master, str, NULL, true); if (rp->iop == NULL) { (void) close(master); (void) kill(pid, SIGKILL); - return FALSE; + return false; } /* @@ -1867,13 +1867,13 @@ two_way_open(const char *str, struct redirect *rp) (void) kill(pid, SIGKILL); if (dup_master > 0) (void) close(dup_master); - return FALSE; + return false; } rp->flag |= RED_PTY; os_close_on_exec(master, str, "pipe", "from"); os_close_on_exec(dup_master, str, "pipe", "to"); first_pty_letter = '\0'; /* reset for next command */ - return TRUE; + return true; } #endif /* defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS) */ @@ -1889,14 +1889,14 @@ use_pipes: #endif if (pipe(ptoc) < 0) - return FALSE; /* errno set, diagnostic from caller */ + return false; /* errno set, diagnostic from caller */ if (pipe(ctop) < 0) { save_errno = errno; close(ptoc[0]); close(ptoc[1]); errno = save_errno; - return FALSE; + return false; } #ifdef __EMX__ @@ -1913,7 +1913,7 @@ use_pipes: close(ptoc[0]); close(ptoc[1]); close(ctop[0]); close(ctop[1]); errno = save_errno; - return FALSE; + return false; } /* connect pipes to stdin and stdout */ @@ -1967,7 +1967,7 @@ use_pipes: close(ctop[0]); errno = save_errno; - return FALSE; + return false; } #else /* NOT __EMX__ */ @@ -1976,7 +1976,7 @@ use_pipes: close(ptoc[0]); close(ptoc[1]); close(ctop[0]); close(ctop[1]); errno = save_errno; - return FALSE; + return false; } if (pid == 0) { /* child */ @@ -2001,7 +2001,7 @@ use_pipes: /* parent */ rp->pid = pid; - rp->iop = iop_alloc(ctop[0], str, NULL, TRUE); + rp->iop = iop_alloc(ctop[0], str, NULL, true); if (rp->iop == NULL) { (void) close(ctop[0]); (void) close(ctop[1]); @@ -2009,7 +2009,7 @@ use_pipes: (void) close(ptoc[1]); (void) kill(pid, SIGKILL); - return FALSE; + return false; } rp->fp = fdopen(ptoc[1], "w"); if (rp->fp == NULL) { @@ -2021,7 +2021,7 @@ use_pipes: (void) close(ptoc[1]); (void) kill(pid, SIGKILL); - return FALSE; + return false; } #ifndef __EMX__ @@ -2032,14 +2032,14 @@ use_pipes: (void) close(ctop[1]); #endif - return TRUE; + return true; } #else /*PIPES_SIMULATED*/ fatal(_("`|&' not supported")); /*NOTREACHED*/ - return FALSE; + return false; #endif } @@ -2165,7 +2165,7 @@ gawk_popen(const char *cmd, struct redirect *rp) } #endif os_close_on_exec(p[0], cmd, "pipe", "from"); - rp->iop = iop_alloc(p[0], cmd, NULL, TRUE); + rp->iop = iop_alloc(p[0], cmd, NULL, true); if (rp->iop == NULL) (void) close(p[0]); @@ -2210,7 +2210,7 @@ gawk_popen(const char *cmd, struct redirect *rp) if (current == NULL) return NULL; os_close_on_exec(fileno(current), cmd, "pipe", "from"); - rp->iop = iop_alloc(fileno(current), cmd, NULL, TRUE); + rp->iop = iop_alloc(fileno(current), cmd, NULL, true); if (rp->iop == NULL) { (void) pclose(current); current = NULL; @@ -2357,13 +2357,13 @@ typedef struct { static path_info pi_awkpath = { /* envname */ "AWKPATH", /* dfltp */ & defpath, - /* try_cwd */ TRUE, + /* try_cwd */ true, }; static path_info pi_awklibpath = { /* envname */ "AWKLIBPATH", /* dfltp */ & deflibpath, - /* try_cwd */ FALSE, + /* try_cwd */ false, }; /* init_awkpath --- split path(=$AWKPATH) into components */ @@ -2431,7 +2431,7 @@ get_cwd () size_t bsize = BSIZE; emalloc(buf, char *, bsize * sizeof(char), "get_cwd"); - while (TRUE) { + while (true) { if (getcwd(buf, bsize) == buf) return buf; if (errno != ERANGE) { @@ -2614,14 +2614,14 @@ find_open_hook(IOBUF *iop) /* iop_alloc --- allocate an IOBUF structure for an open fd */ static IOBUF * -iop_alloc(int fd, const char *name, IOBUF *iop, int do_openhooks) +iop_alloc(int fd, const char *name, IOBUF *iop, bool do_openhooks) { struct stat sbuf; - int iop_malloced = FALSE; + bool iop_malloced = false; if (iop == NULL) { emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc"); - iop_malloced = TRUE; + iop_malloced = true; } memset(iop, '\0', sizeof(IOBUF)); iop->fd = fd; @@ -3219,7 +3219,7 @@ set_RS() } unref(save_rs); save_rs = dupnode(RS_node->var_value); - RS_is_null = FALSE; + RS_is_null = false; RS = force_string(RS_node->var_value); /* * used to be if (RS_regexp != NULL) { refree(..); refree(..); ...; }. @@ -3231,20 +3231,20 @@ set_RS() RS_re_yes_case = RS_re_no_case = RS_regexp = NULL; if (RS->stlen == 0) { - RS_is_null = TRUE; + RS_is_null = true; matchrec = rsnullscan; } else if (RS->stlen > 1) { - static short warned = FALSE; + static bool warned = false; - RS_re_yes_case = make_regexp(RS->stptr, RS->stlen, FALSE, TRUE, TRUE); - RS_re_no_case = make_regexp(RS->stptr, RS->stlen, TRUE, TRUE, TRUE); + RS_re_yes_case = make_regexp(RS->stptr, RS->stlen, false, true, true); + RS_re_no_case = make_regexp(RS->stptr, RS->stlen, true, true, true); RS_regexp = (IGNORECASE ? RS_re_no_case : RS_re_yes_case); matchrec = rsrescan; if (do_lint && ! warned) { lintwarn(_("multicharacter value of `RS' is a gawk extension")); - warned = TRUE; + warned = true; } } else matchrec = rs1scan; @@ -3267,7 +3267,7 @@ pty_vs_pipe(const char *command) NODE *val; if (PROCINFO_node == NULL) - return FALSE; + return false; val = in_PROCINFO(command, "pty", NULL); if (val) { if (val->flags & MAYBE_NUM) @@ -3278,7 +3278,7 @@ pty_vs_pipe(const char *command) return (val->stlen != 0); } #endif /* HAVE_TERMIOS_H */ - return FALSE; + return false; } /* iopflags2str --- make IOP flags printable */ @@ -3312,22 +3312,22 @@ free_rp(struct redirect *rp) static int inetfile(const char *str, int *length, int *family) { - int ret = FALSE; + bool ret = false; if (strncmp(str, "/inet/", 6) == 0) { - ret = TRUE; + ret = true; if (length != NULL) *length = 6; if (family != NULL) *family = AF_UNSPEC; } else if (strncmp(str, "/inet4/", 7) == 0) { - ret = TRUE; + ret = true; if (length != NULL) *length = 7; if (family != NULL) *family = AF_INET; } else if (strncmp(str, "/inet6/", 7) == 0) { - ret = TRUE; + ret = true; if (length != NULL) *length = 7; if (family != NULL) -- cgit v1.2.3 From cdf892a07fa67c635997e41ee8fe175aaafb2431 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sat, 19 May 2012 23:45:07 -0400 Subject: Add -i option, append .awk if initial search fails, and allow -f repeats. --- io.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index 1e8870ec..a9fb3455 100644 --- a/io.c +++ b/io.c @@ -2538,6 +2538,14 @@ find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) #undef EXTLIB_SUFFIX } +/* + * Try searching with .awk appended if the platform headers have not specified + * another suffix. + */ +#ifndef DEFAULT_FILETYPE +#define DEFAULT_FILETYPE ".awk" +#endif + #ifdef DEFAULT_FILETYPE if (! do_traditional && path == NULL) { char *file_awk; -- cgit v1.2.3 From 6139211362667682c3022a72321e0cd8945b6592 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 24 Jun 2012 18:43:49 -0400 Subject: Hide private parts of IOBUF from extensions. --- io.c | 66 +++++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index a9fb3455..ab204e09 100644 --- a/io.c +++ b/io.c @@ -312,11 +312,11 @@ after_beginfile(IOBUF **curfile) iop = *curfile; assert(iop != NULL); - if (iop->fd == INVALID_HANDLE) { + if (iop->public.fd == INVALID_HANDLE) { const char *fname; int errcode; - fname = iop->name; + fname = iop->public.name; errcode = iop->errcode; iop->errcode = 0; errno = 0; @@ -366,7 +366,7 @@ nextfile(IOBUF **curfile, bool skipping) if (iop != NULL) { if (at_eof(iop)) { - assert(iop->fd != INVALID_HANDLE); + assert(iop->public.fd != INVALID_HANDLE); (void) iop_close(iop); *curfile = NULL; return 1; /* run endfile block */ @@ -430,7 +430,7 @@ nextfile(IOBUF **curfile, bool skipping) iop = *curfile = iop_alloc(fileno(stdin), fname, & mybuf, false); iop->flag |= IOP_NOFREE_OBJ; - if (iop->fd == INVALID_HANDLE) { + if (iop->public.fd == INVALID_HANDLE) { errcode = errno; errno = 0; update_ERRNO_int(errno); @@ -539,7 +539,7 @@ iop_close(IOBUF *iop) if (iop == NULL) return 0; - if (iop->fd == INVALID_HANDLE) { /* from nextfile(...) above */ + if (iop->public.fd == INVALID_HANDLE) { /* from nextfile(...) above */ assert(iop->buf == NULL); assert((iop->flag & IOP_NOFREE_OBJ) != 0); return 0; @@ -555,19 +555,19 @@ iop_close(IOBUF *iop) * So we remap the standard file to /dev/null. * Thanks to Jim Meyering for the suggestion. */ - if (iop->fd == fileno(stdin) - || iop->fd == fileno(stdout) - || iop->fd == fileno(stderr)) - ret = remap_std_file(iop->fd); + if (iop->public.fd == fileno(stdin) + || iop->public.fd == fileno(stdout) + || iop->public.fd == fileno(stderr)) + ret = remap_std_file(iop->public.fd); else - ret = close(iop->fd); + ret = close(iop->public.fd); - if (iop->close_func != NULL) - iop->close_func(iop); + if (iop->public.close_func != NULL) + iop->public.close_func(&iop->public); if (ret == -1) - warning(_("close of fd %d (`%s') failed (%s)"), iop->fd, - iop->name, strerror(errno)); + warning(_("close of fd %d (`%s') failed (%s)"), iop->public.fd, + iop->public.name, strerror(errno)); /* * Be careful -- $0 may still reference the buffer even though * an explicit close is being done; in the future, maybe we @@ -1073,7 +1073,7 @@ close_rp(struct redirect *rp, two_way_close_type how) if ((rp->flag & RED_SOCKET) != 0 && rp->iop != NULL) { #ifdef HAVE_SOCKETS if ((rp->flag & RED_TCP) != 0) - (void) shutdown(rp->iop->fd, SHUT_RD); + (void) shutdown(rp->iop->public.fd, SHUT_RD); #endif /* HAVE_SOCKETS */ (void) iop_close(rp->iop); } else @@ -2224,10 +2224,10 @@ gawk_popen(const char *cmd, struct redirect *rp) static int gawk_pclose(struct redirect *rp) { - int rval, aval, fd = rp->iop->fd; + int rval, aval, fd = rp->iop->public.fd; if (rp->iop != NULL) { - rp->iop->fd = dup(fd); /* kludge to allow close() + pclose() */ + rp->iop->public.fd = dup(fd); /* kludge to allow close() + pclose() */ rval = iop_close(rp->iop); } rp->iop = NULL; @@ -2589,13 +2589,13 @@ srcopen(SRCFILE *s) static struct open_hook { struct open_hook *next; - void *(*open_func)(IOBUF *); + void *(*open_func)(IOBUF_PUBLIC *); } *open_hooks; /* register_open_hook --- add an open hook to the list */ void -register_open_hook(void *(*open_func)(IOBUF *)) +register_open_hook(void *(*open_func)(IOBUF_PUBLIC *)) { struct open_hook *oh; @@ -2614,7 +2614,7 @@ find_open_hook(IOBUF *iop) /* walk through open hooks, stop at first one that responds */ for (oh = open_hooks; oh != NULL; oh = oh->next) { - if ((iop->opaque = (*oh->open_func)(iop)) != NULL) + if ((iop->public.opaque = (*oh->open_func)(&iop->public)) != NULL) break; } } @@ -2632,24 +2632,24 @@ iop_alloc(int fd, const char *name, IOBUF *iop, bool do_openhooks) iop_malloced = true; } memset(iop, '\0', sizeof(IOBUF)); - iop->fd = fd; - iop->name = name; + iop->public.fd = fd; + iop->public.name = name; iop->read_func = ( ssize_t(*)() ) read; if (do_openhooks) { find_open_hook(iop); /* tried to find open hook and could not */ - if (iop->fd == INVALID_HANDLE) { + if (iop->public.fd == INVALID_HANDLE) { if (iop_malloced) efree(iop); return NULL; } - } else if (iop->fd == INVALID_HANDLE) + } else if (iop->public.fd == INVALID_HANDLE) return iop; - if (os_isatty(iop->fd)) + if (os_isatty(iop->public.fd)) iop->flag |= IOP_IS_TTY; - iop->readsize = iop->size = optimal_bufsize(iop->fd, & sbuf); + iop->readsize = iop->size = optimal_bufsize(iop->public.fd, & sbuf); iop->sbuf = sbuf; if (do_lint && S_ISREG(sbuf.st_mode) && sbuf.st_size == 0) lintwarn(_("data file `%s' is empty"), name); @@ -3052,12 +3052,16 @@ get_a_record(char **out, /* pointer to pointer to data */ if (read_can_timeout) read_timeout = get_read_timeout(iop); - if (iop->get_record != NULL) - return iop->get_record(out, iop, errcode); + if (iop->public.get_record != NULL) { + int rc = iop->public.get_record(out, &iop->public, errcode); + if (rc == EOF) + iop->flag |= IOP_AT_EOF; + return rc; + } /* fill initial buffer */ if (has_no_data(iop) || no_data_left(iop)) { - iop->count = iop->read_func(iop->fd, iop->buf, iop->readsize); + iop->count = iop->read_func(iop->public.fd, iop->buf, iop->readsize); if (iop->count == 0) { iop->flag |= IOP_AT_EOF; return EOF; @@ -3124,7 +3128,7 @@ get_a_record(char **out, /* pointer to pointer to data */ amt_to_read = min(amt_to_read, SSIZE_MAX); #endif - iop->count = iop->read_func(iop->fd, iop->dataend, amt_to_read); + iop->count = iop->read_func(iop->public.fd, iop->dataend, amt_to_read); if (iop->count == -1) { *errcode = errno; iop->flag |= IOP_AT_EOF; @@ -3397,7 +3401,7 @@ get_read_timeout(IOBUF *iop) long tmout = 0; if (PROCINFO_node != NULL) { - const char *name = iop->name; + const char *name = iop->public.name; NODE *val = NULL; static NODE *full_idx = NULL; static const char *last_name = NULL; -- cgit v1.2.3 From 3d2d6b46bf3325c0273b35a202184ab09d38e0cd Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 25 Jul 2012 22:34:19 +0300 Subject: Start refactoring iop handling. Add readdir extension. --- io.c | 129 ++++++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 66 insertions(+), 63 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index ab204e09..584e434c 100644 --- a/io.c +++ b/io.c @@ -203,12 +203,12 @@ static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type ho static int wait_any(int interesting); #endif static IOBUF *gawk_popen(const char *cmd, struct redirect *rp); -static IOBUF *iop_alloc(int fd, const char *name, IOBUF *buf, bool do_openhooks); +static IOBUF *iop_alloc(int fd, const char *name, bool do_input_parsers); static int gawk_pclose(struct redirect *rp); static int str2mode(const char *mode); static int two_way_open(const char *str, struct redirect *rp); static int pty_vs_pipe(const char *command); -static void find_open_hook(IOBUF *iop); +static void find_input_parser(IOBUF *iop); static RECVALUE rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state); static RECVALUE rsnullscan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state); @@ -336,10 +336,14 @@ after_beginfile(IOBUF **curfile) * so delay check until now. */ - find_open_hook(iop); + find_input_parser(iop); } /* nextfile --- move to the next input data file */ +/* + * Return value > 0 ----> run BEGINFILE block + * *curfile = NULL ----> hit EOF, run ENDFILE block + */ int nextfile(IOBUF **curfile, bool skipping) @@ -347,7 +351,6 @@ nextfile(IOBUF **curfile, bool skipping) static long i = 1; static bool files = false; NODE *arg, *tmp; - static IOBUF mybuf; const char *fname; int fd = INVALID_HANDLE; int errcode = 0; @@ -406,12 +409,11 @@ nextfile(IOBUF **curfile, bool skipping) mpz_set_ui(MFNR, 0); #endif FNR = 0; - iop = *curfile = iop_alloc(fd, fname, & mybuf, false); + iop = *curfile = iop_alloc(fd, fname, false); if (fd == INVALID_HANDLE) iop->errcode = errcode; else iop->errcode = 0; - iop->flag |= IOP_NOFREE_OBJ; return ++i; /* run beginfile block */ } } @@ -427,8 +429,7 @@ nextfile(IOBUF **curfile, bool skipping) FILENAME_node->var_value = make_string("-", 1); FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */ fname = "-"; - iop = *curfile = iop_alloc(fileno(stdin), fname, & mybuf, false); - iop->flag |= IOP_NOFREE_OBJ; + iop = *curfile = iop_alloc(fileno(stdin), fname, false); if (iop->public.fd == INVALID_HANDLE) { errcode = errno; @@ -539,11 +540,6 @@ iop_close(IOBUF *iop) if (iop == NULL) return 0; - if (iop->public.fd == INVALID_HANDLE) { /* from nextfile(...) above */ - assert(iop->buf == NULL); - assert((iop->flag & IOP_NOFREE_OBJ) != 0); - return 0; - } errno = 0; @@ -555,16 +551,18 @@ iop_close(IOBUF *iop) * So we remap the standard file to /dev/null. * Thanks to Jim Meyering for the suggestion. */ - if (iop->public.fd == fileno(stdin) - || iop->public.fd == fileno(stdout) - || iop->public.fd == fileno(stderr)) - ret = remap_std_file(iop->public.fd); - else - ret = close(iop->public.fd); - if (iop->public.close_func != NULL) iop->public.close_func(&iop->public); + if (iop->public.fd != INVALID_HANDLE) { + if (iop->public.fd == fileno(stdin) + || iop->public.fd == fileno(stdout) + || iop->public.fd == fileno(stderr)) + ret = remap_std_file(iop->public.fd); + else + ret = close(iop->public.fd); + } + if (ret == -1) warning(_("close of fd %d (`%s') failed (%s)"), iop->public.fd, iop->public.name, strerror(errno)); @@ -595,8 +593,7 @@ iop_close(IOBUF *iop) efree(iop->buf); iop->buf = NULL; } - if ((iop->flag & IOP_NOFREE_OBJ) == 0) - efree(iop); + efree(iop); return ret == -1 ? 1 : 0; } @@ -805,7 +802,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) /* do not free rp, saving it for reuse (save_rp = rp) */ return NULL; } - rp->iop = iop_alloc(fd, str, NULL, true); + rp->iop = iop_alloc(fd, str, true); break; case redirect_twoway: direction = "to/from"; @@ -1618,10 +1615,7 @@ strictopen: if (openfd > fileno(stderr)) os_close_on_exec(openfd, name, "file", ""); } - /* - * XXX: FIXME: if fd is INVALID_HANDLE, see if an open hook - * can do something. - */ + return openfd; } @@ -1652,7 +1646,7 @@ two_way_open(const char *str, struct redirect *rp) } os_close_on_exec(fd, str, "socket", "to/from"); os_close_on_exec(newfd, str, "socket", "to/from"); - rp->iop = iop_alloc(newfd, str, NULL, true); + rp->iop = iop_alloc(newfd, str, true); if (rp->iop == NULL) { close(newfd); fclose(rp->fp); @@ -1848,7 +1842,7 @@ two_way_open(const char *str, struct redirect *rp) } rp->pid = pid; - rp->iop = iop_alloc(master, str, NULL, true); + rp->iop = iop_alloc(master, str, true); if (rp->iop == NULL) { (void) close(master); (void) kill(pid, SIGKILL); @@ -2001,7 +1995,7 @@ use_pipes: /* parent */ rp->pid = pid; - rp->iop = iop_alloc(ctop[0], str, NULL, true); + rp->iop = iop_alloc(ctop[0], str, true); if (rp->iop == NULL) { (void) close(ctop[0]); (void) close(ctop[1]); @@ -2165,7 +2159,7 @@ gawk_popen(const char *cmd, struct redirect *rp) } #endif os_close_on_exec(p[0], cmd, "pipe", "from"); - rp->iop = iop_alloc(p[0], cmd, NULL, true); + rp->iop = iop_alloc(p[0], cmd, true); if (rp->iop == NULL) (void) close(p[0]); @@ -2210,7 +2204,7 @@ gawk_popen(const char *cmd, struct redirect *rp) if (current == NULL) return NULL; os_close_on_exec(fileno(current), cmd, "pipe", "from"); - rp->iop = iop_alloc(fileno(current), cmd, NULL, true); + rp->iop = iop_alloc(fileno(current), cmd, true); if (rp->iop == NULL) { (void) pclose(current); current = NULL; @@ -2585,63 +2579,73 @@ srcopen(SRCFILE *s) return INVALID_HANDLE; } -/* open hooks, mainly for use by extension functions */ +/* input parsers, mainly for use by extension functions */ -static struct open_hook { - struct open_hook *next; - void *(*open_func)(IOBUF_PUBLIC *); -} *open_hooks; +static awk_input_parser_t *ip_head, *ip_tail; -/* register_open_hook --- add an open hook to the list */ +/* register_input_parser --- add an input parser to the list, FIFO */ void -register_open_hook(void *(*open_func)(IOBUF_PUBLIC *)) +register_input_parser(awk_input_parser_t *input_parser) { - struct open_hook *oh; + if (input_parser == NULL) + fatal(_("register_input_parser: received NULL pointer")); - emalloc(oh, struct open_hook *, sizeof(*oh), "register_open_hook"); - oh->open_func = open_func; - oh->next = open_hooks; - open_hooks = oh; + input_parser->next = NULL; /* force it */ + if (ip_head == NULL) { + ip_head = ip_tail = input_parser; + } else { + ip_tail->next = input_parser; + ip_tail = ip_tail->next; + } } -/* find_open_hook --- search the list of open hooks */ +/* find_input_parser --- search the list of input parsers */ static void -find_open_hook(IOBUF *iop) +find_input_parser(IOBUF *iop) { - struct open_hook *oh; + awk_input_parser_t *ip, *ip2; - /* walk through open hooks, stop at first one that responds */ - for (oh = open_hooks; oh != NULL; oh = oh->next) { - if ((iop->public.opaque = (*oh->open_func)(&iop->public)) != NULL) - break; + /* if already associated with an input parser, bail out early */ + if (iop->public.get_record != NULL) + return; + + ip = ip2 = NULL; + for (ip2 = ip_head; ip2 != NULL; ip2 = ip2->next) { + if (ip2->can_take_file(& iop->public)) { + if (ip == NULL) + ip = ip2; /* found first one */ + else + fatal(_("input parser `%s' conflicts with previously installed input parser `%s'"), + ip2->name, ip->name); + } } + + if (ip != NULL) + ip->take_control_of(& iop->public); } /* iop_alloc --- allocate an IOBUF structure for an open fd */ static IOBUF * -iop_alloc(int fd, const char *name, IOBUF *iop, bool do_openhooks) +iop_alloc(int fd, const char *name, bool do_input_parsers) { struct stat sbuf; - bool iop_malloced = false; + IOBUF *iop; + + emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc"); - if (iop == NULL) { - emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc"); - iop_malloced = true; - } memset(iop, '\0', sizeof(IOBUF)); iop->public.fd = fd; iop->public.name = name; iop->read_func = ( ssize_t(*)() ) read; - if (do_openhooks) { - find_open_hook(iop); - /* tried to find open hook and could not */ + if (do_input_parsers) { + find_input_parser(iop); + /* tried to find open parser and could not */ if (iop->public.fd == INVALID_HANDLE) { - if (iop_malloced) - efree(iop); + efree(iop); return NULL; } } else if (iop->public.fd == INVALID_HANDLE) @@ -3300,7 +3304,6 @@ iopflags2str(int flag) { static const struct flagtab values[] = { { IOP_IS_TTY, "IOP_IS_TTY" }, - { IOP_NOFREE_OBJ, "IOP_NOFREE_OBJ" }, { IOP_AT_EOF, "IOP_AT_EOF" }, { IOP_CLOSED, "IOP_CLOSED" }, { IOP_AT_START, "IOP_AT_START" }, -- cgit v1.2.3 From 40eefdd931066129d0bb2f6144a0ec7741c6cc2b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 25 Jul 2012 22:56:37 +0300 Subject: Remove translation of errno strings from API. --- io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index 584e434c..6cfc3efe 100644 --- a/io.c +++ b/io.c @@ -1018,7 +1018,7 @@ do_close(int nargs) if (! do_traditional) { /* update ERRNO manually, using errno = ENOENT is a stretch. */ cp = _("close of redirection that was never opened"); - update_ERRNO_string(cp, DONT_TRANSLATE); + update_ERRNO_string(cp); } DEREF(tmp); -- cgit v1.2.3 From ca83de0ec92b56c712f7a7376b21a1a1337b3107 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 26 Jul 2012 11:56:00 -0400 Subject: Document the parser interface and remove some excessive readdir paranoia. --- io.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 6cfc3efe..05e87907 100644 --- a/io.c +++ b/io.c @@ -3036,7 +3036,7 @@ find_longest_terminator: return REC_OK; } -/* get_a_record --- read a record from IOP into out, return length of EOF, set RT */ +/* get_a_record --- read a record from IOP into out, return length of EOF, set RT. Note that errcode is never NULL, and the caller initializes *errcode to 0. */ static int get_a_record(char **out, /* pointer to pointer to data */ @@ -3071,8 +3071,7 @@ get_a_record(char **out, /* pointer to pointer to data */ return EOF; } else if (iop->count == -1) { iop->flag |= IOP_AT_EOF; - if (errcode != NULL) - *errcode = errno; + *errcode = errno; return EOF; } else { iop->dataend = iop->buf + iop->count; -- cgit v1.2.3 From 652a11e5fbe9862a2b8e961b32b9748b3c2c418b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 26 Jul 2012 22:27:54 +0300 Subject: Add set_RT to API and to readdir extension. --- io.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'io.c') diff --git a/io.c b/io.c index 05e87907..f4ea286a 100644 --- a/io.c +++ b/io.c @@ -536,7 +536,7 @@ remap_std_file(int oldfd) static int iop_close(IOBUF *iop) { - int ret; + int ret = 0; if (iop == NULL) return 0; @@ -2667,6 +2667,30 @@ iop_alloc(int fd, const char *name, bool do_input_parsers) return iop; } +/* set_RT_to_null --- real function for use by extension API */ + +void +set_RT_to_null() +{ + if (! do_traditional) { + unref(RT_node->var_value); + RT_node->var_value = dupnode(Nnull_string); + } +} + +/* set_RT --- real function for use by extension API */ + +void +set_RT(const char *str, size_t len) +{ + if (! do_traditional) { + unref(RT_node->var_value); + RT_node->var_value = make_str_node(str, len, ALREADY_MALLOCED); + } +} + +/* macros for speed in default implementation */ + #define set_RT_to_null() \ (void)(! do_traditional && (unref(RT_node->var_value), \ RT_node->var_value = dupnode(Nnull_string))) -- cgit v1.2.3 From 207fc1458c7f168822e454a89f23428c64163427 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 27 Jul 2012 15:25:05 +0300 Subject: Fix bug in API set_RT, bug in readdir.c. --- io.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index f4ea286a..2f3c5f85 100644 --- a/io.c +++ b/io.c @@ -332,7 +332,7 @@ after_beginfile(IOBUF **curfile) } /* - * Open hooks could have been changed by BEGINFILE, + * Input parsers could have been changed by BEGINFILE, * so delay check until now. */ @@ -2678,14 +2678,18 @@ set_RT_to_null() } } -/* set_RT --- real function for use by extension API */ +/* set_RT --- real function **** for use by extension API **** */ void -set_RT(const char *str, size_t len) +set_RT(NODE *n) { - if (! do_traditional) { + if (do_traditional) + unref(n); + else if (RT_node->var_value == n) + assert(n == Nnull_string); /* do nothing */ + else { unref(RT_node->var_value); - RT_node->var_value = make_str_node(str, len, ALREADY_MALLOCED); + RT_node->var_value = n; } } -- cgit v1.2.3 From fbff497e69139d7cd8434112d6f0a36a46350da1 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Fri, 27 Jul 2012 12:16:18 -0400 Subject: Issue a warning if the parser take_control_of function fails. --- io.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 2f3c5f85..5255f84f 100644 --- a/io.c +++ b/io.c @@ -2622,8 +2622,11 @@ find_input_parser(IOBUF *iop) } } - if (ip != NULL) - ip->take_control_of(& iop->public); + if (ip != NULL) { + if (! ip->take_control_of(& iop->public)) + warning(_("input parser `%s' failed to open `%s'."), + ip->name, iop->public.name); + } } /* iop_alloc --- allocate an IOBUF structure for an open fd */ -- cgit v1.2.3 From 82816b279615b27f7c4f87349a8c830a96939d8c Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 29 Jul 2012 16:33:00 +0300 Subject: Finish work on iop management. New readdir test. --- io.c | 104 +++++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 67 insertions(+), 37 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 2f3c5f85..fdcf6b7b 100644 --- a/io.c +++ b/io.c @@ -203,7 +203,7 @@ static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type ho static int wait_any(int interesting); #endif static IOBUF *gawk_popen(const char *cmd, struct redirect *rp); -static IOBUF *iop_alloc(int fd, const char *name, bool do_input_parsers); +static IOBUF *iop_alloc(int fd, const char *name); static int gawk_pclose(struct redirect *rp); static int str2mode(const char *mode); static int two_way_open(const char *str, struct redirect *rp); @@ -315,15 +315,16 @@ after_beginfile(IOBUF **curfile) if (iop->public.fd == INVALID_HANDLE) { const char *fname; int errcode; + bool valid; fname = iop->public.name; errcode = iop->errcode; - iop->errcode = 0; + valid = iop->valid; errno = 0; update_ERRNO_int(errno); iop_close(iop); *curfile = NULL; - if (errcode == EISDIR && ! do_traditional) { + if (! valid && errcode == EISDIR && ! do_traditional) { warning(_("command line argument `%s' is a directory: skipped"), fname); return; /* read next file */ } @@ -409,11 +410,15 @@ nextfile(IOBUF **curfile, bool skipping) mpz_set_ui(MFNR, 0); #endif FNR = 0; - iop = *curfile = iop_alloc(fd, fname, false); + iop = *curfile = iop_alloc(fd, fname); if (fd == INVALID_HANDLE) iop->errcode = errcode; - else + else if (iop->valid) iop->errcode = 0; + + if (! do_traditional && iop->errcode != 0) + update_ERRNO_int(iop->errcode); + return ++i; /* run beginfile block */ } } @@ -429,7 +434,7 @@ nextfile(IOBUF **curfile, bool skipping) FILENAME_node->var_value = make_string("-", 1); FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */ fname = "-"; - iop = *curfile = iop_alloc(fileno(stdin), fname, false); + iop = *curfile = iop_alloc(fileno(stdin), fname); if (iop->public.fd == INVALID_HANDLE) { errcode = errno; @@ -802,7 +807,13 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) /* do not free rp, saving it for reuse (save_rp = rp) */ return NULL; } - rp->iop = iop_alloc(fd, str, true); + rp->iop = iop_alloc(fd, str); + if (! rp->iop->valid) { + if (! do_traditional && rp->iop->errcode != 0) + update_ERRNO_int(rp->iop->errcode); + iop_close(rp->iop); + rp->iop = NULL; + } break; case redirect_twoway: direction = "to/from"; @@ -1605,13 +1616,6 @@ strictopen: } #endif if (openfd != INVALID_HANDLE) { - if (os_isdir(openfd)) { - (void) close(openfd); /* don't leak fds */ - /* Set useful error number. */ - errno = EISDIR; - return INVALID_HANDLE; - } - if (openfd > fileno(stderr)) os_close_on_exec(openfd, name, "file", ""); } @@ -1646,9 +1650,12 @@ two_way_open(const char *str, struct redirect *rp) } os_close_on_exec(fd, str, "socket", "to/from"); os_close_on_exec(newfd, str, "socket", "to/from"); - rp->iop = iop_alloc(newfd, str, true); - if (rp->iop == NULL) { - close(newfd); + rp->iop = iop_alloc(newfd, str); + if (! rp->iop->valid) { + if (! do_traditional && rp->iop->errcode != 0) + update_ERRNO_int(rp->iop->errcode); + iop_close(rp->iop); + rp->iop = NULL; fclose(rp->fp); return false; } @@ -1842,9 +1849,12 @@ two_way_open(const char *str, struct redirect *rp) } rp->pid = pid; - rp->iop = iop_alloc(master, str, true); - if (rp->iop == NULL) { - (void) close(master); + rp->iop = iop_alloc(master, str); + if (! rp->iop->valid) { + if (! do_traditional && rp->iop->errcode != 0) + update_ERRNO_int(rp->iop->errcode); + iop_close(rp->iop); + rp->iop = NULL; (void) kill(pid, SIGKILL); return false; } @@ -1995,9 +2005,12 @@ use_pipes: /* parent */ rp->pid = pid; - rp->iop = iop_alloc(ctop[0], str, true); - if (rp->iop == NULL) { - (void) close(ctop[0]); + rp->iop = iop_alloc(ctop[0], str); + if (! rp->iop->valid) { + if (! do_traditional && rp->iop->errcode != 0) + update_ERRNO_int(rp->iop->errcode); + iop_close(rp->iop); + rp->iop = NULL; (void) close(ctop[1]); (void) close(ptoc[0]); (void) close(ptoc[1]); @@ -2159,9 +2172,13 @@ gawk_popen(const char *cmd, struct redirect *rp) } #endif os_close_on_exec(p[0], cmd, "pipe", "from"); - rp->iop = iop_alloc(p[0], cmd, true); - if (rp->iop == NULL) - (void) close(p[0]); + rp->iop = iop_alloc(p[0], cmd); + if (! rp->iop->valid) { + if (! do_traditional && rp->iop->errcode != 0) + update_ERRNO_int(rp->iop->errcode); + iop_close(rp->iop); + rp->iop = NULL; + } return rp->iop; } @@ -2204,9 +2221,14 @@ gawk_popen(const char *cmd, struct redirect *rp) if (current == NULL) return NULL; os_close_on_exec(fileno(current), cmd, "pipe", "from"); - rp->iop = iop_alloc(fileno(current), cmd, true); - if (rp->iop == NULL) { + rp->iop = iop_alloc(fileno(current), cmd); + if (! rp->iop->valid) { + if (! do_traditional && rp->iop->errcode != 0) + update_ERRNO_int(rp->iop->errcode); (void) pclose(current); + rp->iop->public.fd = INVALID_HANDLE; + iop_close(rp->iop); + rp->iop = NULL; current = NULL; } rp->ifp = current; @@ -2629,10 +2651,11 @@ find_input_parser(IOBUF *iop) /* iop_alloc --- allocate an IOBUF structure for an open fd */ static IOBUF * -iop_alloc(int fd, const char *name, bool do_input_parsers) +iop_alloc(int fd, const char *name) { struct stat sbuf; IOBUF *iop; + bool isdir; emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc"); @@ -2640,16 +2663,22 @@ iop_alloc(int fd, const char *name, bool do_input_parsers) iop->public.fd = fd; iop->public.name = name; iop->read_func = ( ssize_t(*)() ) read; + iop->valid = false; - if (do_input_parsers) { - find_input_parser(iop); - /* tried to find open parser and could not */ - if (iop->public.fd == INVALID_HANDLE) { - efree(iop); - return NULL; - } - } else if (iop->public.fd == INVALID_HANDLE) + find_input_parser(iop); + + /* tried to find open parser and could not */ + if ( iop->public.get_record == NULL + && ! os_isreadable(iop->public.fd, & isdir)) { + if (isdir) + iop->errcode = EISDIR; + close(iop->public.fd); + iop->public.fd = INVALID_HANDLE; + } + + if (iop->public.fd == INVALID_HANDLE) { return iop; + } if (os_isatty(iop->public.fd)) iop->flag |= IOP_IS_TTY; @@ -2664,6 +2693,7 @@ iop_alloc(int fd, const char *name, bool do_input_parsers) iop->dataend = NULL; iop->end = iop->buf + iop->size; iop->flag |= IOP_AT_START; + iop->valid = true; return iop; } -- cgit v1.2.3 From 0eaab9127d090da073a53695583837fcbd2be9d3 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 29 Jul 2012 17:13:13 +0300 Subject: Update input_parser interface for RT. --- io.c | 53 +++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 57cdb581..8bc649e6 100644 --- a/io.c +++ b/io.c @@ -2700,34 +2700,6 @@ iop_alloc(int fd, const char *name) return iop; } -/* set_RT_to_null --- real function for use by extension API */ - -void -set_RT_to_null() -{ - if (! do_traditional) { - unref(RT_node->var_value); - RT_node->var_value = dupnode(Nnull_string); - } -} - -/* set_RT --- real function **** for use by extension API **** */ - -void -set_RT(NODE *n) -{ - if (do_traditional) - unref(n); - else if (RT_node->var_value == n) - assert(n == Nnull_string); /* do nothing */ - else { - unref(RT_node->var_value); - RT_node->var_value = n; - } -} - -/* macros for speed in default implementation */ - #define set_RT_to_null() \ (void)(! do_traditional && (unref(RT_node->var_value), \ RT_node->var_value = dupnode(Nnull_string))) @@ -3097,7 +3069,11 @@ find_longest_terminator: return REC_OK; } -/* get_a_record --- read a record from IOP into out, return length of EOF, set RT. Note that errcode is never NULL, and the caller initializes *errcode to 0. */ +/* + * get_a_record --- read a record from IOP into out, + * return length of EOF, set RT. + * Note that errcode is never NULL, and the caller initializes *errcode to 0. + */ static int get_a_record(char **out, /* pointer to pointer to data */ @@ -3118,9 +3094,26 @@ get_a_record(char **out, /* pointer to pointer to data */ read_timeout = get_read_timeout(iop); if (iop->public.get_record != NULL) { - int rc = iop->public.get_record(out, &iop->public, errcode); + char *rt_start; + size_t rt_len; + int rc = iop->public.get_record(out, &iop->public, errcode, + &rt_start, &rt_len); if (rc == EOF) iop->flag |= IOP_AT_EOF; + else if (! do_traditional) { + /* + * all known extension parsers set RT to "", so probably + * not worth optimizing the other case + */ + if (rt_len != 0) { + /* should we optimize this? */ + unref(RT_node->var_value); + RT_node->var_value = make_string(rt_start, rt_len); + } else if (RT_node->var_value != Nnull_string) { + unref(RT_node->var_value); + RT_node->var_value = dupnode(Nnull_string); + } + } return rc; } -- cgit v1.2.3 From 6456df6de8e7f5931551612cfd4eb4f1c562654b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 1 Aug 2012 19:11:25 +0300 Subject: Finish reworking input parsers. --- io.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 132 insertions(+), 56 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 8bc649e6..d37c0b32 100644 --- a/io.c +++ b/io.c @@ -203,7 +203,8 @@ static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type ho static int wait_any(int interesting); #endif static IOBUF *gawk_popen(const char *cmd, struct redirect *rp); -static IOBUF *iop_alloc(int fd, const char *name); +static IOBUF *iop_alloc(int fd, const char *name, int errno_val); +static IOBUF *iop_finish(IOBUF *iop); static int gawk_pclose(struct redirect *rp); static int str2mode(const char *mode); static int two_way_open(const char *str, struct redirect *rp); @@ -312,7 +313,14 @@ after_beginfile(IOBUF **curfile) iop = *curfile; assert(iop != NULL); - if (iop->public.fd == INVALID_HANDLE) { + /* + * Input parsers could have been changed by BEGINFILE, + * so delay check until now. + */ + + find_input_parser(iop); + + if (! iop->valid) { const char *fname; int errcode; bool valid; @@ -321,7 +329,7 @@ after_beginfile(IOBUF **curfile) errcode = iop->errcode; valid = iop->valid; errno = 0; - update_ERRNO_int(errno); + update_ERRNO_int(errcode); iop_close(iop); *curfile = NULL; if (! valid && errcode == EISDIR && ! do_traditional) { @@ -331,13 +339,6 @@ after_beginfile(IOBUF **curfile) fatal(_("cannot open file `%s' for reading (%s)"), fname, strerror(errcode)); } - - /* - * Input parsers could have been changed by BEGINFILE, - * so delay check until now. - */ - - find_input_parser(iop); } /* nextfile --- move to the next input data file */ @@ -397,12 +398,8 @@ nextfile(IOBUF **curfile, bool skipping) if (! arg_assign(arg->stptr, false)) { files = true; fname = arg->stptr; - errno = 0; - fd = devopen(fname, binmode("r")); - errcode = errno; - if (! do_traditional) - update_ERRNO_int(errno); + /* manage the awk variables: */ unref(FILENAME_node->var_value); FILENAME_node->var_value = dupnode(arg); #ifdef HAVE_MPFR @@ -410,8 +407,16 @@ nextfile(IOBUF **curfile, bool skipping) mpz_set_ui(MFNR, 0); #endif FNR = 0; - iop = *curfile = iop_alloc(fd, fname); - if (fd == INVALID_HANDLE) + + /* IOBUF management: */ + errno = 0; + fd = devopen(fname, binmode("r")); + errcode = errno; + if (! do_traditional) + update_ERRNO_int(errno); + iop = iop_alloc(fd, fname, errcode); + *curfile = iop_finish(iop); + if (iop->public.fd == INVALID_HANDLE) iop->errcode = errcode; else if (iop->valid) iop->errcode = 0; @@ -430,11 +435,13 @@ nextfile(IOBUF **curfile, bool skipping) errno = 0; if (! do_traditional) update_ERRNO_int(errno); + unref(FILENAME_node->var_value); FILENAME_node->var_value = make_string("-", 1); FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */ fname = "-"; - iop = *curfile = iop_alloc(fileno(stdin), fname); + iop = iop_alloc(fileno(stdin), fname, 0); + *curfile = iop_finish(iop); if (iop->public.fd == INVALID_HANDLE) { errcode = errno; @@ -807,7 +814,9 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) /* do not free rp, saving it for reuse (save_rp = rp) */ return NULL; } - rp->iop = iop_alloc(fd, str); + rp->iop = iop_alloc(fd, str, errno); + find_input_parser(rp->iop); + iop_finish(rp->iop); if (! rp->iop->valid) { if (! do_traditional && rp->iop->errcode != 0) update_ERRNO_int(rp->iop->errcode); @@ -1650,7 +1659,9 @@ two_way_open(const char *str, struct redirect *rp) } os_close_on_exec(fd, str, "socket", "to/from"); os_close_on_exec(newfd, str, "socket", "to/from"); - rp->iop = iop_alloc(newfd, str); + rp->iop = iop_alloc(newfd, str, 0); + find_input_parser(rp->iop); + iop_finish(rp->iop); if (! rp->iop->valid) { if (! do_traditional && rp->iop->errcode != 0) update_ERRNO_int(rp->iop->errcode); @@ -1849,7 +1860,9 @@ two_way_open(const char *str, struct redirect *rp) } rp->pid = pid; - rp->iop = iop_alloc(master, str); + rp->iop = iop_alloc(master, str, 0); + find_input_parser(rp->iop); + iop_finish(rp->iop); if (! rp->iop->valid) { if (! do_traditional && rp->iop->errcode != 0) update_ERRNO_int(rp->iop->errcode); @@ -2005,7 +2018,9 @@ use_pipes: /* parent */ rp->pid = pid; - rp->iop = iop_alloc(ctop[0], str); + rp->iop = iop_alloc(ctop[0], str, 0); + find_input_parser(rp->iop); + iop_finish(rp->iop); if (! rp->iop->valid) { if (! do_traditional && rp->iop->errcode != 0) update_ERRNO_int(rp->iop->errcode); @@ -2172,7 +2187,9 @@ gawk_popen(const char *cmd, struct redirect *rp) } #endif os_close_on_exec(p[0], cmd, "pipe", "from"); - rp->iop = iop_alloc(p[0], cmd); + rp->iop = iop_alloc(p[0], cmd, 0); + find_input_parser(rp->iop); + iop_finish(rp->iop); if (! rp->iop->valid) { if (! do_traditional && rp->iop->errcode != 0) update_ERRNO_int(rp->iop->errcode); @@ -2221,7 +2238,9 @@ gawk_popen(const char *cmd, struct redirect *rp) if (current == NULL) return NULL; os_close_on_exec(fileno(current), cmd, "pipe", "from"); - rp->iop = iop_alloc(fileno(current), cmd); + rp->iop = iop_alloc(fileno(current), cmd, 0); + find_input_parser(rp->iop); + iop_finish(rp->iop); if (! rp->iop->valid) { if (! do_traditional && rp->iop->errcode != 0) update_ERRNO_int(rp->iop->errcode); @@ -2605,7 +2624,12 @@ srcopen(SRCFILE *s) static awk_input_parser_t *ip_head, *ip_tail; -/* register_input_parser --- add an input parser to the list, FIFO */ +/* + * register_input_parser --- add an input parser to the list, FIFO. + * The main reason to use FIFO is to provide the diagnostic + * with the correct information: input parser 2 conflicts + * with input parser 1. Otherwise LIFO would have been easier. + */ void register_input_parser(awk_input_parser_t *input_parser) @@ -2646,19 +2670,60 @@ find_input_parser(IOBUF *iop) if (ip != NULL) { if (! ip->take_control_of(& iop->public)) - warning(_("input parser `%s' failed to open `%s'."), + warning(_("input parser `%s' failed to open `%s'"), ip->name, iop->public.name); + else + iop->valid = true; } } +/* + * IOBUF management is somewhat complicated. In particular, + * it is possible and OK for an IOBUF to be allocated with + * a file descriptor that is either valid or not usable with + * read(2), in case an input parser will come along later and + * make it readable. Alternatively, an input parser can simply + * come along and take over reading on a valid readable descriptor. + * + * The first stage is simply to allocate the IOBUF. This is done + * during nextfile() for command line files and by redirect() + * and other routines for getline, input pipes, and the input + * side of a two-way pipe. + * + * The second stage is to check for input parsers. This is done + * for command line files in after_beginfile() and for the others + * as part of the full flow. At this point, either: + * - The fd is valid on a readable file + * - The input parser has taken over a valid fd and made + * it usable (e.g., directories) + * - Or the input parser has simply hijacked the reading + * (such as the gawkextlib XML extension) + * If none of those are true, the fd should be closed, reset + * to INVALID_HANDLE, and iop->errcode set to indicate the error + * (EISDIR for directories, EIO for anything else). + * iop->valid should be set to false in this case. + * + * Otherwise, after the second stage, iop->errcode should be + * zero, iop->valid should be true, and iop->public.fd should + * not be INVALID_HANDLE. + * + * The third stage is to set up the rest of the IOBUF for + * use by get_a_record(). In this case, iop->valid must + * be true already, and iop->public.fd cannot be INVALID_HANDLE. + * + * Checking for input parsers for command line files is delayed + * to after_beginfile() so that the BEGINFILE rule has an + * opportunity to look at FILENAME and ERRNO and attempt to + * recover with a custom input parser. The XML extension, in + * particular, relies strongly upon this ability. + */ + /* iop_alloc --- allocate an IOBUF structure for an open fd */ static IOBUF * -iop_alloc(int fd, const char *name) +iop_alloc(int fd, const char *name, int errno_val) { - struct stat sbuf; IOBUF *iop; - bool isdir; emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc"); @@ -2667,36 +2732,55 @@ iop_alloc(int fd, const char *name) iop->public.name = name; iop->read_func = ( ssize_t(*)() ) read; iop->valid = false; + iop->errcode = errno_val; - find_input_parser(iop); + return iop; +} + +/* iop_finish --- finish setting up an IOBUF */ + +static IOBUF * +iop_finish(IOBUF *iop) +{ + bool isdir = false; + struct stat sbuf; - /* tried to find open parser and could not */ - if ( iop->public.get_record == NULL - && ! os_isreadable(iop->public.fd, & isdir)) { - if (isdir) - iop->errcode = EISDIR; - close(iop->public.fd); - iop->public.fd = INVALID_HANDLE; + if (iop->public.fd != INVALID_HANDLE) { + if (os_isreadable(iop->public.fd, & isdir)) + iop->valid = true; + else { + if (isdir) + iop->errcode = EISDIR; + else { + iop->errcode = EIO; + (void) close(iop->public.fd); + iop->public.fd = INVALID_HANDLE; + } + /* + * Don't close directories: after_beginfile(), + * special cases them. + */ + } } - if (iop->public.fd == INVALID_HANDLE) { + if (! iop->valid || iop->public.fd == INVALID_HANDLE) return iop; - } if (os_isatty(iop->public.fd)) iop->flag |= IOP_IS_TTY; + iop->readsize = iop->size = optimal_bufsize(iop->public.fd, & sbuf); iop->sbuf = sbuf; if (do_lint && S_ISREG(sbuf.st_mode) && sbuf.st_size == 0) - lintwarn(_("data file `%s' is empty"), name); - errno = 0; + lintwarn(_("data file `%s' is empty"), iop->public.name); + iop->errcode = errno = 0; iop->count = iop->scanoff = 0; - emalloc(iop->buf, char *, iop->size += 2, "iop_alloc"); + emalloc(iop->buf, char *, iop->size += 2, "iop_finish"); iop->off = iop->buf; iop->dataend = NULL; iop->end = iop->buf + iop->size; iop->flag |= IOP_AT_START; - iop->valid = true; + return iop; } @@ -3100,19 +3184,11 @@ get_a_record(char **out, /* pointer to pointer to data */ &rt_start, &rt_len); if (rc == EOF) iop->flag |= IOP_AT_EOF; - else if (! do_traditional) { - /* - * all known extension parsers set RT to "", so probably - * not worth optimizing the other case - */ - if (rt_len != 0) { - /* should we optimize this? */ - unref(RT_node->var_value); - RT_node->var_value = make_string(rt_start, rt_len); - } else if (RT_node->var_value != Nnull_string) { - unref(RT_node->var_value); - RT_node->var_value = dupnode(Nnull_string); - } + else { + if (rt_len != 0) + set_RT(rt_start, rt_len); + else + set_RT_to_null(); } return rc; } -- cgit v1.2.3 From 49658bfd0ef5d4efccd210c48560c43bf455ee16 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 8 Aug 2012 22:51:53 +0300 Subject: Move struct stat into IOBUF_PUBLIC. --- io.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index d37c0b32..589abbf4 100644 --- a/io.c +++ b/io.c @@ -2734,6 +2734,9 @@ iop_alloc(int fd, const char *name, int errno_val) iop->valid = false; iop->errcode = errno_val; + if (fd != INVALID_HANDLE) + fstat(fd, & iop->public.sbuf); + return iop; } @@ -2743,10 +2746,9 @@ static IOBUF * iop_finish(IOBUF *iop) { bool isdir = false; - struct stat sbuf; if (iop->public.fd != INVALID_HANDLE) { - if (os_isreadable(iop->public.fd, & isdir)) + if (os_isreadable(& iop->public, & isdir)) iop->valid = true; else { if (isdir) @@ -2769,9 +2771,8 @@ iop_finish(IOBUF *iop) if (os_isatty(iop->public.fd)) iop->flag |= IOP_IS_TTY; - iop->readsize = iop->size = optimal_bufsize(iop->public.fd, & sbuf); - iop->sbuf = sbuf; - if (do_lint && S_ISREG(sbuf.st_mode) && sbuf.st_size == 0) + iop->readsize = iop->size = optimal_bufsize(iop->public.fd, & iop->public.sbuf); + if (do_lint && S_ISREG(iop->public.sbuf.st_mode) && iop->public.sbuf.st_size == 0) lintwarn(_("data file `%s' is empty"), iop->public.name); iop->errcode = errno = 0; iop->count = iop->scanoff = 0; -- cgit v1.2.3 From 8970970f3f3bc3d757fe491e90e608366fb7e604 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 24 Aug 2012 13:25:52 +0300 Subject: Add output and two-way processors to API. Update Mac config stuff. --- io.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 225 insertions(+), 40 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 589abbf4..d4f7535f 100644 --- a/io.c +++ b/io.c @@ -210,6 +210,9 @@ static int str2mode(const char *mode); static int two_way_open(const char *str, struct redirect *rp); static int pty_vs_pipe(const char *command); static void find_input_parser(IOBUF *iop); +static bool find_output_wrapper(awk_output_buf_t *outbuf); +static void init_output_wrapper(awk_output_buf_t *outbuf); +static bool find_two_way_processor(const char *name, struct redirect *rp); static RECVALUE rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state); static RECVALUE rsnullscan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state); @@ -688,7 +691,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) if (do_lint && (redir_exp->flags & STRCUR) == 0) lintwarn(_("expression in `%s' redirection only has numeric value"), what); - redir_exp= force_string(redir_exp); + redir_exp = force_string(redir_exp); str = redir_exp->stptr; if (str == NULL || *str == '\0') @@ -759,7 +762,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) str[redir_exp->stlen] = '\0'; rp->value = str; rp->flag = tflag; - rp->fp = NULL; + init_output_wrapper(& rp->output); rp->iop = NULL; rp->pid = -1; rp->status = 0; @@ -767,7 +770,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) str = rp->value; /* get \0 terminated string */ save_rp = rp; - while (rp->fp == NULL && rp->iop == NULL) { + while (rp->output.fp == NULL && rp->iop == NULL) { if (! new_rp && rp->flag & RED_EOF) { /* * Encountered EOF on file or pipe -- must be cleared @@ -792,12 +795,12 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) (void) flush_io(); os_restore_mode(fileno(stdin)); - if ((rp->fp = popen(str, binmode("w"))) == NULL) + if ((rp->output.fp = popen(str, binmode("w"))) == NULL) fatal(_("can't open pipe `%s' for output (%s)"), str, strerror(errno)); /* set close-on-exec */ - os_close_on_exec(fileno(rp->fp), str, "pipe", "to"); + os_close_on_exec(fileno(rp->output.fp), str, "pipe", "to"); rp->flag |= RED_NOBUF; break; case redirect_pipein: @@ -844,15 +847,16 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) if (mode != NULL) { errno = 0; + rp->output.mode = mode; fd = devopen(str, mode); if (fd > INVALID_HANDLE) { if (fd == fileno(stdin)) - rp->fp = stdin; + rp->output.fp = stdin; else if (fd == fileno(stdout)) - rp->fp = stdout; + rp->output.fp = stdout; else if (fd == fileno(stderr)) - rp->fp = stderr; + rp->output.fp = stderr; else { const char *omode = mode; #if defined(F_GETFL) && defined(O_APPEND) @@ -863,13 +867,13 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) omode = binmode("a"); #endif os_close_on_exec(fd, str, "file", ""); - rp->fp = fdopen(fd, (const char *) omode); + rp->output.fp = fdopen(fd, (const char *) omode); rp->mode = (const char *) mode; /* don't leak file descriptors */ - if (rp->fp == NULL) + if (rp->output.fp == NULL) close(fd); } - if (rp->fp != NULL && os_isatty(fd)) + if (rp->output.fp != NULL && os_isatty(fd)) rp->flag |= RED_NOBUF; /* Move rp to the head of the list. */ @@ -882,9 +886,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) red_head = rp; } } + find_output_wrapper(& rp->output); } - if (rp->fp == NULL && rp->iop == NULL) { + if (rp->output.fp == NULL && rp->iop == NULL) { /* too many files open -- close one and try again */ if (errno == EMFILE || errno == ENFILE) close_one(); @@ -978,16 +983,16 @@ close_one() /* now work back up through the list */ for (rp = rplast; rp != NULL; rp = rp->prev) { /* don't close standard files! */ - if (rp->fp == NULL || rp->fp == stderr || rp->fp == stdout) + if (rp->output.fp == NULL || rp->output.fp == stderr || rp->output.fp == stdout) continue; if ((rp->flag & (RED_FILE|RED_WRITE)) == (RED_FILE|RED_WRITE)) { rp->flag |= RED_USED; errno = 0; - if (fclose(rp->fp) != 0) + if (rp->output.gawk_fclose(rp->output.fp, rp->output.opaque) != 0) warning(_("close of `%s' failed (%s)."), rp->value, strerror(errno)); - rp->fp = NULL; + rp->output.fp = NULL; break; } } @@ -1071,18 +1076,18 @@ close_rp(struct redirect *rp, two_way_close_type how) errno = 0; if ((rp->flag & RED_TWOWAY) != 0) { /* two-way pipe */ /* write end: */ - if ((how == CLOSE_ALL || how == CLOSE_TO) && rp->fp != NULL) { + if ((how == CLOSE_ALL || how == CLOSE_TO) && rp->output.fp != NULL) { #ifdef HAVE_SOCKETS if ((rp->flag & RED_TCP) != 0) - (void) shutdown(fileno(rp->fp), SHUT_WR); + (void) shutdown(fileno(rp->output.fp), SHUT_WR); #endif /* HAVE_SOCKETS */ if ((rp->flag & RED_PTY) != 0) { - fwrite("\004\n", sizeof("\004\n") - 1, 1, rp->fp); - fflush(rp->fp); + rp->output.gawk_fwrite("\004\n", sizeof("\004\n") - 1, 1, rp->output.fp, rp->output.opaque); + rp->output.gawk_fflush(rp->output.fp, rp->output.opaque); } - status = fclose(rp->fp); - rp->fp = NULL; + status = rp->output.gawk_fclose(rp->output.fp, rp->output.opaque); + rp->output.fp = NULL; } /* read end: */ @@ -1100,14 +1105,14 @@ close_rp(struct redirect *rp, two_way_close_type how) } } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) { /* write to pipe */ - status = pclose(rp->fp); + status = pclose(rp->output.fp); if ((BINMODE & 1) != 0) os_setbinmode(fileno(stdin), O_BINARY); - rp->fp = NULL; - } else if (rp->fp != NULL) { /* write to file */ - status = fclose(rp->fp); - rp->fp = NULL; + rp->output.fp = NULL; + } else if (rp->output.fp != NULL) { /* write to file */ + status = rp->output.gawk_fclose(rp->output.fp, rp->output.opaque); + rp->output.fp = NULL; } else if (rp->iop != NULL) { /* read from pipe/file */ if ((rp->flag & RED_PIPE) != 0) /* read from pipe */ status = gawk_pclose(rp); @@ -1130,7 +1135,7 @@ close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how) if (rp == NULL) return 0; - if (rp->fp == stdout || rp->fp == stderr) + if (rp->output.fp == stdout || rp->output.fp == stderr) goto checkwarn; /* bypass closing, remove from list */ if (do_lint && (rp->flag & RED_TWOWAY) == 0 && how != CLOSE_ALL) @@ -1188,7 +1193,7 @@ checkwarn: } /* remove it from the list if closing both or both ends have been closed */ - if (how == CLOSE_ALL || (rp->iop == NULL && rp->fp == NULL)) { + if (how == CLOSE_ALL || (rp->iop == NULL && rp->output.fp == NULL)) { if (rp->next != NULL) rp->next->prev = rp->prev; if (rp->prev != NULL) @@ -1220,8 +1225,8 @@ flush_io() } for (rp = red_head; rp != NULL; rp = rp->next) /* flush both files and pipes, what the heck */ - if ((rp->flag & RED_WRITE) && rp->fp != NULL) { - if (fflush(rp->fp)) { + if ((rp->flag & RED_WRITE) && rp->output.fp != NULL) { + if (rp->output.gawk_fflush(rp->output.fp, rp->output.opaque)) { if (rp->flag & RED_PIPE) warning(_("pipe flush of `%s' failed (%s)."), rp->value, strerror(errno)); @@ -1647,14 +1652,14 @@ two_way_open(const char *str, struct redirect *rp) fd = devopen(str, "rw"); if (fd == INVALID_HANDLE) return false; - rp->fp = fdopen(fd, "w"); - if (rp->fp == NULL) { + rp->output.fp = fdopen(fd, "w"); + if (rp->output.fp == NULL) { close(fd); return false; } newfd = dup(fd); if (newfd < 0) { - fclose(rp->fp); + rp->output.gawk_fclose(rp->output.fp, rp->output.opaque); return false; } os_close_on_exec(fd, str, "socket", "to/from"); @@ -1667,7 +1672,7 @@ two_way_open(const char *str, struct redirect *rp) update_ERRNO_int(rp->iop->errcode); iop_close(rp->iop); rp->iop = NULL; - fclose(rp->fp); + rp->output.gawk_fclose(rp->output.fp, rp->output.opaque); return false; } rp->flag |= RED_SOCKET; @@ -1675,8 +1680,12 @@ two_way_open(const char *str, struct redirect *rp) } #endif /* HAVE_SOCKETS */ + /* case 2: see if an extension wants it */ + if (find_two_way_processor(str, rp)) + return true; + #if defined(HAVE_TERMIOS_H) && ! defined(ZOS_USS) - /* case 2: use ptys for two-way communications to child */ + /* case 3: use ptys for two-way communications to child */ if (! no_ptys && pty_vs_pipe(str)) { static bool initialized = false; static char first_pty_letter; @@ -1876,8 +1885,9 @@ two_way_open(const char *str, struct redirect *rp) * Force read and write ends of two-way connection to * be different fd's so they can be closed independently. */ + rp->output.mode = "w"; if ((dup_master = dup(master)) < 0 - || (rp->fp = fdopen(dup_master, "w")) == NULL) { + || (rp->output.fp = fdopen(dup_master, "w")) == NULL) { iop_close(rp->iop); rp->iop = NULL; (void) close(master); @@ -1885,7 +1895,8 @@ two_way_open(const char *str, struct redirect *rp) if (dup_master > 0) (void) close(dup_master); return false; - } + } else + find_output_wrapper(& rp->output); rp->flag |= RED_PTY; os_close_on_exec(master, str, "pipe", "from"); os_close_on_exec(dup_master, str, "pipe", "to"); @@ -1896,7 +1907,7 @@ two_way_open(const char *str, struct redirect *rp) use_pipes: #ifndef PIPES_SIMULATED /* real pipes */ - /* case 3: two way pipe to a child process */ + /* case 4: two way pipe to a child process */ { int ptoc[2], ctop[2]; int pid; @@ -2033,8 +2044,9 @@ use_pipes: return false; } - rp->fp = fdopen(ptoc[1], "w"); - if (rp->fp == NULL) { + rp->output.fp = fdopen(ptoc[1], "w"); + rp->output.mode = "w"; + if (rp->output.fp == NULL) { iop_close(rp->iop); rp->iop = NULL; (void) close(ctop[0]); @@ -2045,6 +2057,8 @@ use_pipes: return false; } + else + find_output_wrapper(& rp->output); #ifndef __EMX__ os_close_on_exec(ctop[0], str, "pipe", "from"); @@ -2677,6 +2691,124 @@ find_input_parser(IOBUF *iop) } } +/* output wrappers --- for use by extensions */ + +static awk_output_wrapper_t *op_head, *op_tail; + +/* + * register_output_wrapper --- add an output wrapper to the list. + * Same stuff here as for input parsers. + */ + +void +register_output_wrapper(awk_output_wrapper_t *wrapper) +{ + if (wrapper == NULL) + fatal(_("register_output_wrapper: received NULL pointer")); + + wrapper->next = NULL; /* force it */ + if (op_head == NULL) { + op_head = op_tail = wrapper; + } else { + op_tail->next = wrapper; + op_tail = op_tail->next; + } +} + +/* find_output_wrapper --- search the list of output wrappers */ + +static bool +find_output_wrapper(awk_output_buf_t *outbuf) +{ + awk_output_wrapper_t *op, *op2; + + /* if already associated with an output wrapper, bail out early */ + if (outbuf->redirected) + return false; + + op = op2 = NULL; + for (op2 = op_head; op2 != NULL; op2 = op2->next) { + if (op2->can_take_file(outbuf)) { + if (op == NULL) + op = op2; /* found first one */ + else + fatal(_("output wrapper `%s' conflicts with previously installed output wrapper `%s'"), + op2->name, op->name); + } + } + + if (op != NULL) { + if (! op->take_control_of(outbuf)) { + warning(_("output wrapper `%s' failed to open `%s'"), + op->name, outbuf->name); + return false; + } + return true; + } + + return false; +} + + +/* two way processors --- for use by extensions */ + +static awk_two_way_processor_t *tw_head, *tw_tail; + +/* register_two_way_processor --- register a two-way I/O processor, for extensions */ + +void +register_two_way_processor(awk_two_way_processor_t *processor) +{ + if (processor == NULL) + fatal(_("register_output_processor: received NULL pointer")); + + processor->next = NULL; /* force it */ + if (tw_head == NULL) { + tw_head = tw_tail = processor; + } else { + tw_tail->next = processor; + tw_tail = tw_tail->next; + } +} + +/* find_two_way_processor --- search the list of two way processors */ + +static bool +find_two_way_processor(const char *name, struct redirect *rp) +{ + awk_two_way_processor_t *tw, *tw2; + + /* if already associated with i/o, bail out early */ + if ( (rp->iop != NULL && rp->iop->public.fd != INVALID_HANDLE) + || rp->output.fp != NULL) + return false; + + tw = tw2 = NULL; + for (tw2 = tw_head; tw2 != NULL; tw2 = tw2->next) { + if (tw2->can_take_two_way(name)) { + if (tw == NULL) + tw = tw2; /* found first one */ + else + fatal(_("two-way processor `%s' conflicts with previously installed two-way processor `%s'"), + tw2->name, tw->name); + } + } + + if (tw != NULL) { + if (rp->iop == NULL) + rp->iop = iop_alloc(INVALID_HANDLE, name, 0); + if (! tw->take_control_of(name, & rp->iop->public, & rp->output)) { + warning(_("two way processor `%s' failed to open `%s'"), + tw->name, name); + return false; + } + iop_finish(rp->iop); + return true; + } + + return false; +} + /* * IOBUF management is somewhat complicated. In particular, * it is possible and OK for an IOBUF to be allocated with @@ -3601,4 +3733,57 @@ read_with_timeout(int fd, char *buf, size_t size) #endif /* __MINGW32__ */ } +/* + * Dummy pass through functions for default output. + */ + +/* gawk_fwrite --- like fwrite */ + +static size_t +gawk_fwrite(const void *buf, size_t size, size_t count, FILE *fp, void *opaque) +{ + (void) opaque; + return fwrite(buf, size, count, fp); +} + +static int +gawk_fflush(FILE *fp, void *opaque) +{ + (void) opaque; + + return fflush(fp); +} + +static int +gawk_ferror(FILE *fp, void *opaque) +{ + (void) opaque; + + return ferror(fp); +} + +static int +gawk_fclose(FILE *fp, void *opaque) +{ + (void) opaque; + + return fclose(fp); +} + + +/* init_output_wrapper --- initialize the output wrapper */ + +static void +init_output_wrapper(awk_output_buf_t *outbuf) +{ + outbuf->name = NULL; + outbuf->mode = NULL; + outbuf->fp = NULL; + outbuf->opaque = NULL; + outbuf->redirected = false; + outbuf->gawk_fwrite = gawk_fwrite; + outbuf->gawk_fflush = gawk_fflush; + outbuf->gawk_ferror = gawk_ferror; + outbuf->gawk_fclose = gawk_fclose; +} -- cgit v1.2.3 From 1f713af5cd22df0ba9e7bbbde5b2d9eaf527c1ad Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sat, 10 Nov 2012 22:23:03 +0200 Subject: Some VMS fixes. --- io.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index d4f7535f..5f4365c6 100644 --- a/io.c +++ b/io.c @@ -2567,6 +2567,9 @@ find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) size_t src_len; size_t suffix_len; +#ifndef SHLIBEXT /* for vms, for now */ +#define SHLIBEXT "awk" +#endif #define EXTLIB_SUFFIX "." SHLIBEXT src_len = strlen(src); suffix_len = strlen(EXTLIB_SUFFIX); @@ -3702,7 +3705,7 @@ get_read_timeout(IOBUF *iop) static ssize_t read_with_timeout(int fd, char *buf, size_t size) { -#ifndef __MINGW32__ +#if ! defined(__MINGW32__) && ! defined(VMS) fd_set readfds; struct timeval tv; @@ -3728,9 +3731,9 @@ read_with_timeout(int fd, char *buf, size_t size) errno = EAGAIN; #endif return -1; -#else /* __MINGW32__ */ +#else /* __MINGW32__ || VMS */ return read(fd, buf, size); -#endif /* __MINGW32__ */ +#endif /* __MINGW32__ || VMS */ } /* -- cgit v1.2.3 From cafbb82185c4a5fc2608975c048d66017456a038 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 12 Nov 2012 23:13:16 +0200 Subject: Initial changes for VMS building. --- io.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 5f4365c6..2607b6cb 100644 --- a/io.c +++ b/io.c @@ -2567,9 +2567,6 @@ find_source(const char *src, struct stat *stb, int *errcode, int is_extlib) size_t src_len; size_t suffix_len; -#ifndef SHLIBEXT /* for vms, for now */ -#define SHLIBEXT "awk" -#endif #define EXTLIB_SUFFIX "." SHLIBEXT src_len = strlen(src); suffix_len = strlen(EXTLIB_SUFFIX); -- cgit v1.2.3 From df1abb8c0d0b5855af8bb78ecf87f3511807905d Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 14 Nov 2012 20:17:27 +0200 Subject: VMS updates. Should now build, pass some tests. --- io.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index 2607b6cb..45725c5b 100644 --- a/io.c +++ b/io.c @@ -2523,7 +2523,9 @@ do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi) return NULL; } erealloc(path, char *, strlen(path) + strlen(src) + 2, "do_find_source"); +#ifndef VMS strcat(path, "/"); +#endif strcat(path, src); return path; } -- cgit v1.2.3 From 86024b7f014c286daa68c3a0a223ce51f6e13dfa Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 22 Nov 2012 16:11:22 +0200 Subject: Clean up of awk.h. --- io.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'io.c') diff --git a/io.c b/io.c index 45725c5b..b5c25f54 100644 --- a/io.c +++ b/io.c @@ -42,6 +42,10 @@ #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) #endif +#if ! defined(S_ISREG) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + #ifdef HAVE_TERMIOS_H #include #endif @@ -128,6 +132,10 @@ #endif /* HAVE_SOCKETS */ +#ifndef HAVE_SETSID +#define setsid() /* nothing */ +#endif /* HAVE_SETSID */ + #if defined(GAWK_AIX) #undef TANDEM /* AIX defines this in one of its header files */ #endif -- cgit v1.2.3