aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'io.c')
-rw-r--r--io.c723
1 files changed, 382 insertions, 341 deletions
diff --git a/io.c b/io.c
index a7ef2d61..02852f15 100644
--- a/io.c
+++ b/io.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Progamming Language.
@@ -24,43 +24,45 @@
*/
#include "awk.h"
+
#ifndef O_RDONLY
#include <fcntl.h>
#endif
-#include <signal.h>
-extern FILE *popen();
+#ifndef atarist
+#define INVALID_HANDLE (-1)
+#else
+#define INVALID_HANDLE (__SMALLEST_VALID_HANDLE - 1)
+#endif
-static void do_file();
-static IOBUF *nextfile();
-static int get_a_record();
-static int iop_close();
-static IOBUF *iop_alloc();
-static void close_one();
-static int close_redir();
-static IOBUF *gawk_popen();
-static int gawk_pclose();
+static IOBUF *nextfile P((void));
+static int inrec P((IOBUF *iop, int getline_redirect));
+static int iop_close P((IOBUF *iop));
+struct redirect *redirect P((NODE *tree, int *errflg));
+static void close_one P((void));
+static int close_redir P((struct redirect *rp));
+#if (!defined(MSDOS)) && (!defined(atarist))
+static int wait_any P((int interesting));
+#endif
+static IOBUF *gawk_popen P((char *cmd, struct redirect *rp));
+static int gawk_pclose P((struct redirect *rp));
+static int do_pathopen P((char *file));
static struct redirect *red_head = NULL;
-static int getline_redirect = 0; /* "getline <file" being executed */
+static IOBUF *curfile = NULL;
-extern char *line_buf;
extern int output_is_tty;
extern NODE *ARGC_node;
extern NODE *ARGV_node;
extern NODE **fields_arr;
-int field_num;
-
static IOBUF *
nextfile()
{
static int i = 1;
static int files = 0;
- static IOBUF *curfile = NULL;
char *arg;
- char *cp;
- int fd = -1;
+ int fd = INVALID_HANDLE;
if (curfile != NULL && curfile->cnt != EOF)
return curfile;
@@ -68,27 +70,18 @@ nextfile()
arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
if (*arg == '\0')
continue;
- cp = strchr(arg, '=');
- if (cp != NULL) {
- *cp++ = '\0';
- variable(arg)->var_value = make_string(cp, strlen(cp));
- *--cp = '='; /* restore original text of ARGV */
- } else {
+ if (!arg_assign(arg)) {
files++;
- if (STREQ(arg, "-"))
- fd = 0;
- else
- fd = devopen(arg, "r");
- if (fd == -1)
+ fd = devopen(arg, "r");
+ if (fd == INVALID_HANDLE)
fatal("cannot open file `%s' for reading (%s)",
arg, strerror(errno));
/* NOTREACHED */
/* This is a kludge. */
- deref = FILENAME_node->var_value;
- do_deref();
+ unref(FILENAME_node->var_value);
FILENAME_node->var_value =
make_string(arg, strlen(arg));
- FNR_node->var_value->numbr = 0.0;
+ FNR = 0;
i++;
break;
}
@@ -100,129 +93,88 @@ nextfile()
/* FNR is init'ed to 0 */
fd = 0;
}
- if (fd == -1)
+ if (fd == INVALID_HANDLE)
return NULL;
return curfile = iop_alloc(fd);
}
-static IOBUF *
-iop_alloc(fd)
-int fd;
-{
- IOBUF *iop;
- struct stat stb;
-
- /*
- * System V doesn't have the file system block size in the
- * stat structure. So we have to make some sort of reasonable
- * guess. We use stdio's BUFSIZ, since that is what it was
- * meant for in the first place.
- */
-#ifdef BLKSIZE_MISSING
-#define DEFBLKSIZE BUFSIZ
-#else
-#define DEFBLKSIZE (stb.st_blksize ? stb.st_blksize : BUFSIZ)
-#endif
-
- if (fd == -1)
- return NULL;
- emalloc(iop, IOBUF *, sizeof(IOBUF), "nextfile");
- iop->flag = 0;
- if (isatty(fd)) {
- iop->flag |= IOP_IS_TTY;
- iop->size = BUFSIZ;
- } else if (fstat(fd, &stb) == -1)
- fatal("can't stat fd %d (%s)", fd, strerror(errno));
- else if (lseek(fd, 0L, 0) == -1)
- iop->size = DEFBLKSIZE;
- else
- iop->size = (stb.st_size < DEFBLKSIZE ?
- stb.st_size+1 : DEFBLKSIZE);
- errno = 0;
- iop->fd = fd;
- emalloc(iop->buf, char *, iop->size, "nextfile");
- iop->off = iop->buf;
- iop->cnt = 0;
- iop->secsiz = iop->size < BUFSIZ ? iop->size : BUFSIZ;
- emalloc(iop->secbuf, char *, iop->secsiz, "nextfile");
- return iop;
-}
-
void
-do_input()
+set_FNR()
{
- IOBUF *iop;
- extern int exiting;
-
- while ((iop = nextfile()) != NULL) {
- do_file(iop);
- if (exiting)
- break;
- }
+ FNR = (int) FNR_node->var_value->numbr;
}
-static int
-iop_close(iop)
-IOBUF *iop;
+void
+set_NR()
{
- int ret;
-
- ret = close(iop->fd);
- if (ret == -1)
- warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
- free(iop->buf);
- free(iop->secbuf);
- free((char *)iop);
- return ret == -1 ? 1 : 0;
+ NR = (int) NR_node->var_value->numbr;
}
/*
* This reads in a record from the input file
*/
static int
-inrec(iop)
+inrec(iop, getline_redirect)
IOBUF *iop;
+int getline_redirect;
{
- int cnt;
+ char *begin;
+ register int cnt;
int retval = 0;
- cnt = get_a_record(&line_buf, iop);
+ cnt = get_a_record(&begin, iop, *RS);
if (cnt == EOF) {
cnt = 0;
retval = 1;
- } else {
- if (!getline_redirect) {
- assign_number(&NR_node->var_value,
- NR_node->var_value->numbr + 1.0);
- assign_number(&FNR_node->var_value,
- FNR_node->var_value->numbr + 1.0);
- }
+ } else if (!getline_redirect) {
+ NR += 1;
+ FNR += 1;
}
- set_record(line_buf, cnt);
+ set_record(begin, cnt, 1);
return retval;
}
-static void
-do_file(iop)
+static int
+iop_close(iop)
IOBUF *iop;
{
- /* This is where it spends all its time. The infamous MAIN LOOP */
- if (inrec(iop) == 0)
- while (interpret(expression_value) && inrec(iop) == 0)
- ;
- (void) iop_close(iop);
+ int ret;
+
+ if (iop == NULL)
+ return 0;
+ errno = 0;
+
+ /* Work around bug in UNICOS popen, but it shouldn't hurt elsewhere */
+ if (iop->fd < 3)
+ ret = 0;
+ else
+ ret = close(iop->fd);
+ if (ret == -1)
+ warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
+ free(iop->buf);
+ free(iop->secbuf);
+ if (iop == curfile)
+ curfile = NULL; /* kludge -- gotta do better */
+ free((char *)iop);
+ return ret == -1 ? 1 : 0;
}
-int
-get_rs()
+void
+do_input()
{
- register NODE *tmp;
+ IOBUF *iop;
+ extern int exiting;
- tmp = force_string(RS_node->var_value);
- if (tmp->stlen == 0)
- return 0;
- return *(tmp->stptr);
+ while ((iop = nextfile()) != NULL) {
+ if (inrec(iop, 0) == 0)
+ while (interpret(expression_value) && inrec(iop, 0) == 0)
+ ;
+ (void) iop_close(iop);
+ iop = NULL;
+ if (exiting)
+ break;
+ }
}
/* Redirection for printf and print commands */
@@ -263,7 +215,8 @@ int *errflg;
tmp = force_string(tree_eval(tree->subnode));
str = tmp->stptr;
for (rp = red_head; rp != NULL; rp = rp->next)
- if (STREQ(rp->value, str)
+ if (strlen(rp->value) == tmp->stlen
+ && STREQN(rp->value, str, tmp->stlen)
&& ((rp->flag & ~RED_NOBUF) == tflag
|| (outflag
&& (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
@@ -272,12 +225,14 @@ int *errflg;
emalloc(rp, struct redirect *, sizeof(struct redirect),
"redirect");
emalloc(str, char *, tmp->stlen+1, "redirect");
- memcpy(str, tmp->stptr, tmp->stlen+1);
+ memcpy(str, tmp->stptr, tmp->stlen);
+ str[tmp->stlen] = '\0';
rp->value = str;
rp->flag = tflag;
- rp->offset = 0;
rp->fp = NULL;
rp->iop = NULL;
+ rp->pid = 0; /* unlikely that we're worried about init */
+ rp->status = 0;
/* maintain list in most-recently-used first order */
if (red_head)
red_head->prev = rp;
@@ -291,6 +246,8 @@ int *errflg;
switch (tree->type) {
case Node_redirect_output:
mode = "w";
+ if (rp->flag & RED_USED)
+ mode = "a";
break;
case Node_redirect_append:
mode = "a";
@@ -316,15 +273,26 @@ int *errflg;
}
if (mode != NULL) {
fd = devopen(str, mode);
- if (fd != -1) {
- rp->fp = fdopen(fd, mode);
+ if (fd > INVALID_HANDLE) {
+ if (fd == fileno(stdin))
+ rp->fp = stdin;
+ else if (fd == fileno(stdout))
+ rp->fp = stdout;
+ else if (fd == fileno(stderr))
+ rp->fp = stderr;
+ else
+ rp->fp = fdopen(fd, mode);
if (isatty(fd))
rp->flag |= RED_NOBUF;
}
}
if (rp->fp == NULL && rp->iop == NULL) {
/* too many files open -- close one and try again */
+#ifdef atarist
+ if (errno == EMFILE)
+#else
if (errno == ENFILE || errno == EMFILE)
+#endif
close_one();
else {
/*
@@ -341,15 +309,13 @@ int *errflg;
|| tree->type == Node_redirect_append)
fatal("can't redirect %s `%s' (%s)",
direction, str, strerror(errno));
- else
+ else {
+ free_temp(tmp);
return NULL;
+ }
}
}
}
- if (rp->offset != 0) /* this file was previously open */
- if (fseek(rp->fp, rp->offset, 0) == -1)
- fatal("can't seek to %ld on `%s' (%s)",
- rp->offset, str, strerror(errno));
free_temp(tmp);
return rp;
}
@@ -366,7 +332,8 @@ close_one()
/* now work back up through the list */
for (rp = rplast; rp != NULL; rp = rp->prev)
if (rp->fp && (rp->flag & RED_FILE)) {
- rp->offset = ftell(rp->fp);
+ rp->flag |= RED_USED;
+ errno = 0;
if (fclose(rp->fp))
warning("close of \"%s\" failed (%s).",
rp->value, strerror(errno));
@@ -387,14 +354,17 @@ NODE *tree;
tmp = force_string(tree_eval(tree->subnode));
for (rp = red_head; rp != NULL; rp = rp->next) {
- if (STREQ(rp->value, tmp->stptr))
+ if (strlen(rp->value) == tmp->stlen
+ && STREQN(rp->value, tmp->stptr, tmp->stlen))
break;
}
free_temp(tmp);
if (rp == NULL) /* no match */
return tmp_number((AWKNUM) 0.0);
fflush(stdout); /* synchronize regular output */
- return tmp_number((AWKNUM)close_redir(rp));
+ tmp = tmp_number((AWKNUM)close_redir(rp));
+ rp = NULL;
+ return tmp;
}
static int
@@ -403,6 +373,9 @@ register struct redirect *rp;
{
int status = 0;
+ if (rp == NULL)
+ return 0;
+ errno = 0;
if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE))
status = pclose(rp->fp);
else if (rp->fp)
@@ -410,9 +383,10 @@ register struct redirect *rp;
else if (rp->iop) {
if (rp->flag & RED_PIPE)
status = gawk_pclose(rp);
- else
+ else {
status = iop_close(rp->iop);
-
+ rp->iop = NULL;
+ }
}
/* SVR4 awk checks and warns about status of close */
if (status)
@@ -449,13 +423,15 @@ 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 ((rp->flag & RED_WRITE) && rp->fp != NULL) {
+ errno = 0;
if (fflush(rp->fp)) {
warning("%s flush of \"%s\" failed (%s).",
(rp->flag & RED_PIPE) ? "pipe" :
"file", rp->value, strerror(errno));
status++;
}
+ }
return status;
}
@@ -463,23 +439,29 @@ int
close_io ()
{
register struct redirect *rp;
+ register struct redirect *next;
int status = 0;
- for (rp = red_head; rp != NULL; rp = rp->next)
+ for (rp = red_head; rp != NULL; rp = next) {
+ next = rp->next;
if (close_redir(rp))
status++;
+ rp = NULL;
+ }
return status;
}
/* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
+
int
devopen (name, mode)
char *name, *mode;
{
- int openfd = -1;
+ int openfd = INVALID_HANDLE;
FILE *fdopen ();
- char *cp;
+ char *cp, *ptr;
int flag = 0;
+ struct stat buf;
switch(mode[0]) {
case 'r':
@@ -497,37 +479,95 @@ char *name, *mode;
cant_happen();
}
-#if defined(STRICT) || defined(NO_DEV_FD)
- return (open (name, flag, 0666));
-#else
- if (strict)
- return (open (name, flag, 0666));
+#ifdef VMS
+ if ((openfd = vms_devopen(name)) >= 0)
+ return openfd;
+# define strcmp strcasecmp /* VMS filenames are not case sensitive; */
+# define strncmp strncasecmp /* strncmp() is used by STREQN() below. */
+#endif /*VMS*/
- if (!STREQN (name, "/dev/", 5))
- return (open (name, flag, 0666));
- else
+ if (STREQ(name, "-"))
+ openfd = fileno(stdin);
+ else if (STREQN(name, "/dev/", 5) && stat(name, &buf) == -1) {
cp = name + 5;
- /* XXX - first three tests ignore mode */
- if (STREQ(cp, "stdin"))
- return (0);
- else if (STREQ(cp, "stdout"))
- return (1);
- else if (STREQ(cp, "stderr"))
- return (2);
- else if (STREQN(cp, "fd/", 3)) {
- cp += 3;
- if (sscanf (cp, "%d", & openfd) == 1 && openfd >= 0)
- /* got something */
- return openfd;
- else
- return -1;
- } else
- return (open (name, flag, 0666));
+ /* XXX - first three tests ignore mode */
+ if (STREQ(cp, "stdin") && (flag & O_RDONLY))
+ openfd = fileno(stdin);
+ else if (STREQ(cp, "stdout") && (flag & O_WRONLY))
+ openfd = fileno(stdout);
+ else if (STREQ(cp, "stderr") && (flag & O_WRONLY))
+ openfd = fileno(stderr);
+ else if (STREQN(cp, "fd/", 3)) {
+ cp += 3;
+ openfd = strtol(cp, &ptr, 10);
+ if (openfd <= INVALID_HANDLE || ptr == cp)
+ openfd = INVALID_HANDLE;
+#ifdef VMS
+ } else if (STREQ(cp, "null")) {
+ name = "NL:"; /* "/dev/null" => "NL:" */
+ } else if (STREQ(cp, "tty")) {
+ name = "TT:"; /* "/dev/tty" => "TT:" */
+# undef strcmp
+# undef strncmp
+#endif /*VMS*/
+ }
+ }
+
+ if (openfd != INVALID_HANDLE)
+ return openfd;
+ else
+ return open(name, flag, 0666);
+}
+
+#if defined(MSDOS) || defined(atarist)
+#define PIPES_SIMULATED
#endif
+
+#ifndef PIPES_SIMULATED
+ /* real pipes */
+static int
+wait_any(interesting)
+int interesting; /* pid of interest, if any */
+{
+ SIGTYPE (*hstat)(), (*istat)(), (*qstat)();
+ int pid;
+ int status = 0;
+ struct redirect *redp;
+ extern int errno;
+
+ hstat = signal(SIGHUP, SIG_IGN);
+ istat = signal(SIGINT, SIG_IGN);
+ qstat = signal(SIGQUIT, SIG_IGN);
+ for (;;) {
+ pid = wait(&status);
+ if (interesting && pid == interesting) {
+ break;
+ } else if (pid != -1) {
+ for (redp = red_head; redp != NULL; redp = redp->next)
+ if (pid == redp->pid) {
+ redp->pid = -1;
+ redp->status = status;
+ if (redp->fp) {
+ pclose(redp->fp);
+ redp->fp = 0;
+ }
+ if (redp->iop) {
+ (void) iop_close(redp->iop);
+ redp->iop = 0;
+ }
+ break;
+ }
+ }
+ if (pid == -1 && errno == ECHILD)
+ break;
+ }
+ signal(SIGHUP, hstat);
+ signal(SIGINT, istat);
+ signal(SIGQUIT, qstat);
+ return(status);
}
-#ifndef MSDOS
static IOBUF *
gawk_popen(cmd, rp)
char *cmd;
@@ -536,21 +576,25 @@ struct redirect *rp;
int p[2];
register int pid;
- rp->pid = -1;
- rp->iop = NULL;
+ (void) wait_any(0); /* wait for outstanding processes */
if (pipe(p) < 0)
- return NULL;
+ fatal("cannot open pipe \"%s\" (%s)", cmd, strerror(errno));
if ((pid = fork()) == 0) {
- close(p[0]);
- dup2(p[1], 1);
- close(p[1]);
+ if (close(1) == -1)
+ fatal("close of stdout in child failed (%s)",
+ strerror(errno));
+ if (dup(p[1]) != 1)
+ fatal("dup of pipe failed (%s)", strerror(errno));
+ if (close(p[0]) == -1 || close(p[1]) == -1)
+ fatal("close of pipe failed (%s)", strerror(errno));
execl("/bin/sh", "sh", "-c", cmd, 0);
_exit(127);
}
if (pid == -1)
- return NULL;
+ fatal("cannot fork for \"%s\" (%s)", cmd, strerror(errno));
rp->pid = pid;
- close(p[1]);
+ if (close(p[1]) == -1)
+ fatal("close of pipe failed (%s)", strerror(errno));
return (rp->iop = iop_alloc(p[0]));
}
@@ -558,40 +602,47 @@ static int
gawk_pclose(rp)
struct redirect *rp;
{
- SIGTYPE (*hstat)(), (*istat)(), (*qstat)();
- int pid;
- int status;
- struct redirect *redp;
+ (void) iop_close(rp->iop);
+ rp->iop = NULL;
- iop_close(rp->iop);
+ /* process previously found, return stored status */
if (rp->pid == -1)
- return rp->status;
- hstat = signal(SIGHUP, SIG_IGN);
- istat = signal(SIGINT, SIG_IGN);
- qstat = signal(SIGQUIT, SIG_IGN);
- for (;;) {
- pid = wait(&status);
- if (pid == -1 && errno == ECHILD)
- break;
- else if (pid == rp->pid) {
- rp->pid = -1;
- rp->status = status;
- break;
- } else {
- for (redp = red_head; redp != NULL; redp = redp->next)
- if (pid == redp->pid) {
- redp->pid = -1;
- redp->status = status;
- break;
- }
- }
- }
- signal(SIGHUP, hstat);
- signal(SIGINT, istat);
- signal(SIGQUIT, qstat);
- return(rp->status);
+ return (rp->status >> 8) & 0xFF;
+ rp->status = wait_any(rp->pid);
+ rp->pid = -1;
+ return (rp->status >> 8) & 0xFF;
}
-#else
+
+#else /* PIPES_SUMULATED */
+ /* use temporary file rather than pipe */
+
+#ifdef VMS
+static IOBUF *
+gawk_popen(cmd, rp)
+char *cmd;
+struct redirect *rp;
+{
+ FILE *current;
+
+ if ((current = popen(cmd, "r")) == NULL)
+ return NULL;
+ return (rp->iop = iop_alloc(fileno(current)));
+}
+
+static int
+gawk_pclose(rp)
+struct redirect *rp;
+{
+ int rval, aval, fd = rp->iop->fd;
+ FILE *kludge = fdopen(fd, "r"); /* pclose needs FILE* w/ right fileno */
+
+ rp->iop->fd = dup(fd); /* kludge to allow close() + pclose() */
+ rval = iop_close(rp->iop);
+ aval = pclose(kludge);
+ return (rval < 0 ? rval : aval);
+}
+#else /* VMS */
+
static
struct {
char *command;
@@ -613,7 +664,7 @@ struct redirect *rp;
return NULL;
sprintf(cmdbuf,"%s > %s", cmd, name);
system(cmdbuf);
- if ((current = open(name,O_RDONLY)) == -1)
+ if ((current = open(name,O_RDONLY)) == INVALID_HANDLE)
return NULL;
pipes[current].name = name;
pipes[current].command = strdup(cmd);
@@ -628,6 +679,7 @@ struct redirect *rp;
int rval;
rval = iop_close(rp->iop);
+ rp->iop = NULL;
/* check for an open file */
if (pipes[cur].name == NULL)
@@ -638,134 +690,20 @@ struct redirect *rp;
free(pipes[cur].command);
return rval;
}
-#endif
+#endif /* VMS */
-#define DO_END_OF_BUF len = bp - iop->off;\
- used = last - start;\
- while (len + used > iop->secsiz) {\
- iop->secsiz *= 2;\
- erealloc(iop->secbuf,char *,iop->secsiz,"get");\
- }\
- last = iop->secbuf + used;\
- start = iop->secbuf;\
- memcpy(last, iop->off, len);\
- last += len;\
- iop->cnt = read(iop->fd, iop->buf, iop->size);\
- if (iop->cnt < 0)\
- return iop->cnt;\
- end_data = iop->buf + iop->cnt;\
- iop->off = bp = iop->buf;
-
-#define DO_END_OF_DATA iop->cnt = read(iop->fd, end_data, end_buf - end_data);\
- if (iop->cnt < 0)\
- return iop->cnt;\
- end_data += iop->cnt;\
- if (iop->cnt == 0)\
- break;\
- iop->cnt = end_data - iop->buf;
-
-static int
-get_a_record(res, iop)
-char **res;
-IOBUF *iop;
-{
- register char *end_data;
- register char *end_buf;
- char *start;
- register char *bp;
- register char *last;
- int len, used;
- register char rs = get_rs();
-
- if (iop->cnt < 0)
- return iop->cnt;
- if ((iop->flag & IOP_IS_TTY) && output_is_tty)
- fflush(stdout);
- end_data = iop->buf + iop->cnt;
- if (iop->off >= end_data) {
- iop->cnt = read(iop->fd, iop->buf, iop->size);
- if (iop->cnt <= 0)
- return iop->cnt = EOF;
- end_data = iop->buf + iop->cnt;
- iop->off = iop->buf;
- }
- last = start = bp = iop->off;
- end_buf = iop->buf + iop->size;
- if (rs == 0) {
- while (!(*bp == '\n' && bp != iop->buf && bp[-1] == '\n')) {
- if (++bp == end_buf) {
- DO_END_OF_BUF
- }
- if (bp == end_data) {
- DO_END_OF_DATA
- }
- }
- if (*bp == '\n' && bp != iop->off && bp[-1] == '\n') {
- int tmp = 0;
-
- /* allow for more than two newlines */
- while (*bp == '\n') {
- tmp++;
- if (++bp == end_buf) {
- DO_END_OF_BUF
- }
- if (bp == end_data) {
- DO_END_OF_DATA
- }
- }
- iop->off = bp;
- bp -= 1 + tmp;
- } else if (bp != iop->buf && bp[-1] != '\n') {
- warning("record not terminated");
- iop->off = bp + 2;
- } else {
- bp--;
- iop->off = bp + 2;
- }
- } else {
- while (*bp++ != rs) {
- if (bp == end_buf) {
- DO_END_OF_BUF
- }
- if (bp == end_data) {
- DO_END_OF_DATA
- }
- }
- if (*--bp != rs) {
- warning("record not terminated");
- bp++;
- }
- iop->off = bp + 1;
- }
- if (start == iop->secbuf) {
- len = bp - iop->buf;
- if (len > 0) {
- used = last - start;
- while (len + used > iop->secsiz) {
- iop->secsiz *= 2;
- erealloc(iop->secbuf,char *,iop->secsiz,"get2");
- }
- last = iop->secbuf + used;
- start = iop->secbuf;
- memcpy(last, iop->buf, len);
- last += len;
- }
- } else
- last = bp;
- *last = '\0';
- *res = start;
- return last - start;
-}
+#endif /* PIPES_SUMULATED */
NODE *
do_getline(tree)
NODE *tree;
{
- struct redirect *rp;
+ struct redirect *rp = NULL;
IOBUF *iop;
int cnt;
NODE **lhs;
int redir_error = 0;
+ int getline_redirect = 0;
if (tree->rnode == NULL) { /* no redirection */
iop = nextfile();
@@ -779,33 +717,136 @@ NODE *tree;
getline_redirect++;
}
if (tree->lnode == NULL) { /* no optional var. -- read in $0 */
- if (inrec(iop) != 0) {
- getline_redirect = 0;
+ if (inrec(iop, getline_redirect) != 0)
return tmp_number((AWKNUM) 0.0);
- }
} else { /* read in a named variable */
char *s = NULL;
+ Func_ptr after_assign = NULL;
- lhs = get_lhs(tree->lnode, 1);
- cnt = get_a_record(&s, iop);
+ lhs = get_lhs(tree->lnode, &after_assign);
+ cnt = get_a_record(&s, iop, *RS);
if (!getline_redirect) {
- assign_number(&NR_node->var_value,
- NR_node->var_value->numbr + 1.0);
- assign_number(&FNR_node->var_value,
- FNR_node->var_value->numbr + 1.0);
+ NR += 1;
+ FNR += 1;
}
if (cnt == EOF) {
- getline_redirect = 0;
- free(s);
+ if (rp) {
+ (void) iop_close(iop);
+ rp->iop = NULL;
+ }
return tmp_number((AWKNUM) 0.0);
}
+ unref(*lhs);
*lhs = make_string(s, strlen(s));
- do_deref();
/* we may have to regenerate $0 here! */
- if (field_num == 0)
- set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
- field_num = -1;
+ if (after_assign)
+ (*after_assign)();
}
- getline_redirect = 0;
return tmp_number((AWKNUM) 1.0);
}
+
+int
+pathopen (file)
+char *file;
+{
+ int fd = do_pathopen(file);
+
+#ifdef DEFAULT_FILETYPE
+ if (!strict && fd <= INVALID_HANDLE) {
+ char *file_awk;
+ int save = errno;
+#ifdef VMS
+ int vms_save = vaxc$errno;
+#endif
+
+ /* append ".awk" and try again */
+ emalloc(file_awk, char *, strlen(file) +
+ sizeof(DEFAULT_FILETYPE) + 1, "pathopen");
+ strcat(strcpy(file_awk, file), DEFAULT_FILETYPE);
+ fd = do_pathopen(file_awk);
+ free(file_awk);
+ if (fd <= INVALID_HANDLE) {
+ errno = save;
+#ifdef VMS
+ vaxc$errno = vms_save;
+#endif
+ }
+ }
+#endif /*DEFAULT_FILETYPE*/
+
+ return fd;
+}
+
+static int
+do_pathopen (file)
+char *file;
+{
+ static char *savepath = DEFPATH; /* defined in config.h */
+ static int first = 1;
+ char *awkpath, *cp;
+ char trypath[BUFSIZ];
+ int fd;
+
+ if (STREQ(file, "-"))
+ return (0);
+
+ if (strict)
+ return (open (file, 0));
+
+ if (first) {
+ first = 0;
+ if ((awkpath = getenv ("AWKPATH")) != NULL && *awkpath)
+ savepath = awkpath; /* used for restarting */
+ }
+ awkpath = savepath;
+
+ /* some kind of path name, no search */
+#ifdef VMS /* (strchr not equal implies either or both not NULL) */
+ if (strchr(file, ':') != strchr(file, ']')
+ || strchr(file, '>') != strchr(file, '/'))
+#else /*!VMS*/
+#ifdef MSDOS
+ if (strchr(file, '/') != strchr(file, '\\')
+ || strchr(file, ':') != NULL)
+#else
+ if (strchr(file, '/') != NULL)
+#endif /*MSDOS*/
+#endif /*VMS*/
+ return (devopen (file, "r"));
+
+ do {
+ trypath[0] = '\0';
+ /* this should take into account limits on size of trypath */
+ for (cp = trypath; *awkpath && *awkpath != ENVSEP; )
+ *cp++ = *awkpath++;
+
+ if (cp != trypath) { /* nun-null element in path */
+ /* add directory punctuation only if needed */
+#ifdef VMS
+ if (strchr(":]>/", *(cp-1)) == NULL)
+#else
+#ifdef MSDOS
+ if (strchr(":\\/", *(cp-1)) == NULL)
+#else
+ if (*(cp-1) != '/')
+#endif
+#endif
+ *cp++ = '/';
+ /* append filename */
+ strcpy (cp, file);
+ } else
+ strcpy (trypath, file);
+ if ((fd = devopen (trypath, "r")) >= 0)
+ return (fd);
+
+ /* no luck, keep going */
+ if(*awkpath == ENVSEP && awkpath[1] != '\0')
+ awkpath++; /* skip colon */
+ } while (*awkpath);
+ /*
+ * You might have one of the awk
+ * paths defined, WITHOUT the current working directory in it.
+ * Therefore try to open the file in the current directory.
+ */
+ return (devopen(file, "r"));
+}