Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

macro.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpp.h"

Include dependency graph for macro.c:

Include dependency graph

Go to the source code of this file.

Defines

#define STRLEN   512

Functions

void builtin (Tokenrow *trp, int biname)
void doadefine (Tokenrow *trp, int type)
void doconcat (Tokenrow *trp)
void dodefine (Tokenrow *trp)
void expand (Tokenrow *trp, Nlist *np)
void expandrow (Tokenrow *trp, char *flag)
int gatherargs (Tokenrow *trp, Tokenrow **atr, int *narg)
int lookuparg (Nlist *mac, Token *tp)
Tokenrowstringify (Tokenrow *vp)
void substargs (Nlist *np, Tokenrow *rtr, Tokenrow **atr)


Define Documentation

#define STRLEN   512
 

Definition at line 419 of file macro.c.

Referenced by stringify().


Function Documentation

void builtin Tokenrow trp,
int  biname
 

Definition at line 457 of file macro.c.

References curtime, ERROR, error(), source::fd, source::filename, KDATE, KFILE, KLINENO, KTIME, token::len, source::line, source::next, op, outnum(), outp, s, Source, src, strncpy(), token::t, Token, Tokenrow, tokenrow::tp, token::type, uchar, and token::wslen.

Referenced by expandrow(), and PC_AddBuiltinDefines().

00458 {
00459     char *op;
00460     Token *tp;
00461     Source *s;
00462 
00463     tp = trp->tp;
00464     trp->tp++;
00465     /* need to find the real source */
00466     s = cursource;
00467     while (s && s->fd==-1)
00468         s = s->next;
00469     if (s==NULL)
00470         s = cursource;
00471     /* most are strings */
00472     tp->type = STRING;
00473     if (tp->wslen) {
00474         *outp++ = ' ';
00475         tp->wslen = 1;
00476     }
00477     op = outp;
00478     *op++ = '"';
00479     switch (biname) {
00480 
00481     case KLINENO:
00482         tp->type = NUMBER;
00483         op = outnum(op-1, s->line);
00484         break;
00485 
00486     case KFILE: {
00487         char *src = s->filename;
00488         while ((*op++ = *src++) != 0)
00489             if (src[-1] == '\\')
00490                 *op++ = '\\';
00491         op--;
00492         break;
00493         }
00494 
00495     case KDATE:
00496         strncpy(op, curtime+4, 7);
00497         strncpy(op+7, curtime+20, 4);
00498         op += 11;
00499         break;
00500 
00501     case KTIME:
00502         strncpy(op, curtime+11, 8);
00503         op += 8;
00504         break;
00505 
00506     default:
00507         error(ERROR, "cpp botch: unknown internal macro");
00508         return;
00509     }
00510     if (tp->type==STRING)
00511         *op++ = '"';
00512     tp->t = (uchar*)outp;
00513     tp->len = op - outp;
00514     outp = op;
00515 }

Here is the call graph for this function:

void doadefine Tokenrow trp,
int  type
 

Definition at line 92 of file macro.c.

References tokenrow::bp, error(), FATAL, nlist::flag, lookup(), tokenrow::lp, Nlist, normtokenrow(), np, Token, Tokenrow, tokenrow::tp, token::type, type, uchar, and nlist::vp.

Referenced by setup().

00093 {
00094     Nlist *np;
00095     static Token onetoken[1] = {{ NUMBER, 0, 0, 0, 1, (uchar*)"1" }};
00096     static Tokenrow onetr = { onetoken, onetoken, onetoken+1, 1 };
00097 
00098     trp->tp = trp->bp;
00099     if (type=='U') {
00100         if (trp->lp-trp->tp != 2 || trp->tp->type!=NAME)
00101             goto syntax;
00102         if ((np = lookup(trp->tp, 0)) == NULL)
00103             return;
00104         np->flag &= ~ISDEFINED;
00105         return;
00106     }
00107     if (trp->tp >= trp->lp || trp->tp->type!=NAME)
00108         goto syntax;
00109     np = lookup(trp->tp, 1);
00110     np->flag |= ISDEFINED;
00111     trp->tp += 1;
00112     if (trp->tp >= trp->lp || trp->tp->type==END) {
00113         np->vp = &onetr;
00114         return;
00115     }
00116     if (trp->tp->type!=ASGN)
00117         goto syntax;
00118     trp->tp += 1;
00119     if ((trp->lp-1)->type == END)
00120         trp->lp -= 1;
00121     np->vp = normtokenrow(trp);
00122     return;
00123 syntax:
00124     error(FATAL, "Illegal -D or -U argument %r", trp);
00125 }

