home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 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