home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / awk / awk320sr.zip / AWKFILE.C < prev    next >
C/C++ Source or Header  |  1991-05-22  |  14KB  |  575 lines

  1. /*
  2.  * Awk file and command line processing
  3.  *
  4.  * Copyright (C) 1988, 1989, 1990, 1991 by Rob Duff
  5.  * All rights reserved
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <conio.h>
  10. #include <ctype.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13.  
  14. #include "awkfstr.h"
  15. #include "awk.h"
  16.  
  17. extern long fatol(FSTR);
  18. ELEMENT *allell(void);
  19.  
  20. short modfield = 0;
  21. short modrecord = 0;
  22.  
  23. static ITEM argn[1] = { { ACTUAL, S_SHORT } };
  24. static ITEM argp[1] = { { FORMAL, S_SIMPLE } };
  25.  
  26. static  char    argvbuf[66];        /* string form of getargv */
  27.  
  28. static void set_element(int, char*, ITEM*);
  29.  
  30. /*
  31.  * set an element of the ARGV array
  32.  */
  33. static void set_element(int argc, char *arg, ITEM *vp)
  34. {
  35.     FSTR    sp;
  36.     ELEMENT *ep;
  37.     ITEM    ip[1];
  38.  
  39.     ip->stype = S_SHORT;
  40.     ip->sclass = ACTUAL;
  41.     ip->svalue.ival = argc;
  42.     sp = getstr(tostring(ip));
  43.     buffer[0] = ZSTR;
  44.     fstrncpy(buffer+1, arg, MAXCODE-2);
  45.     ep = allell();
  46.     ep->aclass = ACTUAL;
  47.     ep->atype = S_STRING;
  48.     ep->astr = getstr(buffer);
  49.     ep->aindex = sp;
  50.     ep->anext = NULL;
  51.     add_element(ep, vp);
  52.     if (isnumber(arg)) {
  53.         ep->avalue.dval = todouble((ITEM*)ep);
  54.         ep->atype = S_NUMBER;
  55.     }
  56. }
  57.  
  58. /*
  59.  * copy argv into ARGV
  60.  */
  61. void setargv(int n, char *arg0, char *argv[])
  62. {
  63.     int     argc;
  64.  
  65.     clear_array(av);
  66.     set_element(0, arg0, av);
  67.     argc = 1;
  68.     while (n) {
  69.         set_element(argc, *argv, av);
  70.         n--; argc++; argv++;
  71.     }
  72.     free_item((ITEM*)ac);
  73.     ac->stype = S_SHORT;
  74.     ac->svalue.ival = argc;
  75.     argn->svalue.ival = 0;
  76.     argp->svalue.sptr = av;
  77. }
  78.  
  79. /*
  80.  * check to see whether an argument is a
  81.  * command line assignment.
  82.  * returns pointer to string after "="
  83.  */
  84. FSTR isname(FSTR sp)
  85. {
  86.     if (*sp > ' ' && (isalpha(*sp) || *sp == '_'))
  87.         sp++;
  88.     while (*sp > ' ' && (isalnum(*sp) || *sp == '_'))
  89.         sp++;
  90.     if (*sp != '=')
  91.         sp = NULL;
  92.     return sp;
  93. }
  94.  
  95. /*
  96.  * check to see if a field can be fully
  97.  * represented as a number.
  98.  */
  99. int isnumber(FSTR sp)
  100. {
  101.     int     lag, lead, len, power, digit;
  102.     FSTR    exp;
  103.  
  104.     if (*sp == '\0')
  105.         return 0;
  106.     exp = "0"; len = 1;
  107.     lead = lag = digit = 0;
  108.     if (*sp == '+' || *sp == '-')
  109.         *sp++;
  110.     if (*sp > ' ' && isdigit(*sp))
  111.         digit++;
  112.     while (*sp == '0')
  113.         sp++;
  114.     while (*sp > ' ' && isdigit(*sp)) {
  115.         lead++;
  116.         sp++;
  117.     }
  118.     if (*sp == '.') {
  119.         sp++;
  120.         if (*sp > ' ' && isdigit(*sp))
  121.             digit++;
  122.         while (*sp == '0') {
  123.             lag++;
  124.             sp++;
  125.         }
  126.         while (*sp > ' ' && isdigit(*sp))
  127.             sp++;
  128.     }
  129.     if (*sp == 'e' || *sp == 'E') {
  130.         sp++;
  131.         exp = sp;
  132.         len = 0;
  133.         if (*sp == '+' || *sp == '-')
  134.             *sp++;
  135.         if (*sp < ' ' || !isdigit(*sp))
  136.             return 0;
  137.         while (*sp == '0')
  138.             sp++;
  139.         while (*sp > ' ' && isdigit(*sp)) {
  140.             len++;
  141.             sp++;
  142.         }
  143.     }
  144.     if (digit == 0)
  145.         return 0;
  146.     if (*sp != '\0')
  147.         return 0;
  148.     if (len > 3)
  149.         return 0;
  150.     power = (int)fatol(exp);
  151.     if (lead > 0)
  152.         power += lead;
  153.     else
  154.         power -= lag;
  155.     if (power > 307 || power < -305)
  156.         return 0;
  157.     return 1;
  158. }
  159.  
  160. /*
  161.  * get next non null element of ARGV less than ARGC
  162.  * the user program may delete some of the arguments
  163.  * or set them to null to erase them.
  164.  */
  165. char *getargv()
  166. {
  167.     int     argc, n;
  168.     FSTR    argv, argq;
  169.     IDENT   *vp;
  170.     ITEM    *sp;
  171.     ITEM    item[1];
  172.  
  173.     argc = tointeger(ac);
  174.     while (++(argn->svalue.ival) < argc) {
  175.         index(argp, argn, item);
  176.         argv = tostring(item);
  177.         argq = isname(argv + 1);
  178.         if (argq != NULL) {
  179.             n = (int)(argq - argv) - 1;
  180.             if (n > MAXCODE-1)
  181.                 n = MAXCODE-1;
  182.             fstrncpy(buffer, argv + 1, n);
  183.             buffer[n] = '\0';
  184.              for (vp = ident; vp != NULL; vp = vp->vnext) {
  185.                 if (fstrcmp(buffer, vp->vname) == 0) {
  186.                     sp = vp->vitem;
  187.                     if (sp != nul) {
  188.                         buffer[0] = ZSTR;
  189.                         fstrncpy(buffer + 1, argq + 1, MAXCODE-2);
  190.                         free_item(sp);
  191.                         sp->stype = S_STRING;
  192.                         sp->sstr = getstr(buffer);
  193.                         if (isnumber(buffer+1)) {
  194.                             sp->svalue.dval = todouble(sp);
  195.                             sp->stype = S_NUMBER;
  196.                         }
  197.                     }
  198.                     break;
  199.                 }
  200.             }
  201.         }
  202.         else if (argv[1] != '\0') {
  203.             fstrncpy(argvbuf, argv+1, 64);
  204.             return argvbuf;
  205.         }
  206.     }
  207.     return NULL;
  208. }
  209.  
  210. /*
  211.  * get a list of var=text elements and process them
  212.  */
  213. void getargs(NAME *list)
  214. {
  215.     int     n;
  216.     FSTR    var, text;
  217.     IDENT   *vp;
  218.     ITEM    *sp;
  219.  
  220.     while (list != NULL) {
  221.         var = list->name;
  222.         text = isname(var);
  223.         if (text != NULL) {
  224.             n = (int)(text - var);
  225.             if (n > MAXCODE-1)
  226.                 n = MAXCODE-1;
  227.             fstrncpy(buffer, var, n);
  228.             buffer[n] = '\0';
  229.              for (vp = ident; vp != NULL; vp = vp->vnext) {
  230.                 if (strcmp(buffer, vp->vname) == 0) {
  231.                     sp = vp->vitem;
  232.                     if (sp != nul) {
  233.                         buffer[0] = ZSTR;
  234.                         fstrncpy(buffer + 1, text + 1, MAXCODE-2);
  235.                         free_item(sp);
  236.                         sp->stype = S_STRING;
  237.                         sp->sstr = getstr(buffer);
  238.                         if (isnumber(buffer+1)) {
  239.                             sp->svalue.dval = todouble(sp);
  240.                             sp->stype = S_NUMBER;
  241.                         }
  242.                     }
  243.                     break;
  244.                 }
  245.             }
  246.         }
  247.         else
  248.             error("invalid -v var=text syntax %s", list->name);
  249.         list = list->next;
  250.     }
  251. }
  252.  
  253. /*
  254.  * set the filename variable to name
  255.  * and clear FNR to 0
  256.  */
  257. void setfile(FSTR name)
  258. {
  259.     free_item(fn);
  260.     fn->stype = S_STRING;
  261.     fn->sstr = name;
  262.     free_item(fnr);
  263.     fnr->stype = S_SHORT;
  264.     fnr->svalue.ival = 0;
  265. }
  266.  
  267. /*
  268.  * read the next input record to $0
  269.  */
  270. int getrecord()
  271. {
  272.     kbhit();
  273.     return getline(files + 1, (ITEM*)fieldtab);
  274. }
  275.  
  276. /*
  277.  * read the input until an end of record character
  278.  * is read or until the end of input.
  279.  */
  280. int getline(FYLE *fp, ITEM *ip)
  281. {
  282.     int     ch, och, lrs;
  283.     char    *lp, *ep;
  284.     FSTR    dp;
  285.     double  lnr;
  286.  
  287.     if (fp->ffyle == NULL) {
  288.         return -1;
  289.     }
  290.     if (ip == (ITEM*)fieldtab) {
  291.         lp = linebuf;
  292.         ep = linebuf + sizeof(linebuf) - 1;
  293.         *lp++ = TSTR;
  294.     }
  295.     else {
  296.         lp = buffer;
  297.         ep = buffer + sizeof(buffer) - 1;
  298.         *lp++ = ZSTR;
  299.     }
  300.     *lp = '\0';
  301.     if (feof(fp->ffyle))
  302.         return 0;
  303.     dp = tostring(rs);
  304.     lrs = dp[1];
  305.     ch = fgetc(fp->ffyle);
  306.     if (ch == EOF)
  307.         return 0;
  308.     if (lrs == 0) {
  309.         och = '\0';
  310.         while (ch != EOF && lp < ep) {
  311.             if (ch == '\n' && och == '\n')
  312.                 break;
  313.             *lp++ = och = ch;
  314.             ch = fgetc(fp->ffyle);
  315.         }
  316.     }
  317.     else {
  318.         while (ch != EOF && ch != lrs && lp < ep) {
  319.             *lp++ = ch;
  320.             ch = fgetc(fp->ffyle);
  321.         }
  322.     }
  323.     if (ch != EOF && lp == ep)
  324.         ungetc(ch, fp->ffyle);
  325.     *lp = '\0';
  326.     if (ip == (ITEM*)fieldtab) {
  327.         modrecord = 1;
  328.         modfield = 0;
  329.         free_item(ip);
  330.         ip->stype = S_STRING;
  331.         ip->sstr = linebuf;
  332.         if (ch == EOF && lp == linebuf+1)
  333.             return 0;
  334.     }
  335.     else {
  336.         if (ip != (ITEM*)nul) {
  337.             free_item(ip);
  338.             ip->stype = S_STRING;
  339.             ip->sstr = getstr(buffer);
  340.         }
  341.         if (ch == EOF && lp == buffer+1)
  342.             return 0;
  343.     }
  344.     if (fp == (files + 1)) {
  345.         lnr = todouble((ITEM*)fnr);
  346.         if (fnr->stype != S_DOUBLE) {
  347.             free_item((ITEM*)fnr);
  348.             fnr->stype = S_DOUBLE;
  349.         }
  350.         fnr->svalue.dval = lnr + 1;
  351.         lnr = todouble((ITEM*)nr);
  352.         if (nr->stype != S_DOUBLE) {
  353.             free_item((ITEM*)nr);
  354.             nr->stype = S_DOUBLE;
  355.         }
  356.         nr->svalue.dval = lnr + 1;
  357.     }
  358.     return 1;
  359. }
  360.  
  361. /*
  362.  * free all the fields to prepare for the
  363.  * next input record.
  364.  */
  365. void deparse()
  366. {
  367.     int     i;
  368.  
  369.     for (i = 0; i < MAXFIELD; i++)
  370.         free_item(fieldtab + i);
  371.     fieldtab->stype = S_STRING;
  372.     fieldtab->sstr = linebuf;
  373.     linebuf[0] = TSTR;
  374.     linebuf[1] = 0;
  375.     free_item((ITEM*)nf);
  376.     nf->stype = S_SHORT;
  377.     nf->svalue.ival = 0;
  378.     modfield = 0;
  379.     modrecord = 0;
  380. }
  381.  
  382. /*
  383.  * parse the input record into fields
  384.  */
  385. void parse()
  386. {
  387.     FSTR    dst, mat, beg, src;
  388.     int     lnf, i;
  389.     ITEM    *ip;
  390.  
  391.     if (modrecord) {
  392.         for (i = 1; i < MAXFIELD; i++)
  393.             free_item(fieldtab + i);
  394.         lnf = 0;
  395.         dst = fieldbuf;
  396.         src = onestring(fieldtab)+1;
  397.         beg = src;
  398.         mat = NULL;
  399.         ip = fieldtab+1;
  400.         if (awkfre == blankre) {
  401.             i = *src++;
  402.             while (i != '\0' && lnf < MAXFIELD-1) {
  403.                 while (i > '\0' && isspace(i))
  404.                     i = *src++;
  405.                 if (i != '\0') {
  406.                     ip->stype = S_STRING;
  407.                     ip->sstr = dst;
  408.                     *dst++ = TSTR;
  409.                     while (i != '\0' && (i < 0 || !isspace(i))) {
  410.                         *dst++ = i;
  411.                         i = *src++;
  412.                     }
  413.                     *dst++ = '\0';
  414.                     if (isnumber(ip->sstr+1)) {
  415.                         ip->svalue.dval = todouble(ip);
  416.                         ip->stype = S_NUMBER;
  417.                     }
  418.                     lnf++;
  419.                     ip++;
  420.                 }
  421.             }
  422.         }
  423.         else {
  424.             while (*src != '\0' && lnf < MAXFIELD-1) {
  425.                 ip->stype = S_STRING;
  426.                 ip->sstr = dst;
  427.                 *dst++ = TSTR;
  428.                 while (*src != '\0' && 
  429.                       (mat = matchp(beg, src, awkfre)) == NULL && *src != '\n')
  430.                     *dst++ = *src++;
  431.                 if (src == mat)
  432.                     *dst++ = *mat++;
  433.                 if (mat != NULL) {
  434.                      if (*src != '\0') {
  435.                         if(mat > src)
  436.                             src = mat;
  437.                         else {
  438.                             mat = NULL;
  439.                             if (dst == fieldbuf + 1)
  440.                                 *dst++ = *src++;
  441.                         }
  442.                     }
  443.                 }
  444.                 else if (*src == '\n') {
  445.                     src++;
  446.                     mat = NULL;
  447.                 }
  448.                 *dst++ = '\0';
  449.                 if (isnumber(ip->sstr+1)) {
  450.                     ip->svalue.dval = todouble(ip);
  451.                     ip->stype = S_NUMBER;
  452.                 }
  453.                 lnf++;
  454.                 ip++;
  455.             }
  456.             if (mat != NULL) {
  457.                 ip->stype = S_STRING;
  458.                 ip->sstr = nullstr;
  459.                 lnf++;
  460.             }
  461.         }
  462.         free_item((ITEM*)nf);
  463.         nf->stype = S_SHORT;
  464.         nf->svalue.ival = lnf;
  465.             modfield = 0;
  466.         modrecord = 0;
  467.     }
  468. }
  469.  
  470. /*
  471.  * convert the fields back into the input record
  472.  * this is done whenever $0 is referenced after
  473.  * any field is modified.
  474.  */
  475. void unparse()
  476. {
  477.     int     i, lnf;
  478.     char    *dp;
  479.     FSTR    sp, fp;
  480.  
  481.     if (modfield) {
  482.         free_item(fieldtab);
  483.         fieldtab->stype = S_STRING;
  484.         fieldtab->sstr = linebuf;
  485.         dp = linebuf;
  486.         *dp++ = TSTR;
  487.         fp = tostring((ITEM*)ofs);
  488.         lnf = tointeger((ITEM*)nf);
  489.         for (i = 1; i <= lnf; i++) {
  490.             if (i > 1) {
  491.                 sp = fp+1;
  492.                 while (*sp != '\0')
  493.                     *dp++ = *sp++;
  494.             }
  495.             sp = tostring(fieldtab + i)+1;
  496.             while (*sp != '\0')
  497.                 *dp++ = *sp++;
  498.         }
  499.         *dp = '\0';
  500.         for (i = lnf + 1; i < MAXFIELD; i++)
  501.             free_item(fieldtab + i);
  502.         modfield = 0;
  503.         modrecord = 0;
  504.     }
  505. }
  506.  
  507. /*
  508.  * convert an item into a file number
  509.  * the item is converted to a string
  510.  * and this string is used as the filename
  511.  * mp is a pointer to a string that is the
  512.  * open mode of the file "w" or "a"
  513.  */
  514. FYLE *getfile(ITEM *a, int p)
  515. {
  516.     FSTR    sp;
  517.     FYLE    *fp;
  518.  
  519.     sp = tostring(a);
  520.     for (fp = files + 2; fp < nextfile; fp++) {
  521.         if (fstrcmp(fp->fname+1, sp+1) == 0)
  522.             break;
  523.     }
  524.     if (p == P_CLOSE) {
  525.         if (fp < nextfile && fp->ffyle != NULL) {
  526.             fclose(fp->ffyle);
  527.             fp->ffyle = NULL;
  528.         }
  529.         fp = NULL;
  530.     }
  531.     else {
  532.         if (fp >= nextfile) {
  533.             if (nextfile >= files + MAXFILE) {
  534.                 for (fp = files; fp < nextfile; fp++) {
  535.                     if (fp->ffyle == NULL)
  536.                         break;
  537.                 }
  538.             }
  539.             else
  540.                 fp = nextfile++;
  541.             if (fp >= files + MAXFILE)
  542.                 error("too many files open \"%s\"", sp+1);
  543.         }
  544.         if (fp->ffyle == NULL) {
  545.             switch (p) {
  546.             case P_OPEN:
  547.                 fp->fmode = "r";
  548.                 break;
  549.             case P_CREATE:
  550.                 fp->fmode = "w";
  551.                 break;
  552.             case P_APPEND:
  553.                 fp->fmode = "a";
  554.                 break;
  555.             }
  556.             fp->fname = newstr(sp);
  557.             fp->ffyle = NULL;
  558.         }
  559.     }
  560.     return fp;
  561. }
  562.  
  563. /*
  564.  * close all of the files used by the AWK program
  565.  */
  566. void awkclose()
  567. {
  568.     FYLE *fp;
  569.  
  570.     for (fp = files + 2; fp < nextfile; fp++)
  571.         if (fp->ffyle != NULL)
  572.             fclose(fp->ffyle);
  573. }
  574.  
  575.