home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / compcomp / gnuawk / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-10  |  17.1 KB  |  812 lines

  1. /*
  2.  * io.c - routines for dealing with input and output and records
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27. #ifndef O_RDONLY
  28. #include <fcntl.h>
  29. #endif
  30. #include <signal.h>
  31.  
  32. extern FILE *popen();
  33.  
  34. static void do_file();
  35. static IOBUF *nextfile();
  36. static int get_a_record();
  37. static int iop_close();
  38. static IOBUF *iop_alloc();
  39. static void close_one();
  40. static int close_redir();
  41. static IOBUF *gawk_popen();
  42. static int gawk_pclose();
  43.  
  44. static struct redirect *red_head = NULL;
  45. static int getline_redirect = 0;    /* "getline <file" being executed */
  46.  
  47. extern char *line_buf;
  48. extern int output_is_tty;
  49. extern NODE *ARGC_node;
  50. extern NODE *ARGV_node;
  51. extern NODE **fields_arr;
  52.  
  53. int field_num;
  54.  
  55. static IOBUF *
  56. nextfile()
  57. {
  58.     static int i = 1;
  59.     static int files = 0;
  60.     static IOBUF *curfile = NULL;
  61.     char *arg;
  62.     char *cp;
  63.     int fd = -1;
  64.  
  65.     if (curfile != NULL && curfile->cnt != EOF)
  66.         return curfile;
  67.     for (; i < (int) (ARGC_node->lnode->numbr); i++) {
  68.         arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
  69.         if (*arg == '\0')
  70.             continue;
  71.         cp = strchr(arg, '=');
  72.         if (cp != NULL) {
  73.             *cp++ = '\0';
  74.             variable(arg)->var_value = make_string(cp, strlen(cp));
  75.             *--cp = '=';    /* restore original text of ARGV */
  76.         } else {
  77.             files++;
  78.             if (STREQ(arg, "-"))
  79.                 fd = 0;
  80.             else
  81.                 fd = devopen(arg, "r");
  82.             if (fd == -1)
  83.                 fatal("cannot open file `%s' for reading (%s)",
  84.                     arg, strerror(errno));
  85.                 /* NOTREACHED */
  86.             /* This is a kludge.  */
  87.             deref = FILENAME_node->var_value;
  88.             do_deref();
  89.             FILENAME_node->var_value =
  90.                 make_string(arg, strlen(arg));
  91.             FNR_node->var_value->numbr = 0.0;
  92.             i++;
  93.             break;
  94.         }
  95.     }
  96.     if (files == 0) {
  97.         files++;
  98.         /* no args. -- use stdin */
  99.         /* FILENAME is init'ed to "-" */
  100.         /* FNR is init'ed to 0 */
  101.         fd = 0;
  102.     }
  103.     if (fd == -1)
  104.         return NULL;
  105.     return curfile = iop_alloc(fd);
  106. }
  107.  
  108. static IOBUF *
  109. iop_alloc(fd)
  110. int fd;
  111. {
  112.     IOBUF *iop;
  113.     struct stat stb;
  114.  
  115.     /*
  116.      * System V doesn't have the file system block size in the
  117.      * stat structure. So we have to make some sort of reasonable
  118.      * guess. We use stdio's BUFSIZ, since that is what it was
  119.      * meant for in the first place.
  120.      */
  121. #ifdef BLKSIZE_MISSING
  122. #define    DEFBLKSIZE    BUFSIZ
  123. #else
  124. #define DEFBLKSIZE    (stb.st_blksize ? stb.st_blksize : BUFSIZ)
  125. #endif
  126.  
  127.     if (fd == -1)
  128.         return NULL;
  129.     emalloc(iop, IOBUF *, sizeof(IOBUF), "nextfile");
  130.     iop->flag = 0;
  131.     if (isatty(fd)) {
  132.         iop->flag |= IOP_IS_TTY;
  133.         iop->size = BUFSIZ;
  134.     } else if (fstat(fd, &stb) == -1)
  135.         fatal("can't stat fd %d (%s)", fd, strerror(errno));
  136.     else if (lseek(fd, 0L, 0) == -1)
  137.         iop->size = DEFBLKSIZE;
  138.     else
  139.         iop->size = (stb.st_size < DEFBLKSIZE ?
  140.                 stb.st_size+1 : DEFBLKSIZE);
  141.     errno = 0;
  142.     iop->fd = fd;
  143.     emalloc(iop->buf, char *, iop->size, "nextfile");
  144.     iop->off = iop->buf;
  145.     iop->cnt = 0;
  146.     iop->secsiz = iop->size < BUFSIZ ? iop->size : BUFSIZ;
  147.     emalloc(iop->secbuf, char *, iop->secsiz, "nextfile");
  148.     return iop;
  149. }
  150.  
  151. void
  152. do_input()
  153. {
  154.     IOBUF *iop;
  155.     extern int exiting;
  156.  
  157.     while ((iop = nextfile()) != NULL) {
  158.         do_file(iop);
  159.         if (exiting)
  160.             break;
  161.     }
  162. }
  163.  
  164. static int
  165. iop_close(iop)
  166. IOBUF *iop;
  167. {
  168.     int ret;
  169.  
  170.     ret = close(iop->fd);
  171.     if (ret == -1)
  172.         warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
  173.     free(iop->buf);
  174.     free(iop->secbuf);
  175.     free((char *)iop);
  176.     return ret == -1 ? 1 : 0;
  177. }
  178.  
  179. /*
  180.  * This reads in a record from the input file
  181.  */
  182. static int
  183. inrec(iop)
  184. IOBUF *iop;
  185. {
  186.     int cnt;
  187.     int retval = 0;
  188.  
  189.     cnt = get_a_record(&line_buf, iop);
  190.     if (cnt == EOF) {
  191.         cnt = 0;
  192.         retval = 1;
  193.     } else {
  194.         if (!getline_redirect) {
  195.             assign_number(&NR_node->var_value,
  196.                 NR_node->var_value->numbr + 1.0);
  197.             assign_number(&FNR_node->var_value,
  198.                 FNR_node->var_value->numbr + 1.0);
  199.         }
  200.     }
  201.     set_record(line_buf, cnt);
  202.  
  203.     return retval;
  204. }
  205.  
  206. static void
  207. do_file(iop)
  208. IOBUF *iop;
  209. {
  210.     /* This is where it spends all its time.  The infamous MAIN LOOP */
  211.     if (inrec(iop) == 0)
  212.         while (interpret(expression_value) && inrec(iop) == 0)
  213.             ;
  214.     (void) iop_close(iop);
  215. }
  216.  
  217. int
  218. get_rs()
  219. {
  220.     register NODE *tmp;
  221.  
  222.     tmp = force_string(RS_node->var_value);
  223.     if (tmp->stlen == 0)
  224.         return 0;
  225.     return *(tmp->stptr);
  226. }
  227.  
  228. /* Redirection for printf and print commands */
  229. struct redirect *
  230. redirect(tree, errflg)
  231. NODE *tree;
  232. int *errflg;
  233. {
  234.     register NODE *tmp;
  235.     register struct redirect *rp;
  236.     register char *str;
  237.     int tflag = 0;
  238.     int outflag = 0;
  239.     char *direction = "to";
  240.     char *mode;
  241.     int fd;
  242.  
  243.     switch (tree->type) {
  244.     case Node_redirect_append:
  245.         tflag = RED_APPEND;
  246.     case Node_redirect_output:
  247.         outflag = (RED_FILE|RED_WRITE);
  248.         tflag |= outflag;
  249.         break;
  250.     case Node_redirect_pipe:
  251.         tflag = (RED_PIPE|RED_WRITE);
  252.         break;
  253.     case Node_redirect_pipein:
  254.         tflag = (RED_PIPE|RED_READ);
  255.         break;
  256.     case Node_redirect_input:
  257.         tflag = (RED_FILE|RED_READ);
  258.         break;
  259.     default:
  260.         fatal ("invalid tree type %d in redirect()", tree->type);
  261.         break;
  262.     }
  263.     tmp = force_string(tree_eval(tree->subnode));
  264.     str = tmp->stptr;
  265.     for (rp = red_head; rp != NULL; rp = rp->next)
  266.         if (STREQ(rp->value, str)
  267.             && ((rp->flag & ~RED_NOBUF) == tflag
  268.             || (outflag
  269.                 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
  270.             break;
  271.     if (rp == NULL) {
  272.         emalloc(rp, struct redirect *, sizeof(struct redirect),
  273.             "redirect");
  274.         emalloc(str, char *, tmp->stlen+1, "redirect");
  275.         memcpy(str, tmp->stptr, tmp->stlen+1);
  276.         rp->value = str;
  277.         rp->flag = tflag;
  278.         rp->offset = 0;
  279.         rp->fp = NULL;
  280.         rp->iop = NULL;
  281.         /* maintain list in most-recently-used first order */
  282.         if (red_head)
  283.             red_head->prev = rp;
  284.         rp->prev = NULL;
  285.         rp->next = red_head;
  286.         red_head = rp;
  287.     }
  288.     while (rp->fp == NULL && rp->iop == NULL) {
  289.         mode = NULL;
  290.         errno = 0;
  291.         switch (tree->type) {
  292.         case Node_redirect_output:
  293.             mode = "w";
  294.             break;
  295.         case Node_redirect_append:
  296.             mode = "a";
  297.             break;
  298.         case Node_redirect_pipe:
  299.             if ((rp->fp = popen(str, "w")) == NULL)
  300.                 fatal("can't open pipe (\"%s\") for output (%s)",
  301.                     str, strerror(errno));
  302.             rp->flag |= RED_NOBUF;
  303.             break;
  304.         case Node_redirect_pipein:
  305.             direction = "from";
  306.             if (gawk_popen(str, rp) == NULL)
  307.                 fatal("can't open pipe (\"%s\") for input (%s)",
  308.                     str, strerror(errno));
  309.             break;
  310.         case Node_redirect_input:
  311.             direction = "from";
  312.             rp->iop = iop_alloc(devopen(str, "r"));
  313.             break;
  314.         default:
  315.             cant_happen();
  316.         }
  317.         if (mode != NULL) {
  318.             fd = devopen(str, mode);
  319.             if (fd != -1) {
  320.                 rp->fp = fdopen(fd, mode);
  321.                 if (isatty(fd))
  322.                     rp->flag |= RED_NOBUF;
  323.             }
  324.         }
  325.         if (rp->fp == NULL && rp->iop == NULL) {
  326.             /* too many files open -- close one and try again */
  327.             if (errno == ENFILE || errno == EMFILE)
  328.                 close_one();
  329.             else {
  330.                 /*
  331.                  * Some other reason for failure.
  332.                  *
  333.                  * On redirection of input from a file,
  334.                  * just return an error, so e.g. getline
  335.                  * can return -1.  For output to file,
  336.                  * complain. The shell will complain on
  337.                  * a bad command to a pipe.
  338.                  */
  339.                 *errflg = 1;
  340.                 if (tree->type == Node_redirect_output
  341.                     || tree->type == Node_redirect_append)
  342.                     fatal("can't redirect %s `%s' (%s)",
  343.                         direction, str, strerror(errno));
  344.                 else
  345.                     return NULL;
  346.             }
  347.         }
  348.     }
  349.     if (rp->offset != 0)    /* this file was previously open */
  350.         if (fseek(rp->fp, rp->offset, 0) == -1)
  351.             fatal("can't seek to %ld on `%s' (%s)",
  352.                 rp->offset, str, strerror(errno));
  353.     free_temp(tmp);
  354.     return rp;
  355. }
  356.  
  357. static void
  358. close_one()
  359. {
  360.     register struct redirect *rp;
  361.     register struct redirect *rplast = NULL;
  362.  
  363.     /* go to end of list first, to pick up least recently used entry */
  364.     for (rp = red_head; rp != NULL; rp = rp->next)
  365.         rplast = rp;
  366.     /* now work back up through the list */
  367.     for (rp = rplast; rp != NULL; rp = rp->prev)
  368.         if (rp->fp && (rp->flag & RED_FILE)) {
  369.             rp->offset = ftell(rp->fp);
  370.             if (fclose(rp->fp))
  371.                 warning("close of \"%s\" failed (%s).",
  372.                     rp->value, strerror(errno));
  373.             rp->fp = NULL;
  374.             break;
  375.         }
  376.     if (rp == NULL)
  377.         /* surely this is the only reason ??? */
  378.         fatal("too many pipes or input files open"); 
  379. }
  380.  
  381. NODE *
  382. do_close(tree)
  383. NODE *tree;
  384. {
  385.     NODE *tmp;
  386.     register struct redirect *rp;
  387.  
  388.     tmp = force_string(tree_eval(tree->subnode));
  389.     for (rp = red_head; rp != NULL; rp = rp->next) {
  390.         if (STREQ(rp->value, tmp->stptr))
  391.             break;
  392.     }
  393.     free_temp(tmp);
  394.     if (rp == NULL) /* no match */
  395.         return tmp_number((AWKNUM) 0.0);
  396.     fflush(stdout);    /* synchronize regular output */
  397.     return tmp_number((AWKNUM)close_redir(rp));
  398. }
  399.  
  400. static int
  401. close_redir(rp)
  402. register struct redirect *rp;
  403. {
  404.     int status = 0;
  405.  
  406.     if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE))
  407.         status = pclose(rp->fp);
  408.     else if (rp->fp)
  409.         status = fclose(rp->fp);
  410.     else if (rp->iop) {
  411.         if (rp->flag & RED_PIPE)
  412.             status = gawk_pclose(rp);
  413.         else
  414.             status = iop_close(rp->iop);
  415.  
  416.     }
  417.     /* SVR4 awk checks and warns about status of close */
  418.     if (status)
  419.         warning("failure status (%d) on %s close of \"%s\" (%s).",
  420.             status,
  421.             (rp->flag & RED_PIPE) ? "pipe" :
  422.             "file", rp->value, strerror(errno));
  423.     if (rp->next)
  424.         rp->next->prev = rp->prev;
  425.     if (rp->prev)
  426.         rp->prev->next = rp->next;
  427.     else
  428.         red_head = rp->next;
  429.     free(rp->value);
  430.     free((char *)rp);
  431.     return status;
  432. }
  433.  
  434. int
  435. flush_io ()
  436. {
  437.     register struct redirect *rp;
  438.     int status = 0;
  439.  
  440.     errno = 0;
  441.     if (fflush(stdout)) {
  442.         warning("error writing standard output (%s).", strerror(errno));
  443.         status++;
  444.     }
  445.     errno = 0;
  446.     if (fflush(stderr)) {
  447.         warning("error writing standard error (%s).", strerror(errno));
  448.         status++;
  449.     }
  450.     for (rp = red_head; rp != NULL; rp = rp->next)
  451.         /* flush both files and pipes, what the heck */
  452.         if ((rp->flag & RED_WRITE) && rp->fp != NULL)
  453.             if (fflush(rp->fp)) {
  454.                 warning("%s flush of \"%s\" failed (%s).",
  455.                     (rp->flag  & RED_PIPE) ? "pipe" :
  456.                     "file", rp->value, strerror(errno));
  457.                 status++;
  458.             }
  459.     return status;
  460. }
  461.  
  462. int
  463. close_io ()
  464. {
  465.     register struct redirect *rp;
  466.     int status = 0;
  467.  
  468.     for (rp = red_head; rp != NULL; rp = rp->next)
  469.         if (close_redir(rp))
  470.             status++;
  471.     return status;
  472. }
  473.  
  474. /* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
  475. int
  476. devopen (name, mode)
  477. char *name, *mode;
  478. {
  479.     int openfd = -1;
  480.     FILE *fdopen ();
  481.     char *cp;
  482.     int flag = 0;
  483.  
  484.     switch(mode[0]) {
  485.     case 'r':
  486.         flag = O_RDONLY;
  487.         break;
  488.  
  489.     case 'w':
  490.         flag = O_WRONLY|O_CREAT|O_TRUNC;
  491.         break;
  492.  
  493.     case 'a':
  494.         flag = O_WRONLY|O_APPEND|O_CREAT;
  495.         break;
  496.     default:
  497.         cant_happen();
  498.     }
  499.  
  500. #if defined(STRICT) || defined(NO_DEV_FD)
  501.     return (open (name, flag, 0666));
  502. #else
  503.     if (strict)
  504.         return (open (name, flag, 0666));
  505.  
  506.     if (!STREQN (name, "/dev/", 5))
  507.         return (open (name, flag, 0666));
  508.     else
  509.         cp = name + 5;
  510.         
  511.     /* XXX - first three tests ignore mode */
  512.     if (STREQ(cp, "stdin"))
  513.         return (0);
  514.     else if (STREQ(cp, "stdout"))
  515.         return (1);
  516.     else if (STREQ(cp, "stderr"))
  517.         return (2);
  518.     else if (STREQN(cp, "fd/", 3)) {
  519.         cp += 3;
  520.         if (sscanf (cp, "%d", & openfd) == 1 && openfd >= 0)
  521.             /* got something */
  522.             return openfd;
  523.         else
  524.             return -1;
  525.     } else
  526.         return (open (name, flag, 0666));
  527. #endif
  528. }
  529.  
  530. #ifndef MSDOS
  531. static IOBUF *
  532. gawk_popen(cmd, rp)
  533. char *cmd;
  534. struct redirect *rp;
  535. {
  536.     int p[2];
  537.     register int pid;
  538.  
  539.     rp->pid = -1;
  540.     rp->iop = NULL;
  541.     if (pipe(p) < 0)
  542.         return NULL;
  543.     if ((pid = fork()) == 0) {
  544.         close(p[0]);
  545.         dup2(p[1], 1);
  546.         close(p[1]);
  547.         execl("/bin/sh", "sh", "-c", cmd, 0);
  548.         _exit(127);
  549.     }
  550.     if (pid == -1)
  551.         return NULL;
  552.     rp->pid = pid;
  553.     close(p[1]);
  554.     return (rp->iop = iop_alloc(p[0]));
  555. }
  556.  
  557. static int
  558. gawk_pclose(rp)
  559. struct redirect *rp;
  560. {
  561.     SIGTYPE (*hstat)(), (*istat)(), (*qstat)();
  562.     int pid;
  563.     int status;
  564.     struct redirect *redp;
  565.  
  566.     iop_close(rp->iop);
  567.     if (rp->pid == -1)
  568.         return rp->status;
  569.     hstat = signal(SIGHUP, SIG_IGN);
  570.     istat = signal(SIGINT, SIG_IGN);
  571.     qstat = signal(SIGQUIT, SIG_IGN);
  572.     for (;;) {
  573.         pid = wait(&status);
  574.         if (pid == -1 && errno == ECHILD)
  575.             break;
  576.         else if (pid == rp->pid) {
  577.             rp->pid = -1;
  578.             rp->status = status;
  579.             break;
  580.         } else {
  581.             for (redp = red_head; redp != NULL; redp = redp->next)
  582.                 if (pid == redp->pid) {
  583.                     redp->pid = -1;
  584.                     redp->status = status;
  585.                     break;
  586.                 }
  587.         }
  588.     }
  589.     signal(SIGHUP, hstat);
  590.     signal(SIGINT, istat);
  591.     signal(SIGQUIT, qstat);
  592.     return(rp->status);
  593. }
  594. #else
  595. static
  596. struct {
  597.     char *command;
  598.     char *name;
  599. } pipes[_NFILE];
  600.  
  601. static IOBUF *
  602. gawk_popen(cmd, rp)
  603. char *cmd;
  604. struct redirect *rp;
  605. {
  606.     extern char *strdup(const char *);
  607.     int current;
  608.     char *name;
  609.     static char cmdbuf[256];
  610.  
  611.     /* get a name to use.  */
  612.     if ((name = tempnam(".", "pip")) == NULL)
  613.         return NULL;
  614.     sprintf(cmdbuf,"%s > %s", cmd, name);
  615.     system(cmdbuf);
  616.     if ((current = open(name,O_RDONLY)) == -1)
  617.         return NULL;
  618.     pipes[current].name = name;
  619.     pipes[current].command = strdup(cmd);
  620.     return (rp->iop = iop_alloc(current));
  621. }
  622.  
  623. static int
  624. gawk_pclose(rp)
  625. struct redirect *rp;
  626. {
  627.     int cur = rp->iop->fd;
  628.     int rval;
  629.  
  630.     rval = iop_close(rp->iop);
  631.  
  632.     /* check for an open file  */
  633.     if (pipes[cur].name == NULL)
  634.         return -1;
  635.     unlink(pipes[cur].name);
  636.     free(pipes[cur].name);
  637.     pipes[cur].name = NULL;
  638.     free(pipes[cur].command);
  639.     return rval;
  640. }
  641. #endif
  642.  
  643. #define    DO_END_OF_BUF    len = bp - iop->off;\
  644.             used = last - start;\
  645.             while (len + used > iop->secsiz) {\
  646.                 iop->secsiz *= 2;\
  647.                 erealloc(iop->secbuf,char *,iop->secsiz,"get");\
  648.             }\
  649.             last = iop->secbuf + used;\
  650.             start = iop->secbuf;\
  651.             memcpy(last, iop->off, len);\
  652.             last += len;\
  653.             iop->cnt = read(iop->fd, iop->buf, iop->size);\
  654.             if (iop->cnt < 0)\
  655.                 return iop->cnt;\
  656.             end_data = iop->buf + iop->cnt;\
  657.             iop->off = bp = iop->buf;
  658.  
  659. #define    DO_END_OF_DATA    iop->cnt = read(iop->fd, end_data, end_buf - end_data);\
  660.             if (iop->cnt < 0)\
  661.                 return iop->cnt;\
  662.             end_data += iop->cnt;\
  663.             if (iop->cnt == 0)\
  664.                 break;\
  665.             iop->cnt = end_data - iop->buf;
  666.  
  667. static int
  668. get_a_record(res, iop)
  669. char **res;
  670. IOBUF *iop;
  671. {
  672.     register char *end_data;
  673.     register char *end_buf;
  674.     char *start;
  675.     register char *bp;
  676.     register char *last;
  677.     int len, used;
  678.     register char rs = get_rs();
  679.  
  680.     if (iop->cnt < 0)
  681.         return iop->cnt;
  682.     if ((iop->flag & IOP_IS_TTY) && output_is_tty)
  683.         fflush(stdout);
  684.     end_data = iop->buf + iop->cnt;
  685.     if (iop->off >= end_data) {
  686.         iop->cnt = read(iop->fd, iop->buf, iop->size);
  687.         if (iop->cnt <= 0)
  688.             return iop->cnt = EOF;
  689.         end_data = iop->buf + iop->cnt;
  690.         iop->off = iop->buf;
  691.     }
  692.     last = start = bp = iop->off;
  693.     end_buf = iop->buf + iop->size;
  694.     if (rs == 0) {
  695.         while (!(*bp == '\n' && bp != iop->buf && bp[-1] == '\n')) {
  696.             if (++bp == end_buf) {
  697.                 DO_END_OF_BUF
  698.             }
  699.             if (bp == end_data) {
  700.                 DO_END_OF_DATA
  701.             }
  702.         }
  703.         if (*bp == '\n' && bp != iop->off && bp[-1] == '\n') {
  704.             int tmp = 0;
  705.  
  706.             /* allow for more than two newlines */
  707.             while (*bp == '\n') {
  708.                 tmp++;
  709.                 if (++bp == end_buf) {
  710.                     DO_END_OF_BUF
  711.                 }
  712.                 if (bp == end_data) {
  713.                     DO_END_OF_DATA
  714.                 }
  715.             }
  716.             iop->off = bp;
  717.             bp -= 1 + tmp;
  718.         } else if (bp != iop->buf && bp[-1] != '\n') {
  719.             warning("record not terminated");
  720.             iop->off = bp + 2;
  721.         } else {
  722.             bp--;
  723.             iop->off = bp + 2;
  724.         }
  725.     } else {
  726.         while (*bp++ != rs) {
  727.             if (bp == end_buf) {
  728.                 DO_END_OF_BUF
  729.             }
  730.             if (bp == end_data) {
  731.                 DO_END_OF_DATA
  732.             }
  733.         }
  734.         if (*--bp != rs) {
  735.             warning("record not terminated");
  736.             bp++;
  737.         }
  738.         iop->off = bp + 1;
  739.     }
  740.     if (start == iop->secbuf) {
  741.         len = bp - iop->buf;
  742.         if (len > 0) {
  743.             used = last - start;
  744.             while (len + used > iop->secsiz) {
  745.                 iop->secsiz *= 2;
  746.                 erealloc(iop->secbuf,char *,iop->secsiz,"get2");
  747.             }
  748.             last = iop->secbuf + used;
  749.             start = iop->secbuf;
  750.             memcpy(last, iop->buf, len);
  751.             last += len;
  752.         }
  753.     } else
  754.         last = bp;
  755.     *last = '\0';
  756.     *res = start;
  757.     return last - start;
  758. }
  759.  
  760. NODE *
  761. do_getline(tree)
  762. NODE *tree;
  763. {
  764.     struct redirect *rp;
  765.     IOBUF *iop;
  766.     int cnt;
  767.     NODE **lhs;
  768.     int redir_error = 0;
  769.  
  770.     if (tree->rnode == NULL) {     /* no redirection */
  771.         iop = nextfile();
  772.         if (iop == NULL)        /* end of input */
  773.             return tmp_number((AWKNUM) 0.0);
  774.     } else {
  775.         rp = redirect(tree->rnode, &redir_error);
  776.         if (rp == NULL && redir_error)    /* failed redirect */
  777.             return tmp_number((AWKNUM) -1.0);
  778.         iop = rp->iop;
  779.         getline_redirect++;
  780.     }
  781.     if (tree->lnode == NULL) {    /* no optional var. -- read in $0 */
  782.         if (inrec(iop) != 0) {
  783.             getline_redirect = 0;
  784.             return tmp_number((AWKNUM) 0.0);
  785.         }
  786.     } else {            /* read in a named variable */
  787.         char *s = NULL;
  788.  
  789.         lhs = get_lhs(tree->lnode, 1);
  790.         cnt = get_a_record(&s, iop);
  791.         if (!getline_redirect) {
  792.             assign_number(&NR_node->var_value,
  793.                 NR_node->var_value->numbr + 1.0);
  794.             assign_number(&FNR_node->var_value,
  795.                 FNR_node->var_value->numbr + 1.0);
  796.         }
  797.         if (cnt == EOF) {
  798.             getline_redirect = 0;
  799.             free(s);
  800.             return tmp_number((AWKNUM) 0.0);
  801.         }
  802.         *lhs = make_string(s, strlen(s));
  803.         do_deref();
  804.         /* we may have to regenerate $0 here! */
  805.         if (field_num == 0)
  806.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  807.         field_num = -1;
  808.     }
  809.     getline_redirect = 0;
  810.     return tmp_number((AWKNUM) 1.0);
  811. }
  812.