Here is the call graph for this function:

void doconcat Tokenrow trp  ) 
 

Definition at line 360 of file macro.c.

References tokenrow::bp, dofree(), ERROR, error(), gettokens(), insertrow(), token::len, tokenrow::lp, makespace(), maketokenrow(), setsource(), strncpy(), token::t, Token, Tokenrow, tokenrow::tp, token::type, unsetsource(), and WARNING.

Referenced by expand().

00361 {
00362     Token *ltp, *ntp;
00363     Tokenrow ntr;
00364     int len;
00365 
00366     for (trp->tp=trp->bp; trp->tp<trp->lp; trp->tp++) {
00367         if (trp->tp->type==DSHARP1)
00368             trp->tp->type = DSHARP;
00369         else if (trp->tp->type==DSHARP) {
00370             char tt[128];
00371             ltp = trp->tp-1;
00372             ntp = trp->tp+1;
00373             if (ltp<trp->bp || ntp>=trp->lp) {
00374                 error(ERROR, "## occurs at border of replacement");
00375                 continue;
00376             }
00377             len = ltp->len + ntp->len;
00378             strncpy((char*)tt, (char*)ltp->t, ltp->len);
00379             strncpy((char*)tt+ltp->len, (char*)ntp->t, ntp->len);
00380             tt[len] = '\0';
00381             setsource("<##>", -1, tt);
00382             maketokenrow(3, &ntr);
00383             gettokens(&ntr, 1);
00384             unsetsource();
00385             if (ntr.lp-ntr.bp!=2 || ntr.bp->type==UNCLASS)
00386                 error(WARNING, "Bad token %r produced by ##", &ntr);
00387             ntr.lp = ntr.bp+1;
00388             trp->tp = ltp;
00389             makespace(&ntr);
00390             insertrow(trp, (ntp-ltp)+1, &ntr);
00391             dofree(ntr.bp);
00392             trp->tp--;
00393         }
00394     }
00395 }

Here is the call graph for this function:

void dodefine Tokenrow trp  ) 
 

Definition at line 10 of file macro.c.

References nlist::ap, tokenrow::bp, comparetokens(), dofree(), err(), ERROR, error(), nlist::flag, growtokenrow(), token::len, lookup(), LP, tokenrow::lp, maketokenrow(), tokenrow::max, Nlist, normtokenrow(), np, strncmp(), token::t, Token, Tokenrow, tokenrow::tp, token::type, nlist::vp, and token::wslen.

Referenced by control().

00011 {
00012     Token *tp;
00013     Nlist *np;
00014     Tokenrow *def, *args;
00015 
00016     tp = trp->tp+1;
00017     if (tp>=trp->lp || tp->type!=NAME) {
00018         error(ERROR, "#defined token is not a name");
00019         return;
00020     }
00021     np = lookup(tp, 1);
00022     if (np->flag&ISUNCHANGE) {
00023         error(ERROR, "#defined token %t can't be redefined", tp);
00024         return;
00025     }
00026     /* collect arguments */
00027     tp += 1;
00028     args = NULL;
00029     if (tp<trp->lp && tp->type==LP && tp->wslen==0) {
00030         /* macro with args */
00031         int narg = 0;
00032         tp += 1;
00033         args = new(Tokenrow);
00034         maketokenrow(2, args);
00035         if (tp->type!=RP) {
00036             int err = 0;
00037             for (;;) {
00038                 Token *atp;
00039                 if (tp->type!=NAME) {
00040                     err++;
00041                     break;
00042                 }
00043                 if (narg>=args->max)
00044                     growtokenrow(args);
00045                 for (atp=args->bp; atp<args->lp; atp++)
00046                     if (atp->len==tp->len
00047                      && strncmp((char*)atp->t, (char*)tp->t, tp->len)==0)
00048                         error(ERROR, "Duplicate macro argument");
00049                 *args->lp++ = *tp;
00050                 narg++;
00051                 tp += 1;
00052                 if (tp->type==RP)
00053                     break;
00054                 if (tp->type!=COMMA) {
00055                     err++;
00056                     break;
00057                 }
00058                 tp += 1;
00059             }
00060             if (err) {
00061                 error(ERROR, "Syntax error in macro parameters");
00062                 return;
00063             }
00064         }
00065         tp += 1;
00066     }
00067     trp->tp = tp;
00068     if (((trp->lp)-1)->type==NL)
00069         trp->lp -= 1;
00070     def = normtokenrow(trp);
00071     if (np->flag&ISDEFINED) {
00072         if (comparetokens(def, np->vp)
00073          || (np->ap==NULL) != (args==NULL)
00074          || np->ap && comparetokens(args, np->ap))
00075             error(ERROR, "Macro redefinition of %t", trp->bp+2);
00076     }
00077     if (args) {
00078         Tokenrow *tap;
00079         tap = normtokenrow(args);
00080         dofree(args->bp);
00081         args = tap;
00082     }
00083     np->ap = args;
00084     np->vp = def;
00085     np->flag |= ISDEFINED;
00086 }

