Annotation of coherent/b/bin/c/n0/expand.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * n0/expand.c
                      3:  * C preprocessor.
                      4:  * Macro expansion.
                      5:  */
                      6: 
                      7: #include <time.h>
                      8: #ifdef   vax
                      9: #include "INC$LIB:cc0.h"
                     10: #else
                     11: #include "cc0.h"
                     12: #endif
                     13: 
                     14: /*
                     15:  * Expand the string as an actual parameter.
                     16:  * This happens after the list of strings
                     17:  * in the substituted macro has been pushed
                     18:  * onto dstack; expand the string as if it
                     19:  * formed the rest of the source file and
                     20:  * substitute the expanded string back into
                     21:  * the source stream, with the hidden sets of
                     22:  * identifiers augmented by the macro name we
                     23:  * are substituting.
                     24:  */
                     25: char *argexpand(hide, p) int hide; char *p;
                     26: {
                     27:        register char *ap, *spshp;
                     28:        register int c;
                     29: 
                     30:        /* Push the parameter as input */
                     31:        dspush(DS_IEOF, NULL);
                     32:        dspush(DS_STRNG, p);
                     33:        /* Save the push buffer */
                     34:        spshp = dpshp;
                     35:        /* Scan the parameter as input */
                     36:        while ((c = get()) >= 0) {
                     37:                switch (ct[c]) {
                     38:                case QUOTE:
                     39:                case STRING:
                     40:                        dpshstr(c);
                     41:                        continue;
                     42:                case DOT:
                     43:                case CON:
                     44:                        dpshnum(c);
                     45:                        continue;
                     46:                case ID:
                     47:                        if (expand(c))
                     48:                                continue;
                     49:                        dpshs(id);
                     50:                        /* Augment hidden set */
                     51:                        dpshc(hideaug(hide, idhide));
                     52:                        continue;
                     53:                default:
                     54:                        dpshc(c);
                     55:                        continue;
                     56:                }
                     57:        }
                     58:        ++dstackp;                      /* pop IEOF */
                     59:        /* Now pop the expanded string off the push buffer */
                     60:        /* and onto the put buffer */
                     61:        p = dputp;
                     62:        for (ap = spshp; --ap >= dpshp; )
                     63:                dputc(*ap);
                     64:        dputc(0);
                     65:        /* Restore push buffer pointer */
                     66:        dpshp = spshp;
                     67:        /* Return pointer to expanded argument */
                     68:        return p;
                     69: }
                     70: 
                     71: /*
                     72:  * Scan and augment the hidden sets in a string.
                     73:  * An in place copy in essence.
                     74:  */
                     75: char *argpaste(hide, p) int hide; char *p;
                     76: {
                     77:        register int c;
                     78:        char *sputp;
                     79:        sputp = dputp;
                     80:        dputp = p;
                     81:        dspush(DS_IEOF, NULL);
                     82:        dspush(DS_STRNG, p);
                     83:        while ((c = get()) >= 0) {
                     84:                switch (ct[c]) {
                     85:                case QUOTE:
                     86:                case STRING:
                     87:                        dputstr(c);
                     88:                        continue;
                     89:                case DOT:
                     90:                case CON:
                     91:                        dputnum(c);
                     92:                        continue;
                     93:                case ID:
                     94:                        getid(c);
                     95:                        dputs(id);
                     96:                        /* Augment hidden set */
                     97:                        dputc(hideaug(hide, idhide));
                     98:                        continue;
                     99:                default:
                    100:                        dputc(c);
                    101:                        continue;
                    102:                }
                    103:        }
                    104:        ++dstackp;
                    105:        dputp = sputp;
                    106:        return p;
                    107: }
                    108: 
                    109: 
                    110: /*
                    111:  * Substitute for the macro specified.
                    112:  * Collect the actual parameters into the push buffer,
                    113:  * then reverse them onto the put buffer.
                    114:  * (Collecting the parameters may pop the dstackp.)
                    115:  * Then parse the macro body into the put buffer,
                    116:  * forming a list of literal strings
                    117:  * (with their hidden sets augmented),
                    118:  * # parameters, ## parameters, and
                    119:  * vanilla parameters.
                    120:  * Then scan the list pushed and
                    121:  * recursively expand the vanilla
                    122:  * parameters with argexpand(),
                    123:  * expanding each parameter only once
                    124:  * no matter how many times it appears
                    125:  * in the substituted body.
                    126:  * Then rescan the list pushed again
                    127:  * to augment the hidden sets of ## params.
                    128:  */
                    129: substitute(tp, sp) TOK *tp; CPPSYM *sp;
                    130: {
                    131:        register int c, d;
                    132:        register int narg, plev;
                    133:        register char *p, *pp;
                    134:        register DSTACK *dsp;
                    135:        DSTACK *dparamp, *dbodyp, *dbasep;
                    136:        char *cparamp;
                    137:        int tpidhide;
                    138: 
                    139:        /* Install hide set index */
                    140:        tpidhide = hideset(tp);
                    141: 
                    142:        /* Collect parameters */
                    143:        dparamp = dlistp;
                    144:        cparamp = dpshp;
                    145:        if (sp->s_value == XUSERA) {
                    146:                c = getskip();
                    147:                for (narg = 0; c >= 0 && c != ')'; narg += 1) {
                    148:                        plev = 0; p = dpshp;
                    149:                        while (c >= 0) {
                    150:                                switch (ct[c]) {
                    151:                                case QUOTE:
                    152:                                case STRING:
                    153:                                        dpshstr(c); c = get(); continue;
                    154:                                case LPAREN:
                    155:                                        plev++; break;
                    156:                                case COMMA:
                    157:                                        if (!plev) goto next; break;
                    158:                                case RPAREN:
                    159:                                        if (!plev) goto next; plev--; break;
                    160:                                case SKIP:
                    161:                                        unget(getskip()); c = ' '; break;
                    162:                                case ID:
                    163:                                        getid(c); dpshs(id); dpshc(idhide);
                    164:                                        c = get(); continue;
                    165:                                case DOT:
                    166:                                case CON:
                    167:                                        dpshnum(c); c = get(); continue;
                    168:                                }
                    169:                                dpshc(c); c = get();
                    170:                        }
                    171:                next:   if (narg < sp->s_narg) {
                    172:                                if (dpshp < p && dpshp[0] == ' ')
                    173:                                        ++dpshp;
                    174:                                dpshc(0);
                    175:                                dslist(DS_PARAM, p);
                    176:                        }
                    177:                        if (c == ',')
                    178:                                c = getskip();
                    179:                }
                    180:                if (c < 0) {
                    181:                        cerror("EOF in macro \"%s\" invocation", tp->t_id);
                    182:                        tp = NULL;
                    183:                }
                    184:                if (sp->s_narg != narg) {
                    185:                        cerror("\"%s\" argument mismatch", tp->t_id);
                    186:                        tp = NULL;
                    187:                }
                    188:                if (tp == NULL) {
                    189:                        dlistp = dparamp;
                    190:                        dpshp = cparamp;
                    191:                        return 1;
                    192:                }
                    193:        }
                    194:        /* Copy the parameter strings onto the top of dbuf */
                    195:        dpshp = cparamp;
                    196:        cparamp = dputp;
                    197:        for (dsp = dparamp+sp->s_narg; --dsp >= dparamp; ) {
                    198:                p = dsp->ds_ptr;
                    199:                dsp->ds_ptr = dputp;
                    200:                while (d = *--p) dputc(d);
                    201:                dputc(d);
                    202:        }
                    203:        /* Copy the macro body into dbuf */
                    204:        dbodyp = dlistp;
                    205:        dspush(DS_IEOF, 0);
                    206:        dspush(DS_STRNG, sp->s_body);
                    207:        p = dputp;
                    208:        dsp = dparamp;
                    209:        while ((c = get()) >= 0) {
                    210:                switch (ct[c]) {
                    211:                case QUOTE:
                    212:                case STRING:
                    213:                        dputstr(c); continue;
                    214:                case ID:
                    215:                        getid(c);
                    216:                        dputs(id);
                    217:                        dputc(hideaug(tpidhide, idhide));
                    218:                        continue;
                    219:                case CON:
                    220:                case DOT:
                    221:                        dputnum(c); continue;
                    222:                default:
                    223:                        dputc(c); continue;
                    224:                case HIGH0:             /* param */
                    225:                        c -= ARG0;
                    226:                        pp = dsp[c].ds_ptr;
                    227:                        if (p != dputp) {
                    228:                                dputc(0);
                    229:                                dslist(DS_STRNG, p);
                    230:                                p = dputp;
                    231:                        }
                    232:                        c = get();
                    233:                        d = get();
                    234:                        unget(d);
                    235:                        unget(c);
                    236:                        if (c == '#' && d == '#')
                    237:                                dslist(DS_SHARP2, pp);
                    238:                        else
                    239:                                dslist(DS_PARAM, pp);
                    240:                        continue;
                    241:                case SHARP:             /* # or ## */
                    242:                        c = get();
                    243:                        if (ct[c] == HIGH0) {
                    244:                                c -= ARG0;
                    245:                                pp = dsp[c].ds_ptr;
                    246:                                if (p != dputp) {
                    247:                                        dputc(0);
                    248:                                        dslist(DS_STRNG, p);
                    249:                                        p = dputp;
                    250:                                }
                    251:                                dslistc(DS_UNGET, '"');
                    252:                                dslist(DS_SHARP, pp);
                    253:                                dslistc(DS_UNGET, '"');
                    254:                                continue;
                    255:                        }
                    256:                        c = get();
                    257:                        if (ct[c] == HIGH0) {
                    258:                                c -= ARG0;
                    259:                                pp = dsp[c].ds_ptr;
                    260:                                if (p != dputp) {
                    261:                                        dputc(0);
                    262:                                        dslist(DS_STRNG, p);
                    263:                                        p = dputp;
                    264:                                }
                    265:                                dslist(DS_SHARP2, pp);
                    266:                                continue;
                    267:                        }
                    268:                        unget(c);
                    269:                        continue;
                    270:                }
                    271:        }
                    272:        if (p != dputp) {
                    273:                dputc(0);
                    274:                dslist(DS_STRNG, p);
                    275:                p = dputp;
                    276:        }
                    277:        ++dstackp;      /* Pop IEOF */
                    278:        dbasep = dstackp;
                    279:        dspush(DS_NAME, tp);
                    280:        dspush(DS_DPUTP, cparamp);
                    281:        while (--dlistp >= dbodyp)
                    282:                *--dstackp = *dlistp;
                    283:        dlistp = dparamp;
                    284:        /* Expand parameters and augment their hidden sets */
                    285:        for (dsp = dstackp; dsp < dbasep; dsp += 1) {
                    286:                if (dsp->ds_type == DS_PARAM) {
                    287:                        p = argexpand(tpidhide, pp = dsp->ds_ptr);
                    288:                        /* Now make all references to pp */
                    289:                        /* refer to the expanded version p */
                    290:                        for (dparamp = dsp; dsp < dbasep; dsp += 1)
                    291:                                if (dsp->ds_type == DS_PARAM
                    292:                                 && dsp->ds_ptr == pp) {
                    293:                                        dsp->ds_type = DS_STRNG;
                    294:                                        dsp->ds_ptr = p;
                    295:                                }
                    296:                        dsp = dparamp;
                    297:                }
                    298:        }
                    299:        /* Now scan for glued parameters and augment their hidden sets */
                    300:        /* Done in a separate loop since ##param might appear before */
                    301:        /* param itself in the substitution list, and they both refer */
                    302:        /* to the same copy of the parameter in dbuf before argexpand */
                    303:        for (dsp = dstackp; dsp < dbasep; dsp += 1) {
                    304:                if (dsp->ds_type == DS_SHARP2) {
                    305:                        p = argpaste(tpidhide, pp = dsp->ds_ptr);
                    306:                        for (dparamp = dsp; dsp < dbasep; dsp += 1)
                    307:                                if (dsp->ds_type == DS_SHARP2
                    308:                                 && dsp->ds_ptr == pp) {
                    309:                                        dsp->ds_type = DS_STRNG;
                    310:                                        dsp->ds_ptr = p;
                    311:                                }
                    312:                        dsp = dparamp;
                    313:                }
                    314:        }
                    315:        return 1;
                    316: }
                    317: 
                    318: /*
                    319:  * Try macro expansion,
                    320:  * return true if it happened.
                    321:  * Read id[] starting with 'c'
                    322:  * and see if it is defined.
                    323:  * Since this is called for each
                    324:  * identifier read, it should use
                    325:  * minimal registers and defer most
                    326:  * processing to subfunctions.
                    327:  */
                    328: expand(c) register int c;
                    329: {
                    330:        char *p;
                    331:        CPPSYM *sp;
                    332:        TOK *tp;
                    333:        extern char *ctime();
                    334:        static char lineno[16];
                    335: 
                    336:        getid(c);
                    337:        tp = idp;
                    338:        if ((sp=idp->t_sym) == NULL
                    339:         || sp->s_slevel != SL_CPP
                    340:         || hidden()) {
                    341:  none_such:    if (incpp > 1) {        /* Parsing a #if expression */
                    342:                        dspush(DS_STRNG, deffalse);
                    343:                        return 1;
                    344:                }
                    345:                return 0;
                    346:        }
                    347: 
                    348:        switch ((int)sp->s_value) {
                    349:        case XUSER:
                    350:                return substitute(tp, sp);
                    351:        case XUFILE:
                    352:                unget('"');
                    353:                dspush(DS_UFILE, file);
                    354:                unget('"');
                    355:                return 1;
                    356:        case XUBASE:
                    357:                unget('"');
                    358:                dspush(DS_UFILE, basefile);
                    359:                unget('"');
                    360:                return 1;
                    361:        case XULINE:
                    362:                dspush(DS_STRNG, lineno);
                    363:                sprintf(lineno, "%d", line);
                    364:                return 1;
                    365:        case XUDATE:
                    366:        case XUTIME:
                    367:                p = ctime(&curtime);
                    368:                if (sp->s_value == XUDATE) {
                    369:                        p[24] = 0;
                    370:                        strcpy(p+11, p+20);
                    371:                        p += 4;
                    372:                } else {
                    373:                        p[19] = 0;
                    374:                        p += 11;
                    375:                }
                    376:                unget('"');
                    377:                dspush(DS_STRNG, p);
                    378:                unget('"');
                    379:                return 1;
                    380: #if    0
                    381: /*
                    382:  * ANSI C says __STDC__ should be defined as 0 for a non-ANSI compiler,
                    383:  * but too many sources use #ifdef __STDC__ when they should use #if __STDC__.
                    384:  * This is therefore conditionalized out here and in n0/cc0key.c.
                    385:  */
                    386:        case XUSTDC:
                    387:                dspush(DS_STRNG, deffalse);
                    388:                return 1;
                    389: #endif
                    390:        case XDEFINED:
                    391:                if (incpp < 2)
                    392:                        return 0;
                    393:                if ((c = getnb()) == '(') {
                    394:                        if ((c = getnb()) < 0 || ct[c] != ID)
                    395:                                goto bad;
                    396:                        getid(c);
                    397:                        if ((c = getnb()) != ')')
                    398:                                goto bad;
                    399:                } else if (ct[c] == ID)
                    400:                        getid(c);
                    401:                else {
                    402:        bad:            cerror("illegal use of defined");
                    403:                        dspush(DS_STRNG, deffalse);
                    404:                        return 1;
                    405:                }
                    406:                tp = idp;
                    407:                if ((sp = tp->t_sym) != NULL
                    408:                 && sp->s_slevel == SL_CPP
                    409:                 && ! hidden())
                    410:                        dspush(DS_STRNG, deftrue);
                    411:                else
                    412:                        dspush(DS_STRNG, deffalse);
                    413:                return 1;
                    414:        case XUSERA:
                    415:                if (skipto('('))
                    416:                        return substitute(tp, sp);
                    417:                goto none_such;
                    418:        default:
                    419:                cbotch("value %d in expand", sp->s_value);
                    420:        }
                    421:        return 0;
                    422: }
                    423: 
                    424: /* end of n0/expand.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.