# 2.11BSD#431 - /usr/src/usr.bin/m4/main.c

##### Functions

    initkwds          X
    inspect           X
    macro             X
    main              X

##### Variables

    bbase             X
    bp                X
    buf               X
    bufbase           X
    ecommt            X
    endest            X
    endpbb            X
    ep                X
    fp                X
    hashtab           X
    ilevel            X
    keywrds           X
    lquote            X
    m4temp            X
    m4wraps           X
    null              X
    oindex            X
    progname          X
    rquote            X
    scommt            X
    sp                X
    strspace          X

##### Macros

    MAXKEYS           X

       1: /*-
       2:  * Copyright (c) 1989, 1993
       3:  *	The Regents of the University of California.  All rights reserved.
       4:  *
       5:  * This code is derived from software contributed to Berkeley by
       6:  * Ozan Yigit at York University.
       7:  *
       8:  * Redistribution and use in source and binary forms, with or without
       9:  * modification, are permitted provided that the following conditions
      10:  * are met:
      11:  * 1. Redistributions of source code must retain the above copyright
      12:  *    notice, this list of conditions and the following disclaimer.
      13:  * 2. Redistributions in binary form must reproduce the above copyright
      14:  *    notice, this list of conditions and the following disclaimer in the
      15:  *    documentation and/or other materials provided with the distribution.
      16:  * 3. All advertising materials mentioning features or use of this software
      17:  *    must display the following acknowledgement:
      18:  *	This product includes software developed by the University of
      19:  *	California, Berkeley and its contributors.
      20:  * 4. Neither the name of the University nor the names of its contributors
      21:  *    may be used to endorse or promote products derived from this software
      22:  *    without specific prior written permission.
      23:  *
      24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      34:  * SUCH DAMAGE.
      35:  */
      36:
      37: #if !defined(lint) && defined(DOSCCS)
      38: static char copyright[] =
      39: "@(#) Copyright (c) 1989, 1993\n\
      40: 	The Regents of the University of California.  All rights reserved.\n";
      41:
      42: static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/6/93";
      43: #endif
      44:
      45: /*
      46:  * main.c
      47:  * Facility: m4 macro processor
      48:  * by: oz
      49:  */
      50:
      51: #include <sys/types.h>
      52: #include <signal.h>
      53: #include <errno.h>
      54: #include <stdio.h>
      55: #include <ctype.h>
      56: #include <string.h>
      57: #include "mdef.h"
      58: #include "stdd.h"
      59: #include "extern.h"
      60: #include "pathnames.h"
      61:
      62: ndptr hashtab[HASHSIZE];    /* hash table for macros etc.  */
      63: char buf[BUFSIZE];      /* push-back buffer	       */
      64: char *bufbase = buf;        /* the base for current ilevel */
      65: char *bbase[MAXINP];        /* the base for each ilevel    */
      66: char *bp = buf;         /* first available character   */
      67: char *endpbb = buf+BUFSIZE; /* end of push-back buffer     */
      68: stae mstack[STACKMAX+1];    /* stack of m4 machine         */
      69: char strspace[STRSPMAX+1];  /* string space for evaluation */
      70: char *ep = strspace;        /* first free char in strspace */
      71: char *endest= strspace+STRSPMAX;/* end of string space	       */
      72: int sp;             /* current m4  stack pointer   */
      73: int fp;             /* m4 call frame pointer       */
      74: FILE *infile[MAXINP];       /* input file stack (0=stdin)  */
      75: FILE *outfile[MAXOUT];      /* diversion array(0=bitbucket)*/
      76: FILE *active;           /* active output file pointer  */
      77: char *m4temp;           /* filename for diversions     */
      78: int ilevel = 0;         /* input file stack pointer    */
      79: int oindex = 0;         /* diversion index..	       */
      80: char *null = "";                /* as it says.. just a null..  */
      81: char *m4wraps = "";             /* m4wrap string default..     */
      82: char *progname;         /* name of this program        */
      83: char lquote = LQUOTE;       /* left quote character  (`)   */
      84: char rquote = RQUOTE;       /* right quote character (')   */
      85: char scommt = SCOMMT;       /* start character for comment */
      86: char ecommt = ECOMMT;       /* end character for comment   */
      87:
      88: struct keyblk keywrds[] = { /* m4 keywords to be installed */
      89:     "include",      INCLTYPE,
      90:     "sinclude",     SINCTYPE,
      91:     "define",       DEFITYPE,
      92:     "defn",         DEFNTYPE,
      93:     "divert",       DIVRTYPE,
      94:     "expr",         EXPRTYPE,
      95:     "eval",         EXPRTYPE,
      96:     "substr",       SUBSTYPE,
      97:     "ifelse",       IFELTYPE,
      98:     "ifdef",        IFDFTYPE,
      99:     "len",          LENGTYPE,
     100:     "incr",         INCRTYPE,
     101:     "decr",         DECRTYPE,
     102:     "dnl",          DNLNTYPE,
     103:     "changequote",  CHNQTYPE,
     104:     "changecom",    CHNCTYPE,
     105:     "index",        INDXTYPE,
     106: #ifdef EXTENDED
     107:     "paste",        PASTTYPE,
     108:     "spaste",       SPASTYPE,
     109: #endif
     110:     "popdef",       POPDTYPE,
     111:     "pushdef",      PUSDTYPE,
     112:     "dumpdef",      DUMPTYPE,
     113:     "shift",        SHIFTYPE,
     114:     "translit",     TRNLTYPE,
     115:     "undefine",     UNDFTYPE,
     116:     "undivert",     UNDVTYPE,
     117:     "divnum",       DIVNTYPE,
     118:     "maketemp",     MKTMTYPE,
     119:     "errprint",     ERRPTYPE,
     120:     "m4wrap",       M4WRTYPE,
     121:     "m4exit",       EXITTYPE,
     122:     "syscmd",       SYSCTYPE,
     123:     "sysval",       SYSVTYPE,
     124:
     125: #ifdef unix
     126:     "unix",         MACRTYPE,
     127: #else
     128: #ifdef vms
     129:     "vms",          MACRTYPE,
     130: #endif
     131: #endif
     132: };
     133:
     134: #define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk))
     135:
     136: extern int optind;
     137: extern char *optarg;
     138:
     139: void macro();
     140: void initkwds();
     141: extern int getopt();
     142:
     143: int
     144: main(argc,argv)
     145:     int argc;
     146:     char *argv[];
     147: {
     148:     register int c;
     149:     register int n;
     150:     char *p;
     151:     register FILE *ifp;
     152:
     153:     progname = basename(argv[0]);
     154:
     155:     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
     156:         signal(SIGINT, onintr);
     157:
     158:     initkwds();
     159:
     160:     while ((c = getopt(argc, argv, "tD:U:o:")) != EOF)
     161:         switch(c) {
     162:
     163:         case 'D':               /* define something..*/
     164:             for (p = optarg; *p; p++)
     165:                 if (*p == '=')
     166:                     break;
     167:             if (*p)
     168:                 *p++ = EOS;
     169:             dodefine(optarg, p);
     170:             break;
     171:         case 'U':               /* undefine...       */
     172:             remhash(optarg, TOP);
     173:             break;
     174:         case 'o':       /* specific output   */
     175:         case '?':
     176:             usage();
     177:         }
     178:
     179:         argc -= optind;
     180:         argv += optind;
     181:
     182:     active = stdout;        /* default active output     */
     183:                     /* filename for diversions   */
     184:     m4temp = mktemp(xstrdup(_PATH_DIVNAME));
     185:
     186:     bbase[0] = bufbase;
     187:         if (!argc) {
     188:         sp = -1;        /* stack pointer initialized */
     189:         fp = 0;         /* frame pointer initialized */
     190:         infile[0] = stdin;  /* default input (naturally) */
     191:         macro();
     192:     } else
     193:         for (; argc--; ++argv) {
     194:             p = *argv;
     195:             if (p[0] == '-' && p[1] == '\0')
     196:                 ifp = stdin;
     197:             else if ((ifp = fopen(p, "r")) == NULL)
     198:                 oops("%s: %s", p, strerror(errno));
     199:             sp = -1;
     200:             fp = 0;
     201:             infile[0] = ifp;
     202:             macro();
     203:             if (ifp != stdin)
     204:                 (void)fclose(ifp);
     205:         }
     206:
     207:     if (*m4wraps) {         /* anything for rundown ??   */
     208:         ilevel = 0;     /* in case m4wrap includes.. */
     209:         bufbase = bp = buf; /* use the entire buffer   */
     210:         putback(EOF);       /* eof is a must !!	     */
     211:         pbstr(m4wraps);     /* user-defined wrapup act   */
     212:         macro();        /* last will and testament   */
     213:     }
     214:
     215:     if (active != stdout)
     216:         active = stdout;    /* reset output just in case */
     217:     for (n = 1; n < MAXOUT; n++)    /* default wrap-up: undivert */
     218:         if (outfile[n] != NULL)
     219:             getdiv(n);
     220:                     /* remove bitbucket if used  */
     221:     if (outfile[0] != NULL) {
     222:         (void) fclose(outfile[0]);
     223:         m4temp[UNIQUE] = '0';
     224: #ifdef vms
     225:         (void) remove(m4temp);
     226: #else
     227:         (void) unlink(m4temp);
     228: #endif
     229:     }
     230:
     231:     return 0;
     232: }
     233:
     234: ndptr inspect();
     235:
     236: /*
     237:  * macro - the work horse..
     238:  */
     239: void
     240: macro() {
     241:     char token[MAXTOK];
     242:     register char *s;
     243:     register int t, l;
     244:     register ndptr p;
     245:     register int  nlpar;
     246:
     247:     cycle {
     248:         if ((t = gpbc()) == '_' || isalpha(t)) {
     249:             putback(t);
     250:             if ((p = inspect(s = token)) == nil) {
     251:                 if (sp < 0)
     252:                     while (*s)
     253:                         putc(*s++, active);
     254:                 else
     255:                     while (*s)
     256:                         chrsave(*s++);
     257:             }
     258:             else {
     259:         /*
     260: 		 * real thing.. First build a call frame:
     261: 		 */
     262:                 pushf(fp);  /* previous call frm */
     263:                 pushf(p->type); /* type of the call  */
     264:                 pushf(0);   /* parenthesis level */
     265:                 fp = sp;    /* new frame pointer */
     266:         /*
     267: 		 * now push the string arguments:
     268: 		 */
     269:                 pushs(p->defn);       /* defn string */
     270:                 pushs(p->name);       /* macro name  */
     271:                 pushs(ep);        /* start next..*/
     272:
     273:                 putback(l = gpbc());
     274:                 if (l != LPAREN)  {   /* add bracks  */
     275:                     putback(RPAREN);
     276:                     putback(LPAREN);
     277:                 }
     278:             }
     279:         }
     280:         else if (t == EOF) {
     281:             if (sp > -1)
     282:                 oops("unexpected end of input", "");
     283:             if (ilevel <= 0)
     284:                 break;          /* all done thanks.. */
     285:             --ilevel;
     286:             (void) fclose(infile[ilevel+1]);
     287:             bufbase = bbase[ilevel];
     288:             continue;
     289:         }
     290:     /*
     291: 	 * non-alpha single-char token seen..
     292: 	 * [the order of else if .. stmts is important.]
     293: 	 */
     294:         else if (t == lquote) {         /* strip quotes */
     295:             nlpar = 1;
     296:             do {
     297:                 if ((l = gpbc()) == rquote)
     298:                     nlpar--;
     299:                 else if (l == lquote)
     300:                     nlpar++;
     301:                 else if (l == EOF)
     302:                     oops("missing right quote", "");
     303:                 if (nlpar > 0) {
     304:                     if (sp < 0)
     305:                         putc(l, active);
     306:                     else
     307:                         chrsave(l);
     308:                 }
     309:             }
     310:             while (nlpar != 0);
     311:         }
     312:
     313:         else if (sp < 0) {      /* not in a macro at all */
     314:             if (t == scommt) {  /* comment handling here */
     315:                 putc(t, active);
     316:                 while ((t = gpbc()) != ecommt)
     317:                     putc(t, active);
     318:             }
     319:             putc(t, active);    /* output directly..	 */
     320:         }
     321:
     322:         else switch(t) {
     323:
     324:         case LPAREN:
     325:             if (PARLEV > 0)
     326:                 chrsave(t);
     327:             while (isspace(l = gpbc()))
     328:                 ;       /* skip blank, tab, nl.. */
     329:             putback(l);
     330:             PARLEV++;
     331:             break;
     332:
     333:         case RPAREN:
     334:             if (--PARLEV > 0)
     335:                 chrsave(t);
     336:             else {          /* end of argument list */
     337:                 chrsave(EOS);
     338:
     339:                 if (sp == STACKMAX)
     340:                     oops("internal stack overflow", "");
     341:
     342:                 if (CALTYP == MACRTYPE)
     343:                     expand((char **) mstack+fp+1, sp-fp);
     344:                 else
     345:                     eval((char **) mstack+fp+1, sp-fp, CALTYP);
     346:
     347:                 ep = PREVEP;    /* flush strspace */
     348:                 sp = PREVSP;    /* previous sp..  */
     349:                 fp = PREVFP;    /* rewind stack...*/
     350:             }
     351:             break;
     352:
     353:         case COMMA:
     354:             if (PARLEV == 1) {
     355:                 chrsave(EOS);       /* new argument   */
     356:                 while (isspace(l = gpbc()))
     357:                     ;
     358:                 putback(l);
     359:                 pushs(ep);
     360:             } else
     361:                 chrsave(t);
     362:             break;
     363:
     364:         default:
     365:             chrsave(t);         /* stack the char */
     366:             break;
     367:         }
     368:     }
     369: }
     370:
     371: /*
     372:  * build an input token..
     373:  * consider only those starting with _ or A-Za-z. This is a
     374:  * combo with lookup to speed things up.
     375:  */
     376: ndptr
     377: inspect(tp)
     378: register char *tp;
     379: {
     380:     register char c;
     381:     register char *name = tp;
     382:     register char *etp = tp+MAXTOK;
     383:     register ndptr p;
     384:     register unsigned long h = 0;
     385:
     386:     while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
     387:         h = (h << 5) + h + (*tp++ = c);
     388:     putback(c);
     389:     if (tp == etp)
     390:         oops("token too long", "");
     391:
     392:     *tp = EOS;
     393:
     394:     for (p = hashtab[h%HASHSIZE]; p != nil; p = p->nxtptr)
     395:         if (STREQ(name, p->name))
     396:             break;
     397:     return p;
     398: }
     399:
     400: /*
     401:  * initkwds - initialise m4 keywords as fast as possible.
     402:  * This very similar to install, but without certain overheads,
     403:  * such as calling lookup. Malloc is not used for storing the
     404:  * keyword strings, since we simply use the static  pointers
     405:  * within keywrds block.
     406:  */
     407: void
     408: initkwds() {
     409:     register int i;
     410:     register int h;
     411:     register ndptr p;
     412:
     413:     for (i = 0; i < MAXKEYS; i++) {
     414:         h = hash(keywrds[i].knam);
     415:         p = (ndptr) xalloc(sizeof(struct ndblock));
     416:         p->nxtptr = hashtab[h];
     417:         hashtab[h] = p;
     418:         p->name = keywrds[i].knam;
     419:         p->defn = null;
     420:         p->type = keywrds[i].ktyp | STATIC;
     421:     }
     422: }