Here is the call graph for this function:

void expand Tokenrow trp,
Nlist np
 

Definition at line 178 of file macro.c.

References nlist::ap, tokenrow::bp, copytokenrow(), doconcat(), dofree(), ERROR, error(), gatherargs(), token::hideset, i, insertrow(), tokenrow::lp, NARG, newhideset(), Nlist, np, rowlen, substargs(), Token, Tokenrow, tokenrow::tp, token::type, unionhideset(), and nlist::vp.

Referenced by expandrow(), RemoveLinearMeshColumnsRows(), SubdivideMesh(), and SubdivideMeshQuads().

00179 {
00180     Tokenrow ntr;
00181     int ntokc, narg, i;
00182     Token *tp;
00183     Tokenrow *atr[NARG+1];
00184     int hs;
00185 
00186     copytokenrow(&ntr, np->vp);     /* copy macro value */
00187     if (np->ap==NULL)           /* parameterless */
00188         ntokc = 1;
00189     else {
00190         ntokc = gatherargs(trp, atr, &narg);
00191         if (narg<0) {           /* not actually a call (no '(') */
00192             trp->tp++;
00193             return;
00194         }
00195         if (narg != rowlen(np->ap)) {
00196             error(ERROR, "Disagreement in number of macro arguments");
00197             trp->tp->hideset = newhideset(trp->tp->hideset, np);
00198             trp->tp += ntokc;
00199             return;
00200         }
00201         substargs(np, &ntr, atr);   /* put args into replacement */
00202         for (i=0; i<narg; i++) {
00203             dofree(atr[i]->bp);
00204             dofree(atr[i]);
00205         }
00206     }
00207     doconcat(&ntr);             /* execute ## operators */
00208     hs = newhideset(trp->tp->hideset, np);
00209     for (tp=ntr.bp; tp<ntr.lp; tp++) {  /* distribute hidesets */
00210         if (tp->type==NAME) {
00211             if (tp->hideset==0)
00212                 tp->hideset = hs;
00213             else
00214                 tp->hideset = unionhideset(tp->hideset, hs);
00215         }
00216     }
00217     ntr.tp = ntr.bp;
00218     insertrow(trp, ntokc, &ntr);
00219     trp->tp -= rowlen(&ntr);
00220     dofree(ntr.bp);
00221     return;
00222 }   

Here is the call graph for this function:

void expandrow Tokenrow trp,
char *  flag
 

Definition at line 132 of file macro.c.

References builtin(), checkhideset(), ERROR, error(), expand(), nlist::flag, token::hideset, ISDEFINED, token::len, lookup(), LP, tokenrow::lp, NAME, Nlist, np, NULL, quicklook, setsource(), token::t, Token, Tokenrow, tokenrow::tp, token::type, unsetsource(), and nlist::val.

Referenced by control(), doinclude(), eval(), process(), and substargs().

