OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [lcc/] [cpp/] [macro.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 hellwig
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include "cpp.h"
5
 
6
/*
7
 * do a macro definition.  tp points to the name being defined in the line
8
 */
9
void
10
dodefine(Tokenrow *trp)
11
{
12
        Token *tp;
13
        Nlist *np;
14
        Tokenrow *def, *args;
15
 
16
        tp = trp->tp+1;
17
        if (tp>=trp->lp || tp->type!=NAME) {
18
                error(ERROR, "#defined token is not a name");
19
                return;
20
        }
21
        np = lookup(tp, 1);
22
        if (np->flag&ISUNCHANGE) {
23
                error(ERROR, "#defined token %t can't be redefined", tp);
24
                return;
25
        }
26
        /* collect arguments */
27
        tp += 1;
28
        args = NULL;
29
        if (tp<trp->lp && tp->type==LP && tp->wslen==0) {
30
                /* macro with args */
31
                int narg = 0;
32
                tp += 1;
33
                args = new(Tokenrow);
34
                maketokenrow(2, args);
35
                if (tp->type!=RP) {
36
                        int err = 0;
37
                        for (;;) {
38
                                Token *atp;
39
                                if (tp->type!=NAME) {
40
                                        err++;
41
                                        break;
42
                                }
43
                                if (narg>=args->max)
44
                                        growtokenrow(args);
45
                                for (atp=args->bp; atp<args->lp; atp++)
46
                                        if (atp->len==tp->len
47
                                         && strncmp((char*)atp->t, (char*)tp->t, tp->len)==0)
48
                                                error(ERROR, "Duplicate macro argument");
49
                                *args->lp++ = *tp;
50
                                narg++;
51
                                tp += 1;
52
                                if (tp->type==RP)
53
                                        break;
54
                                if (tp->type!=COMMA) {
55
                                        err++;
56
                                        break;
57
                                }
58
                                tp += 1;
59
                        }
60
                        if (err) {
61
                                error(ERROR, "Syntax error in macro parameters");
62
                                return;
63
                        }
64
                }
65
                tp += 1;
66
        }
67
        trp->tp = tp;
68
        if (((trp->lp)-1)->type==NL)
69
                trp->lp -= 1;
70
        def = normtokenrow(trp);
71
        if (np->flag&ISDEFINED) {
72
                if (comparetokens(def, np->vp)
73
                 || (np->ap==NULL) != (args==NULL)
74
                 || np->ap && comparetokens(args, np->ap))
75
                        error(ERROR, "Macro redefinition of %t", trp->bp+2);
76
        }
77
        if (args) {
78
                Tokenrow *tap;
79
                tap = normtokenrow(args);
80
                dofree(args->bp);
81
                args = tap;
82
        }
83
        np->ap = args;
84
        np->vp = def;
85
        np->flag |= ISDEFINED;
86
}
87
 
88
/*
89
 * Definition received via -D or -U
90
 */
91
void
92
doadefine(Tokenrow *trp, int type)
93
{
94
        Nlist *np;
95
        static unsigned char one[] = "1";
96
        static Token onetoken[1] = {{ NUMBER, 0, 0, 0, 1, one }};
97
        static Tokenrow onetr = { onetoken, onetoken, onetoken+1, 1 };
98
 
99
        trp->tp = trp->bp;
100
        if (type=='U') {
101
                if (trp->lp-trp->tp != 2 || trp->tp->type!=NAME)
102
                        goto syntax;
103
                if ((np = lookup(trp->tp, 0)) == NULL)
104
                        return;
105
                np->flag &= ~ISDEFINED;
106
                return;
107
        }
108
        if (trp->tp >= trp->lp || trp->tp->type!=NAME)
109
                goto syntax;
110
        np = lookup(trp->tp, 1);
111
        np->flag |= ISDEFINED;
112
        trp->tp += 1;
113
        if (trp->tp >= trp->lp || trp->tp->type==END) {
114
                np->vp = &onetr;
115
                return;
116
        }
117
        if (trp->tp->type!=ASGN)
118
                goto syntax;
119
        trp->tp += 1;
120
        if ((trp->lp-1)->type == END)
121
                trp->lp -= 1;
122
        np->vp = normtokenrow(trp);
123
        return;
124
syntax:
125
        error(FATAL, "Illegal -D or -U argument %r", trp);
126
}
127
 
128
/*
129
 * Do macro expansion in a row of tokens.
130
 * Flag is NULL if more input can be gathered.
131
 */
132
void
133
expandrow(Tokenrow *trp, char *flag)
134
{
135
        Token *tp;
136
        Nlist *np;
137
 
138
        if (flag)
139
                setsource(flag, NULL, "");
140
        for (tp = trp->tp; tp<trp->lp; ) {
141
                if (tp->type!=NAME
142
                 || quicklook(tp->t[0], tp->len>1?tp->t[1]:0)==0
143
                 || (np = lookup(tp, 0))==NULL
144
                 || (np->flag&(ISDEFINED|ISMAC))==0
145
                 || tp->hideset && checkhideset(tp->hideset, np)) {
146
                        tp++;
147
                        continue;
148
                }
149
                trp->tp = tp;
150
                if (np->val==KDEFINED) {
151
                        tp->type = DEFINED;
152
                        if ((tp+1)<trp->lp && (tp+1)->type==NAME)
153
                                (tp+1)->type = NAME1;
154
                        else if ((tp+3)<trp->lp && (tp+1)->type==LP
155
                         && (tp+2)->type==NAME && (tp+3)->type==RP)
156
                                (tp+2)->type = NAME1;
157
                        else
158
                                error(ERROR, "Incorrect syntax for `defined'");
159
                        tp++;
160
                        continue;
161
                }
162
                if (np->flag&ISMAC)
163
                        builtin(trp, np->val);
164
                else {
165
                        expand(trp, np);
166
                }
167
                tp = trp->tp;
168
        }
169
        if (flag)
170
                unsetsource();
171
}
172
 
173
/*
174
 * Expand the macro whose name is np, at token trp->tp, in the tokenrow.
175
 * Return trp->tp at the first token next to be expanded
176
 * (ordinarily the beginning of the expansion)
177
 */
178
void
179
expand(Tokenrow *trp, Nlist *np)
180
{
181
        Tokenrow ntr;
182
        int ntokc, narg, i;
183
        Token *tp;
184
        Tokenrow *atr[NARG+1];
185
        int hs;
186
 
187
        copytokenrow(&ntr, np->vp);             /* copy macro value */
188
        if (np->ap==NULL)                       /* parameterless */
189
                ntokc = 1;
190
        else {
191
                ntokc = gatherargs(trp, atr, &narg);
192
                if (narg<0) {                    /* not actually a call (no '(') */
193
                        /* gatherargs has already pushed trp->tr to the next token */
194
                        return;
195
                }
196
                if (narg != rowlen(np->ap)) {
197
                        error(ERROR, "Disagreement in number of macro arguments");
198
                        trp->tp->hideset = newhideset(trp->tp->hideset, np);
199
                        trp->tp += ntokc;
200
                        return;
201
                }
202
                substargs(np, &ntr, atr);       /* put args into replacement */
203
                for (i=0; i<narg; i++) {
204
                        dofree(atr[i]->bp);
205
                        dofree(atr[i]);
206
                }
207
        }
208
        doconcat(&ntr);                         /* execute ## operators */
209
        hs = newhideset(trp->tp->hideset, np);
210
        for (tp=ntr.bp; tp<ntr.lp; tp++) {      /* distribute hidesets */
211
                if (tp->type==NAME) {
212
                        if (tp->hideset==0)
213
                                tp->hideset = hs;
214
                        else
215
                                tp->hideset = unionhideset(tp->hideset, hs);
216
                }
217
        }
218
        ntr.tp = ntr.bp;
219
        insertrow(trp, ntokc, &ntr);
220
        trp->tp -= rowlen(&ntr);
221
        dofree(ntr.bp);
222
        return;
223
}
224
 
225
/*
226
 * Gather an arglist, starting in trp with tp pointing at the macro name.
227
 * Return total number of tokens passed, stash number of args found.
228
 * trp->tp is not changed relative to the tokenrow.
229
 */
230
int
231
gatherargs(Tokenrow *trp, Tokenrow **atr, int *narg)
232
{
233
        int parens = 1;
234
        int ntok = 0;
235
        Token *bp, *lp;
236
        Tokenrow ttr;
237
        int ntokp;
238
        int needspace;
239
 
240
        *narg = -1;                     /* means that there is no macro call */
241
        /* look for the ( */
242
        for (;;) {
243
                trp->tp++;
244
                ntok++;
245
                if (trp->tp >= trp->lp) {
246
                        gettokens(trp, 0);
247
                        if ((trp->lp-1)->type==END) {
248
                                trp->lp -= 1;
249
                                trp->tp -= ntok;
250
                                return ntok;
251
                        }
252
                }
253
                if (trp->tp->type==LP)
254
                        break;
255
                if (trp->tp->type!=NL)
256
                        return ntok;
257
        }
258
        *narg = 0;
259
        ntok++;
260
        ntokp = ntok;
261
        trp->tp++;
262
        /* search for the terminating ), possibly extending the row */
263
        needspace = 0;
264
        while (parens>0) {
265
                if (trp->tp >= trp->lp)
266
                        gettokens(trp, 0);
267
                if (needspace) {
268
                        needspace = 0;
269
                        makespace(trp);
270
                }
271
                if (trp->tp->type==END) {
272
                        trp->lp -= 1;
273
                        trp->tp -= ntok;
274
                        error(ERROR, "EOF in macro arglist");
275
                        return ntok;
276
                }
277
                if (trp->tp->type==NL) {
278
                        trp->tp += 1;
279
                        adjustrow(trp, -1);
280
                        trp->tp -= 1;
281
                        makespace(trp);
282
                        needspace = 1;
283
                        continue;
284
                }
285
                if (trp->tp->type==LP)
286
                        parens++;
287
                else if (trp->tp->type==RP)
288
                        parens--;
289
                trp->tp++;
290
                ntok++;
291
        }
292
        trp->tp -= ntok;
293
        /* Now trp->tp won't move underneath us */
294
        lp = bp = trp->tp+ntokp;
295
        for (; parens>=0; lp++) {
296
                if (lp->type == LP) {
297
                        parens++;
298
                        continue;
299
                }
300
                if (lp->type==RP)
301
                        parens--;
302
                if (lp->type==DSHARP)
303
                        lp->type = DSHARP1;     /* ## not special in arg */
304
                if (lp->type==COMMA && parens==0 || parens<0 && (lp-1)->type!=LP) {
305
                        if (*narg>=NARG-1)
306
                                error(FATAL, "Sorry, too many macro arguments");
307
                        ttr.bp = ttr.tp = bp;
308
                        ttr.lp = lp;
309
                        atr[(*narg)++] = normtokenrow(&ttr);
310
                        bp = lp+1;
311
                }
312
        }
313
        return ntok;
314
}
315
 
316
/*
317
 * substitute the argument list into the replacement string
318
 *  This would be simple except for ## and #
319
 */
320
void
321
substargs(Nlist *np, Tokenrow *rtr, Tokenrow **atr)
322
{
323
        Tokenrow tatr;
324
        Token *tp;
325
        int ntok, argno;
326
 
327
        for (rtr->tp=rtr->bp; rtr->tp<rtr->lp; ) {
328
                if (rtr->tp->type==SHARP) {     /* string operator */
329
                        tp = rtr->tp;
330
                        rtr->tp += 1;
331
                        if ((argno = lookuparg(np, rtr->tp))<0) {
332
                                error(ERROR, "# not followed by macro parameter");
333
                                continue;
334
                        }
335
                        ntok = 1 + (rtr->tp - tp);
336
                        rtr->tp = tp;
337
                        insertrow(rtr, ntok, stringify(atr[argno]));
338
                        continue;
339
                }
340
                if (rtr->tp->type==NAME
341
                 && (argno = lookuparg(np, rtr->tp)) >= 0) {
342
                        if ((rtr->tp+1)->type==DSHARP
343
                         || rtr->tp!=rtr->bp && (rtr->tp-1)->type==DSHARP)
344
                                insertrow(rtr, 1, atr[argno]);
345
                        else {
346
                                copytokenrow(&tatr, atr[argno]);
347
                                expandrow(&tatr, "<macro>");
348
                                insertrow(rtr, 1, &tatr);
349
                                dofree(tatr.bp);
350
                        }
351
                        continue;
352
                }
353
                rtr->tp++;
354
        }
355
}
356
 
357
/*
358
 * Evaluate the ## operators in a tokenrow
359
 */
360
void
361
doconcat(Tokenrow *trp)
362
{
363
        Token *ltp, *ntp;
364
        Tokenrow ntr;
365
        int len;
366
 
367
        for (trp->tp=trp->bp; trp->tp<trp->lp; trp->tp++) {
368
                if (trp->tp->type==DSHARP1)
369
                        trp->tp->type = DSHARP;
370
                else if (trp->tp->type==DSHARP) {
371
                        char tt[128];
372
                        ltp = trp->tp-1;
373
                        ntp = trp->tp+1;
374
                        if (ltp<trp->bp || ntp>=trp->lp) {
375
                                error(ERROR, "## occurs at border of replacement");
376
                                continue;
377
                        }
378
                        len = ltp->len + ntp->len;
379
                        strncpy((char*)tt, (char*)ltp->t, ltp->len);
380
                        strncpy((char*)tt+ltp->len, (char*)ntp->t, ntp->len);
381
                        tt[len] = '\0';
382
                        setsource("<##>", NULL, tt);
383
                        maketokenrow(3, &ntr);
384
                        gettokens(&ntr, 1);
385
                        unsetsource();
386
                        if (ntr.lp-ntr.bp!=2 || ntr.bp->type==UNCLASS)
387
                                error(WARNING, "Bad token %r produced by ##", &ntr);
388
                        ntr.lp = ntr.bp+1;
389
                        trp->tp = ltp;
390
                        makespace(&ntr);
391
                        insertrow(trp, (ntp-ltp)+1, &ntr);
392
                        dofree(ntr.bp);
393
                        trp->tp--;
394
                }
395
        }
396
}
397
 
398
/*
399
 * tp is a potential parameter name of macro mac;
400
 * look it up in mac's arglist, and if found, return the
401
 * corresponding index in the argname array.  Return -1 if not found.
402
 */
403
int
404
lookuparg(Nlist *mac, Token *tp)
405
{
406
        Token *ap;
407
 
408
        if (tp->type!=NAME || mac->ap==NULL)
409
                return -1;
410
        for (ap=mac->ap->bp; ap<mac->ap->lp; ap++) {
411
                if (ap->len==tp->len && strncmp((char*)ap->t,(char*)tp->t,ap->len)==0)
412
                        return ap - mac->ap->bp;
413
        }
414
        return -1;
415
}
416
 
417
/*
418
 * Return a quoted version of the tokenrow (from # arg)
419
 */
420
#define STRLEN  512
421
Tokenrow *
422
stringify(Tokenrow *vp)
423
{
424
        static Token t = { STRING };
425
        static Tokenrow tr = { &t, &t, &t+1, 1 };
426
        Token *tp;
427
        uchar s[STRLEN];
428
        uchar *sp = s, *cp;
429
        int i, instring;
430
 
431
        *sp++ = '"';
432
        for (tp = vp->bp; tp < vp->lp; tp++) {
433
                instring = tp->type==STRING || tp->type==CCON;
434
                if (sp+2*tp->len >= &s[STRLEN-10]) {
435
                        error(ERROR, "Stringified macro arg is too long");
436
                        break;
437
                }
438
                if (tp->wslen && (tp->flag&XPWS)==0)
439
                        *sp++ = ' ';
440
                for (i=0, cp=tp->t; i<tp->len; i++) {
441
                        if (instring && (*cp=='"' || *cp=='\\'))
442
                                *sp++ = '\\';
443
                        *sp++ = *cp++;
444
                }
445
        }
446
        *sp++ = '"';
447
        *sp = '\0';
448
        sp = s;
449
        t.len = strlen((char*)sp);
450
        t.t = newstring(sp, t.len, 0);
451
        return &tr;
452
}
453
 
454
/*
455
 * expand a builtin name
456
 */
457
void
458
builtin(Tokenrow *trp, int biname)
459
{
460
        char *op;
461
        Token *tp;
462
        Source *s;
463
 
464
        tp = trp->tp;
465
        trp->tp++;
466
        /* need to find the real source */
467
        s = cursource;
468
        while (s && s->fd==NULL)
469
                s = s->next;
470
        if (s==NULL)
471
                s = cursource;
472
        /* most are strings */
473
        tp->type = STRING;
474
        if (tp->wslen) {
475
                *outp++ = ' ';
476
                tp->wslen = 1;
477
        }
478
        op = outp;
479
        *op++ = '"';
480
        switch (biname) {
481
 
482
        case KLINENO:
483
                tp->type = NUMBER;
484
                op = outnum(op-1, s->line);
485
                break;
486
 
487
        case KFILE: {
488
                char *src = s->filename;
489
                while ((*op++ = *src++) != 0)
490
                        if (src[-1] == '\\')
491
                                *op++ = '\\';
492
                op--;
493
                break;
494
                }
495
 
496
        case KDATE:
497
                strncpy(op, curtime+4, 7);
498
                strncpy(op+7, curtime+20, 4);
499
                op += 11;
500
                break;
501
 
502
        case KTIME:
503
                strncpy(op, curtime+11, 8);
504
                op += 8;
505
                break;
506
 
507
        default:
508
                error(ERROR, "cpp botch: unknown internal macro");
509
                return;
510
        }
511
        if (tp->type==STRING)
512
                *op++ = '"';
513
        tp->t = (uchar*)outp;
514
        tp->len = op - outp;
515
        outp = op;
516
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.