#### Defined functions

initkwds defined in line 407; used 2 times

- in line 140, 158

inspect defined in line 376; used 2 times

- in line 234, 250

macro defined in line 239; used 4 times

- in line 139, 191, 202, 212

main defined in line 143; never used

#### Defined variables

bbase defined in line 65; used 4 times

- in line 186, 287
- in /usr/src/usr.bin/m4/main.c line 186, 287

bp defined in line 66; used 6 times

- in line 209
- in /usr/src/usr.bin/m4/main.c line 209
- in /usr/src/usr.bin/m4/misc.c line 76-77(2), 95, 103

buf defined in line 63; used 8 times

- in line 64-67(3), 209
- in /usr/src/usr.bin/m4/main.c line 64-67(3), 209

bufbase defined in line 64; used 6 times

- in line 186, 209, 287
- in /usr/src/usr.bin/m4/main.c line 186, 209, 287

copyright defined in line 38; never used
ecommt defined in line 86; used 2 times

- in line 316
- in /usr/src/usr.bin/m4/main.c line 316

endest defined in line 71; used 1 times

- in /usr/src/usr.bin/m4/misc.c line 133

endpbb defined in line 67; used 3 times

- in /usr/src/usr.bin/m4/misc.c line 76, 101-103(2)

ep defined in line 70; used 8 times