00133 {
00134     Token *tp;
00135     Nlist *np;
00136 
00137     if (flag)
00138         setsource(flag, -1, "");
00139     for (tp = trp->tp; tp<trp->lp; ) {
00140         if (tp->type!=NAME
00141          || quicklook(tp->t[0], tp->len>1?tp->t[1]:0)==0
00142          || (np = lookup(tp, 0))==NULL
00143          || (np->flag&(ISDEFINED|ISMAC))==0
00144          || tp->hideset && checkhideset(tp->hideset, np)) {
00145             tp++;
00146             continue;
00147         }
00148         trp->tp = tp;
00149         if (np->val==KDEFINED) {
00150             tp->type = DEFINED;
00151             if ((tp+1)<trp->lp && (tp+1)->type==NAME)
00152                 (tp+1)->type = NAME1;
00153             else if ((tp+3)<trp->lp && (tp+1)->type==LP
00154              && (tp+2)->type==NAME && (tp+3)->type==RP)
00155                 (tp+2)->type = NAME1;
00156             else
00157                 error(ERROR, "Incorrect syntax for `defined'");
00158             tp++;
00159             continue;
00160         }
00161         if (np->flag&ISMAC)
00162             builtin(trp, np->val);
00163         else {
00164             expand(trp, np);
00165         }
00166         tp = trp->tp;
00167     }
00168     if (flag)
00169         unsetsource();
00170 }

Here is the call graph for this function:

int gatherargs Tokenrow trp,
Tokenrow **  atr,
int *  narg
 

Definition at line 230 of file macro.c.

References adjustrow(), tokenrow::bp, COMMA, ERROR, error(), FATAL, gettokens(), tokenrow::lp, makespace(), NARG, normtokenrow(), Token, Tokenrow, tokenrow::tp, and token::type.

Referenced by expand().

00231 {
00232     int parens = 1;
00233     int ntok = 0;
00234     Token *bp, *lp;
00235     Tokenrow ttr;
00236     int ntokp;
00237     int needspace;
00238 
00239     *narg = -1;         /* means that there is no macro call */
00240     /* look for the ( */
00241     for (;;) {
00242         trp->tp++;
00243         ntok++;
00244         if (trp->tp >= trp->lp) {
00245             gettokens(trp, 0);
00246             if ((trp->lp-1)->type==END) {
00247                 trp->lp -= 1;
00248                 trp->tp -= ntok;
00249                 return ntok;
00250             }
00251         }
00252         if (trp->tp->type==LP)
00253             break;
00254         if (trp->tp->type!=NL)
00255             return ntok;
00256     }
00257     *narg = 0;
00258     ntok++;
00259     ntokp = ntok;
00260     trp->tp++;
00261     /* search for the terminating ), possibly extending the row */
00262     needspace = 0;
00263     while (parens>0) {
00264         if (trp->tp >= trp->lp)
00265             gettokens(trp, 0);
00266         if (needspace) {
00267             needspace = 0;
00268             makespace(trp);
00269         }
00270         if (trp->tp->type==END) {
00271             trp->lp -= 1;
00272             trp->tp -= ntok;
00273             error(ERROR, "EOF in macro arglist");
00274             return ntok;
00275         }
00276         if (trp->tp->type==NL) {
00277             trp->tp += 1;
00278             adjustrow(trp, -1);
00279             trp->tp -= 1;
00280             makespace(trp);
00281             needspace = 1;
00282             continue;
00283         }
00284         if (trp->tp->type==LP)
00285             parens++;
00286         else if (trp->tp->type==RP)
00287             parens--;
00288         trp->tp++;
00289         ntok++;
00290     }
00291     trp->tp -= ntok;
00292     /* Now trp->tp won't move underneath us */
00293     lp = bp = trp->tp+ntokp;
00294     for (; parens>=0; lp++) {
00295         if (lp->type == LP) {
00296             parens++;
00297             continue;
00298         }
00299         if (lp->type==RP)
00300             parens--;
00301         if (lp->type==DSHARP)
00302             lp->type = DSHARP1; /* ## not special in arg */
00303         if (lp->type==COMMA && parens==0 || parens<0 && (lp-1)->type!=LP) {
00304             if (*narg>=NARG-1)
00305                 error(FATAL, "Sorry, too many macro arguments");
00306             ttr.bp = ttr.tp = bp;
00307             ttr.lp = lp;
00308             atr[(*narg)++] = normtokenrow(&ttr);
00309             bp = lp+1;
00310         }
00311     }
00312     return ntok;
00313 }

