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

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

unix.superglobalmegacorp.com

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