- in line 271, 347, 359
- in /usr/src/usr.bin/m4/main.c line 271, 347, 359
- in /usr/src/usr.bin/m4/misc.c line 133-134(2)

fp defined in line 73; used 18 times

- in line 189, 200, 262-265(2), 343-349(5)
- in /usr/src/usr.bin/m4/main.c line 189, 200, 262-265(2), 343-349(5)

hashtab defined in line 62; used 3 times

- in line 394, 416-417(2)

ilevel defined in line 78; used 10 times

- in line 208, 283-287(4)
- in /usr/src/usr.bin/m4/main.c line 208, 283-287(4)

keywrds defined in line 88; used 4 times

- in line 134, 414-420(3)

lquote defined in line 83; used 4 times

- in line 294-299(2)
- in /usr/src/usr.bin/m4/main.c line 294-299(2)

m4temp defined in line 77; used 14 times

- in line 184, 223-227(3)
- in /usr/src/usr.bin/m4/main.c line 184, 223-227(3)
- in /usr/src/usr.bin/m4/misc.c line 153-155(3), 162-166(3)

m4wraps defined in line 81; used 4 times

- in line 207-211(2)
- in /usr/src/usr.bin/m4/main.c line 207-211(2)

null defined in line 80; used 3 times

- in line 419
- in /usr/src/usr.bin/m4/look.c line 104
- in /usr/src/usr.bin/m4/main.c line 419

oindex defined in line 79; never used
progname defined in line 82; used 3 times

- in line 153
- in /usr/src/usr.bin/m4/main.c line 153
- in /usr/src/usr.bin/m4/misc.c line 238

rquote defined in line 84; used 2 times

- in line 297
- in /usr/src/usr.bin/m4/main.c line 297

sccsid defined in line 42; never used
scommt defined in line 85; used 2 times

- in line 314
- in /usr/src/usr.bin/m4/main.c line 314

sp defined in line 72; used 22 times

- in line 188, 199, 251, 265, 281, 304, 313, 339-348(4)
- in /usr/src/usr.bin/m4/main.c line 188, 199, 251, 265, 281, 304, 313, 339-348(4)

strspace defined in line 69; used 2 times

- in line 70-71(2)

#### Defined macros

MAXKEYS defined in line 134; used 1 times

- in line 413

Last modified: 1994-04-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1812 |