Here is the call graph for this function:

int lookuparg Nlist mac,
Token tp
 

Definition at line 403 of file macro.c.

References nlist::ap, tokenrow::bp, token::len, tokenrow::lp, NAME, Nlist, strncmp(), token::t, Token, and token::type.

Referenced by substargs().

00404 {
00405     Token *ap;
00406 
00407     if (tp->type!=NAME || mac->ap==NULL)
00408         return -1;
00409     for (ap=mac->ap->bp; ap<mac->ap->lp; ap++) {
00410         if (ap->len==tp->len && strncmp((char*)ap->t,(char*)tp->t,ap->len)==0)
00411             return ap - mac->ap->bp;
00412     }
00413     return -1;
00414 }

Here is the call graph for this function:

Tokenrow* stringify Tokenrow vp  ) 
 

Definition at line 421 of file macro.c.

References cp, ERROR, error(), token::flag, i, token::len, newstring(), s, STRING, strlen(), STRLEN, token::t, t, Token, Tokenrow, tr, token::type, uchar, vp, and token::wslen.

Referenced by substargs().

00422 {
00423     static Token t = { STRING };
00424     static Tokenrow tr = { &t, &t, &t+1, 1 };
00425     Token *tp;
00426     uchar s[STRLEN];
00427     uchar *sp = s, *cp;
00428     int i, instring;
00429 
00430     *sp++ = '"';
00431     for (tp = vp->bp; tp < vp->lp; tp++) {
00432         instring = tp->type==STRING || tp->type==CCON;
00433         if (sp+2*tp->len >= &s[STRLEN-10]) {
00434             error(ERROR, "Stringified macro arg is too long");
00435             break;
00436         }
00437         if (tp->wslen && (tp->flag&XPWS)==0)
00438             *sp++ = ' ';
00439         for (i=0, cp=tp->t; i<tp->len; i++) {   
00440             if (instring && (*cp=='"' || *cp=='\\'))
00441                 *sp++ = '\\';
00442             *sp++ = *cp++;
00443         }
00444     }
00445     *sp++ = '"';
00446     *sp = '\0';
00447     sp = s;
00448     t.len = strlen((char*)sp);
00449     t.t = newstring(sp, t.len, 0);
00450     return &tr;
00451 }

Here is the call graph for this function:

void substargs Nlist np,
Tokenrow rtr,
Tokenrow **  atr
 

Definition at line 320 of file macro.c.

References tokenrow::bp, copytokenrow(), dofree(), DSHARP, ERROR, error(), expandrow(), insertrow(), lookuparg(), tokenrow::lp, NAME, Nlist, np, stringify(), Token, Tokenrow, tokenrow::tp, and token::type.

Referenced by expand().

00321 {
00322     Tokenrow tatr;
00323     Token *tp;
00324     int ntok, argno;
00325 
00326     for (rtr->tp=rtr->bp; rtr->tp<rtr->lp; ) {
00327         if (rtr->tp->type==SHARP) { /* string operator */
00328             tp = rtr->tp;
00329             rtr->tp += 1;
00330             if ((argno = lookuparg(np, rtr->tp))<0) {
00331                 error(ERROR, "# not followed by macro parameter");
00332                 continue;
00333             }
00334             ntok = 1 + (rtr->tp - tp);
00335             rtr->tp = tp;
00336             insertrow(rtr, ntok, stringify(atr[argno]));
00337             continue;
00338         }
00339         if (rtr->tp->type==NAME
00340          && (argno = lookuparg(np, rtr->tp)) >= 0) {
00341             if ((rtr->tp+1)->type==DSHARP
00342              || rtr->tp!=rtr->bp && (rtr->tp-1)->type==DSHARP)
00343                 insertrow(rtr, 1, atr[argno]);
00344             else {
00345                 copytokenrow(&tatr, atr[argno]);
00346                 expandrow(&tatr, "<macro>");
00347                 insertrow(rtr, 1, &tatr);
00348                 dofree(tatr.bp);
00349             }
00350             continue;
00351         }
00352         rtr->tp++;
00353     }
00354 }

Here is the call graph for this function:


Generated on Thu Aug 25 15:47:51 2005 for Quake III Arena by  doxygen 1.3.9.1