home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 280_01 / macro.c < prev    next >
Text File  |  1989-01-13  |  11KB  |  565 lines

  1. /* [MACRO.C of JUGPDS Vol.46]*/
  2. /*
  3. *****************************************************************
  4. *                                *
  5. *    Written by  Hakuo Katayose (JUG-CP/M No.179)        *
  6. *            49-114 Kawauchi-Sanjuunin-machi        *
  7. *            Sendai, Miyagi 980                          *
  8. *            Phone: 0222-61-3219                *
  9. *                                *
  10. *       Modifird by Toshiya Oota   (JUG-CPM No.10)              *
  11. *                   Sakae ko-po 205                 *
  12. *            5-19-6 Hosoda                *
  13. *            Katusikaku Tokyo 124            *
  14. *                                *
  15. *        for MS-DOS Lattice C V3.1J & 80186/V20/V30    *
  16. *                                *
  17. *    Compiler Option: -ccu -k0(1) -ms -n -v -w        *
  18. *                                *
  19. *    Edited & tested by Y. Monma (JUG-CP/M Disk Editor)    *
  20. *            &  T. Ota   (JUG-CP/M Sub Disk Editor)    *
  21. *                                *
  22. *****************************************************************
  23. */
  24.  
  25. /* macro (m4) - expand macros with arguments */
  26.  
  27. #include "stdio.h"
  28. #include "dos.h"
  29. #include "tools.h"
  30. #include "toolfunc.h"
  31.     
  32. #define ARGFLAG     '$'
  33.  
  34. #define    IFTYPE        3
  35. #define    INCTYPE        4
  36. #define    ARTTYPE        5
  37. #define SUBTYPE        7
  38. #define DEFTYPE        8
  39. #define LENTYPE     9
  40.  
  41. #define    UBUFSIZE  256
  42. #define ARGSIZE      128
  43. #define CALLSIZE  128
  44. #define EVALSIZE 1024
  45.  
  46. #define MAXTOK      80
  47. #define MAXDEF     256
  48.  
  49. char    ubuf[UBUFSIZE];
  50. int    ubufp;
  51.  
  52. struct    mac {
  53.     char    *name;
  54.     char    *repn;
  55. } deftbl[1000];
  56.  
  57. int    tcnt;
  58.  
  59. char    ctype[256];
  60. FILE    *infp;
  61.  
  62. char    evalst[EVALSIZE];
  63. int    ep, cp;
  64.  
  65. void    initialize(),eval(),dodef(),dolen(),pbnum(),doif(),dosub(),doincr();
  66. void    doarith(),install(),puttok(),putchr(),ungets(),ungetch();
  67.  
  68. void main(argc, argv)
  69. int    argc;
  70. char    *argv[];
  71.  
  72. {
  73.     int    ap, t, nbl, plev[CALLSIZE];
  74.     char    token[(MAXTOK-1)], defn[MAXDEF], *balp, s[2];
  75.     int    callst[CALLSIZE];
  76.     int    argstk[ARGSIZE];
  77.  
  78.     balp = "()";
  79.     if (argc < 2) {
  80.         fprintf(STDERR, "MAC999 Usage: macro filename");
  81.         exit();
  82.     }
  83.     if ((infp = fopen(argv[1], READ)) == NO) {
  84.         fprintf(STDERR, "MAC901 Can't open file:%s", argv[1]);
  85.         exit();
  86.     }
  87.     initialize();
  88.     s[0] = DEFTYPE;
  89.     s[1] = EOS;
  90.     install("define", s);
  91.     s[0] = IFTYPE;
  92.     s[1] = EOS;
  93.      install("ifelse", s);
  94.     s[0] = INCTYPE;
  95.     s[1] = EOS;
  96.     install("incr", s);
  97.     s[0] = ARTTYPE;
  98.     s[1] = EOS;
  99.     install("arith", s);
  100.     s[0] = SUBTYPE;
  101.     s[1] = EOS;
  102.     install("substr", s);
  103.     s[0] = LENTYPE;
  104.     s[1] = EOS;
  105.     install("len", s);
  106.  
  107.     cp = 0;
  108.     ap = 1;
  109.     ep = 1;
  110.     while ((t = gettok(token, MAXTOK)) != EOF) {
  111.         if (t == ALPHA) {
  112.         if (lookup(token, defn) == NO)
  113.             puttok(token);
  114.         else { /* defined, put it in eval stack */
  115.             if (++cp > CALLSIZE) {
  116.                 fprintf(STDERR, "MAC902 Call stack overflow.\n");
  117.             }
  118.                 callst[cp] = ap;
  119.                 ap = push(ep, argstk, ap);
  120.                 puttok(defn); /* stack definition */
  121.                 putchr(EOS);
  122.                 ap = push(ep, argstk, ap);
  123.                 puttok(token); /* stack name */
  124.                 putchar(EOS);
  125.                 ap = push(ep, argstk, ap);
  126.                 t = gettok(token, MAXTOK); /* peek a next */
  127.                 ungets(token);
  128.                 if (t != LPAREN) /* add () if not present */
  129.                     ungets(balp);
  130.                 plev[cp] = 0;
  131.         }
  132.     }
  133.     else if (t == LBRACKET) { /* strip one level of [] */
  134.         nbl = 1;
  135.         while (1) {
  136.             if ((t = gettok(token, MAXTOK)) == LBRACKET)
  137.                 nbl++;
  138.             else if (t == RBRACKET) {
  139.                 if (--nbl == 0)
  140.                     break;
  141.             }
  142.             else if (t == EOF) {
  143.                 fprintf(STDERR, "MAC903 EOF inserting.\n");
  144.                 exit();
  145.             }
  146.             puttok(token);
  147.         }
  148.     }
  149.     else if (cp == 0)    /* not in a macro at all */
  150.         puttok(token);
  151.     else if (t == LPAREN) {
  152.         if (plev[cp] > 0)
  153.             puttok(token);
  154.         plev[cp]++;
  155.     }
  156.     else if (t == RPAREN) {
  157.         if (--plev[cp] > 0)
  158.             puttok(token);
  159.         else { /* end of argument list */
  160.             putchr(EOS);
  161.             eval(argstk, callst[cp], ap-1);
  162.             ap = callst[cp]; /* pop eval stack */
  163.             ep = argstk[ap];
  164.             cp--;
  165.             }
  166.         }
  167.         else if (t == ',' && plev[cp] == 1) { /* new arg */
  168.             putchr(EOS);
  169.         ap = push(ep, argstk, ap);
  170.         }
  171.     else
  172.         puttok(token); /* just stack it */
  173.     }
  174.     if (cp != 0)
  175.     fprintf(STDERR, "MAC904 Unexpeced EOF.");
  176. }
  177.  
  178. /* eval - expand arg i through j: evaluate builtin or push back defn */
  179. void eval(argstk, i, j)
  180. int    argstk[];
  181.  
  182. {
  183.     int    t, argno, k, td;
  184.  
  185.     t = argstk[i];
  186.     if ((td = evalst[t]) == DEFTYPE)
  187.         dodef(argstk, i , j);
  188.     else if (evalst[t] == INCTYPE)
  189.         doincr(argstk, i, j);
  190.     else if (evalst[t] == ARTTYPE)
  191.         doarith(argstk, i, j);
  192.     else if (evalst[t] == SUBTYPE)
  193.         dosub(argstk, i, j);
  194.     else if (evalst[t] == IFTYPE)
  195.         doif(argstk, i, j);
  196.     else if (evalst[t] == LENTYPE)    
  197.         dolen(argstk, i, j);
  198.     else {
  199.         for (k = t + strlen(&evalst[t]) - 1; k > t; k--)
  200.             if (evalst[k-1] != ARGFLAG)
  201.                 ungetch(evalst[k]);
  202.             else {
  203.                 argno = evalst[k--]-'0';
  204.                 if (argno >= 0 && argno < j-i)
  205.                     ungets(&evalst[argstk[i+argno+1]]);
  206.             }
  207.         if (k == t) /* do last character */
  208.             ungetch(evalst[k]);
  209.     }
  210. }
  211.  
  212.  
  213. /* dodef - install definition in table */
  214. void dodef(argstk, i, j)
  215. int    argstk[];
  216.  
  217. {
  218.     if (j-i >2)
  219.         install(&evalst[argstk[i+2]], &evalst[argstk[i+3]]);
  220. }
  221.  
  222.  
  223. /* delen - compute length of string */
  224. void dolen(argstk, i, j)
  225. int    argstk[];
  226.  
  227. {
  228.     int    num;
  229.  
  230.     num = strlen(&evalst[argstk[i+2]]);
  231.     pbnum(num);
  232. }
  233.  
  234.  
  235. /* pbnum - convert number to string, push back on input */
  236. void pbnum(num)
  237. int    num;
  238.  
  239. {
  240.     do {
  241.         ungetch(num%10+'0');
  242.         num /= 10;
  243.     } while (num != 0);
  244. }
  245.  
  246.  
  247. /* doif - select one of two arguents */
  248. void doif(argstk, i, j)
  249. int    argstk[];
  250.  
  251.  {
  252.     if (j-i < 5)
  253.         return;
  254.     if (!strcmp(&evalst[argstk[i+2]], evalst[argstk[i+3]]))
  255.         ungets(&evalst[argstk[i+4]]);
  256.     else
  257.         ungets(&evalst[argstk[i+5]]);
  258. }
  259.  
  260.  
  261. /* dosub - select substring */
  262. void dosub(argstk, i, j)
  263. int    argstk[];
  264.  
  265. {
  266.     int    fc, nc, app, k;
  267.  
  268.     if (j-i < 3)
  269.         return;
  270.     nc = (j-i < 4) ? MAXTOK : ctoi(&evalst[argstk[i+4]]);
  271.     app = argstk[i+2];
  272.     fc = app + ctoi(&evalst[argstk[i+3]]) - 1;
  273.     if (fc >= app && fc < app + strlen(&evalst[app])) {
  274.         k = fc + min(nc, strlen(&evalst[fc])) - 1;
  275.         while (k >= fc)
  276.             ungetch(evalst[k--]);
  277.     }
  278. }
  279.  
  280.  
  281. /* doincr - increment argument by 1 */
  282. void doincr(argstk, i, j)
  283. int    argstk[];
  284.  
  285. {
  286.     int    k, num;
  287.  
  288.     k = (j-i < 3) ? 1 : ctoi(&evalst[argstk[i+3]]);
  289.     num = ctoi(&evalst[argstk[i+2]])+k;
  290.     pbnum(num);
  291. }
  292.  
  293.  
  294. /* doarith - arithmetic computation */
  295. void doarith(argstk, i, j)
  296. int    argstk[];
  297.  
  298. {
  299.     int    k, num, l;
  300.  
  301.     if (j-i < 3)
  302.         return;
  303.     num = ctoi(&evalst[argstk[i+2]]);
  304.     k = (j-i < 4) ? num : ctoi(&evalst[argstk[i+4]]);
  305.     switch (evalst[(l = argstk[i+3])]) {
  306.         case     '+' :
  307.             num += k;
  308.             break;
  309.         case    '-' :
  310.             num -= k;
  311.             break;
  312.         case    '*' :
  313.             num *= k;
  314.             break;
  315.         case    '/' :
  316.             num /= k;
  317.             break;
  318.         case    '%' :
  319.             num %= k;
  320.             break;
  321.         case    '=' :
  322.             switch (evalst[l+1]) {
  323.                 case '<' :
  324.                     num = (num <= k);
  325.                     break;
  326.                 case '>' :
  327.                     num = (num >= k);
  328.                     break;
  329.                   case '=' :
  330.                     num = (num ==k);
  331.                     break;
  332.                 case EOS :
  333.                     num = (num < k);
  334.                     break;
  335.                 default :
  336.                     return;
  337.             }
  338.             break;
  339.         case '<':
  340.             switch (evalst[l+1]) {
  341.                 case '<' :
  342.                     num = (num <<= k);
  343.                     break;
  344.                 case '>' :
  345.                     num = (num != k);
  346.                     break;
  347.                 case '=' :
  348.                     num = (num <= k);
  349.                     break;
  350.                 case EOS :
  351.                     num = (num < k);
  352.                 default :
  353.                 return;
  354.             }
  355.             break;
  356.         case '>' :
  357.             switch (evalst[l+1]) {
  358.                 case '<' :
  359.                     num = (num != k);
  360.                     break;
  361.                 case '>' :
  362.                     num = (num >>= k);
  363.                     break;
  364.                 case '=' :
  365.                     num = (num >= k);
  366.                     break;
  367.                 case EOS :
  368.                     num = (num > k);
  369.                     break;
  370.                 default :
  371.                     return;
  372.             }
  373.             break;
  374.         default :
  375.             return;
  376.             break;
  377.     }
  378.     pbnum(num);
  379. }
  380.  
  381.  
  382. /* ctoi - convert string to integer */
  383. ctoi(s)
  384. char    *s;
  385.  
  386. {
  387.     int    c, sign;
  388.  
  389.     sign = 1;
  390.     while (*s == ' ' || *s == '\t')
  391.         s++;
  392.     c = 0;
  393.     if (*s == '+' || *s == '-')
  394.         sign = (*s++ == '-') ? -1 : 1;
  395.     while (*s != EOS && ctype[*s] == DIGIT)
  396.         c = c*10 + *s++ - '0';
  397.     return(sign * c);
  398. }
  399.  
  400.  
  401. /* lookup - locate name, extract definition from table */
  402. lookup(s, defn)
  403. char    *s, *defn;
  404.  
  405. {
  406.     int    i;
  407.  
  408.     i = tcnt;
  409.     while (--i >= 0)
  410.         if (!strcmp(deftbl[i].name, s))
  411.             break;
  412.     if (i < 0)
  413.         return(NO);
  414.     strcpy(defn, deftbl[i].repn);
  415.     return(YES);
  416. }
  417.  
  418.  
  419. /* install - add name and definition to table */
  420. void install(s, defn)
  421. char    *s, *defn;
  422. {
  423. struct mac *p;
  424.    p = &deftbl[tcnt];
  425.    if ((p->name = (char *) malloc(strlen(s)+1)) == NULL) {
  426.     fprintf(STDERR, "MAC905 Variable table overflow!\n");
  427.     exit();
  428.    }
  429.    strcpy(p->name, s);
  430.    if ((p->repn = (char *) malloc(strlen(defn)+1)) == NULL) {
  431.     fprintf(STDERR, "MAC906 Variable table overflow!\n");
  432.     exit();
  433.    }
  434.    strcpy(p->repn, defn);
  435.    tcnt++;
  436. }
  437.  
  438.  
  439. /* gettok - get alphanumeric string or single non-alpha */
  440. gettok(w, lim)
  441. char    *w;
  442. int    lim;
  443. {
  444. int    c;
  445.     if ((c = getchr()) == EOF)
  446.     return(c);
  447.    else {
  448.     *w++ = c;
  449.     if (ctype[c] != LETTER && ctype[c] != DIGIT) {
  450.         *w = '\0';
  451.         return(c);
  452.     }
  453.     else
  454.         lim--;
  455.    }
  456.    while (lim-- > 0 && (c= getchr()) != EOF) {
  457.     *w++ = c;
  458.     if (ctype[c] != LETTER && ctype[c] != DIGIT) {
  459.         *--w = NULL;
  460.         ungetch(c);
  461.         return(ALPHA);
  462.     }
  463.    }
  464.    *w = NULL;
  465.    ungetch(c);
  466.    fprintf(STDERR,"MAC907 Token too long.\n");
  467.    return(ALPHA);
  468. }
  469.  
  470.  
  471. /* initialize - initializ arrays and others */
  472. void initialize()
  473.  
  474. {
  475.     int i;
  476.  
  477.     for (i = 0; i < 26; i++)
  478.         ctype[i] = i;
  479.     for (i = 'a'; i <= 'z'; i++)
  480.         ctype[i] = LETTER;
  481.     for (i = 'A'; i <= 'Z'; i++)
  482.         ctype[i] = LETTER;
  483.     for (i = '0'; i <= '9'; i++)
  484.         ctype[i] = DIGIT;
  485.     ubufp =0;
  486.     tcnt =0;
  487. }
  488.  
  489.  
  490. /* push -push ep onto argstk, return new pointer ap */
  491. push(evlp, argstk, argp)
  492. int    argstk[];
  493.  
  494. {
  495.     if (argp > ARGSIZE) {
  496.         fprintf(STDERR, "MAC908 Arg stack overflow!\n");
  497.         exit();
  498.     }
  499.     argstk[argp] = evlp;
  500.     return(argp+1);
  501. }
  502.  
  503.  
  504. /* puttok - put a token either on output or into evaluatin stack */
  505. void puttok(s)
  506. char    *s;
  507.  
  508. {
  509.     while (*s) putchr(*s++);
  510. }
  511.  
  512.  
  513. /* putchr - put single char on output or into evaluation stack */
  514. void putchr(c)
  515.  
  516. {
  517.     if (!cp)
  518.         putchar(c);
  519.     else {
  520.         if (ep > EVALSIZE) {
  521.             fprintf(STDERR, "MAC909 Evalation stack overflow!\n");
  522.             exit();
  523.         }
  524.         evalst[ep++] = c;
  525.     }
  526. }
  527.  
  528.  
  529. /* ungets - push string backonto input */
  530. void ungets(s)
  531. char    *s;
  532.  
  533. {
  534.     char    *p;
  535.  
  536.     p = s;
  537.     while (*s)
  538.         s++;
  539.     while (p != s)
  540.         ungetch(*--s);
  541. }
  542.  
  543. /* getchr - get single character */
  544. getchr()
  545.  
  546. {
  547.     if (ubufp)
  548.     return( (int) ubuf[--ubufp]);
  549.    else
  550.     return( (int) getc(infp));
  551. }
  552.  
  553. /* ungetch - push string back onto input */
  554. void ungetch(c)
  555. int    c;
  556.  
  557. {
  558.     if (ubufp > UBUFSIZE)
  559.         fprintf(STDERR,"MAC910 ungetch: too many characters\n");
  560.     else
  561.         ubuf[ubufp++] = c;
  562. }
  563.  
  564. /* Enf of MACRO.C */
  565.