1*7ce20373SAndrew Rist /************************************************************** 2*7ce20373SAndrew Rist * 3*7ce20373SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*7ce20373SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*7ce20373SAndrew Rist * distributed with this work for additional information 6*7ce20373SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*7ce20373SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*7ce20373SAndrew Rist * "License"); you may not use this file except in compliance 9*7ce20373SAndrew Rist * with the License. You may obtain a copy of the License at 10*7ce20373SAndrew Rist * 11*7ce20373SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*7ce20373SAndrew Rist * 13*7ce20373SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*7ce20373SAndrew Rist * software distributed under the License is distributed on an 15*7ce20373SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*7ce20373SAndrew Rist * KIND, either express or implied. See the License for the 17*7ce20373SAndrew Rist * specific language governing permissions and limitations 18*7ce20373SAndrew Rist * under the License. 19*7ce20373SAndrew Rist * 20*7ce20373SAndrew Rist *************************************************************/ 21*7ce20373SAndrew Rist 22cdf0e10cSrcweir #ifdef _MSC_VER 23cdf0e10cSrcweir # define _POSIX_ 24cdf0e10cSrcweir #endif 25cdf0e10cSrcweir #include <stdio.h> 26cdf0e10cSrcweir #include <stdlib.h> 27cdf0e10cSrcweir #include <string.h> 28cdf0e10cSrcweir #ifdef __hpux 29cdf0e10cSrcweir # define _HPUX_SOURCE 30cdf0e10cSrcweir #endif 31cdf0e10cSrcweir #if defined(__IBMC__) || defined(__EMX__) 32cdf0e10cSrcweir # define PATH_MAX _MAX_PATH 33cdf0e10cSrcweir #endif 34cdf0e10cSrcweir #include <limits.h> 35cdf0e10cSrcweir 36cdf0e10cSrcweir #include "cpp.h" 37cdf0e10cSrcweir 38cdf0e10cSrcweir #define NCONCAT 16384 39cdf0e10cSrcweir 40cdf0e10cSrcweir /* 41cdf0e10cSrcweir * do a macro definition. tp points to the name being defined in the line 42cdf0e10cSrcweir */ 43cdf0e10cSrcweir void dodefine(Tokenrow * trp)44cdf0e10cSrcweir dodefine(Tokenrow * trp) 45cdf0e10cSrcweir { 46cdf0e10cSrcweir Token *tp; 47cdf0e10cSrcweir Nlist *np; 48cdf0e10cSrcweir Source *s; 49cdf0e10cSrcweir Tokenrow *def, *args; 50cdf0e10cSrcweir static uchar location[(PATH_MAX + 8) * NINC], *cp; 51cdf0e10cSrcweir 52cdf0e10cSrcweir tp = trp->tp + 1; 53cdf0e10cSrcweir if (tp >= trp->lp || tp->type != NAME) 54cdf0e10cSrcweir { 55cdf0e10cSrcweir error(ERROR, "#defined token is not a name"); 56cdf0e10cSrcweir return; 57cdf0e10cSrcweir } 58cdf0e10cSrcweir np = lookup(tp, 1); 59cdf0e10cSrcweir if (np->flag & ISUNCHANGE) 60cdf0e10cSrcweir { 61cdf0e10cSrcweir error(ERROR, "#defined token %t can't be redefined", tp); 62cdf0e10cSrcweir return; 63cdf0e10cSrcweir } 64cdf0e10cSrcweir /* collect arguments */ 65cdf0e10cSrcweir tp += 1; 66cdf0e10cSrcweir args = NULL; 67cdf0e10cSrcweir if (tp < trp->lp && tp->type == LP && tp->wslen == 0) 68cdf0e10cSrcweir { 69cdf0e10cSrcweir /* macro with args */ 70cdf0e10cSrcweir int narg = 0; 71cdf0e10cSrcweir 72cdf0e10cSrcweir tp += 1; 73cdf0e10cSrcweir args = new(Tokenrow); 74cdf0e10cSrcweir maketokenrow(2, args); 75cdf0e10cSrcweir if (tp->type != RP) 76cdf0e10cSrcweir { 77cdf0e10cSrcweir int err = 0; 78cdf0e10cSrcweir 79cdf0e10cSrcweir for (;;) 80cdf0e10cSrcweir { 81cdf0e10cSrcweir Token *atp; 82cdf0e10cSrcweir 83cdf0e10cSrcweir if (tp->type != NAME) 84cdf0e10cSrcweir { 85cdf0e10cSrcweir err++; 86cdf0e10cSrcweir break; 87cdf0e10cSrcweir } 88cdf0e10cSrcweir if (narg >= args->max) 89cdf0e10cSrcweir growtokenrow(args); 90cdf0e10cSrcweir for (atp = args->bp; atp < args->lp; atp++) 91cdf0e10cSrcweir if (atp->len == tp->len 92cdf0e10cSrcweir && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0) 93cdf0e10cSrcweir error(ERROR, "Duplicate macro argument"); 94cdf0e10cSrcweir *args->lp++ = *tp; 95cdf0e10cSrcweir narg++; 96cdf0e10cSrcweir tp += 1; 97cdf0e10cSrcweir if (tp->type == RP) 98cdf0e10cSrcweir break; 99cdf0e10cSrcweir if (tp->type != COMMA) 100cdf0e10cSrcweir { 101cdf0e10cSrcweir err++; 102cdf0e10cSrcweir break; 103cdf0e10cSrcweir } 104cdf0e10cSrcweir tp += 1; 105cdf0e10cSrcweir } 106cdf0e10cSrcweir if (err) 107cdf0e10cSrcweir { 108cdf0e10cSrcweir error(ERROR, "Syntax error in macro parameters"); 109cdf0e10cSrcweir return; 110cdf0e10cSrcweir } 111cdf0e10cSrcweir } 112cdf0e10cSrcweir tp += 1; 113cdf0e10cSrcweir } 114cdf0e10cSrcweir trp->tp = tp; 115cdf0e10cSrcweir if (((trp->lp) - 1)->type == NL) 116cdf0e10cSrcweir trp->lp -= 1; 117cdf0e10cSrcweir def = normtokenrow(trp); 118cdf0e10cSrcweir if (np->flag & ISDEFINED) 119cdf0e10cSrcweir { 120cdf0e10cSrcweir if (comparetokens(def, np->vp) 121cdf0e10cSrcweir || (np->ap == NULL) != (args == NULL) 122cdf0e10cSrcweir || (np->ap && comparetokens(args, np->ap))) 123cdf0e10cSrcweir { 124cdf0e10cSrcweir if ( np->loc ) 125cdf0e10cSrcweir error(ERROR, 126cdf0e10cSrcweir "Macro redefinition of %t (already defined at %s)", 127cdf0e10cSrcweir trp->bp + 2, np->loc); 128cdf0e10cSrcweir else 129cdf0e10cSrcweir error(ERROR, 130cdf0e10cSrcweir "Macro redefinition of %t (already defined at %s)", 131cdf0e10cSrcweir trp->bp + 2, "commandline" ); 132cdf0e10cSrcweir } 133cdf0e10cSrcweir } 134cdf0e10cSrcweir if (args) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir Tokenrow *tap; 137cdf0e10cSrcweir 138cdf0e10cSrcweir tap = normtokenrow(args); 139cdf0e10cSrcweir dofree(args->bp); 140cdf0e10cSrcweir args = tap; 141cdf0e10cSrcweir } 142cdf0e10cSrcweir np->ap = args; 143cdf0e10cSrcweir np->vp = def; 144cdf0e10cSrcweir np->flag |= ISDEFINED; 145cdf0e10cSrcweir 146cdf0e10cSrcweir /* build location string of macro definition */ 147cdf0e10cSrcweir for (cp = location, s = cursource; s; s = s->next) 148cdf0e10cSrcweir if (*s->filename) 149cdf0e10cSrcweir { 150cdf0e10cSrcweir if (cp != location) 151cdf0e10cSrcweir *cp++ = ' '; 152cdf0e10cSrcweir sprintf((char *)cp, "%s:%d", s->filename, s->line); 153cdf0e10cSrcweir cp += strlen((char *)cp); 154cdf0e10cSrcweir } 155cdf0e10cSrcweir 156cdf0e10cSrcweir np->loc = newstring(location, strlen((char *)location), 0); 157cdf0e10cSrcweir 158cdf0e10cSrcweir if (Mflag) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir if (np->ap) 161cdf0e10cSrcweir error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp); 162cdf0e10cSrcweir else 163cdf0e10cSrcweir error(INFO, "Macro definition of %s [%r]", np->name, np->vp); 164cdf0e10cSrcweir } 165cdf0e10cSrcweir } 166cdf0e10cSrcweir 167cdf0e10cSrcweir /* 168cdf0e10cSrcweir * Definition received via -D or -U 169cdf0e10cSrcweir */ 170cdf0e10cSrcweir void doadefine(Tokenrow * trp,int type)171cdf0e10cSrcweir doadefine(Tokenrow * trp, int type) 172cdf0e10cSrcweir { 173cdf0e10cSrcweir Nlist *np; 174cdf0e10cSrcweir static uchar onestr[2] = "1"; 175cdf0e10cSrcweir static Token onetoken[1] = {{NUMBER, 0, 0, 1, onestr, 0}}; 176cdf0e10cSrcweir static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1}; 177cdf0e10cSrcweir 178cdf0e10cSrcweir trp->tp = trp->bp; 179cdf0e10cSrcweir if (type == 'U') 180cdf0e10cSrcweir { 181cdf0e10cSrcweir if (trp->lp - trp->tp != 2 || trp->tp->type != NAME) 182cdf0e10cSrcweir goto syntax; 183cdf0e10cSrcweir if ((np = lookup(trp->tp, 0)) == NULL) 184cdf0e10cSrcweir return; 185cdf0e10cSrcweir np->flag &= ~ISDEFINED; 186cdf0e10cSrcweir return; 187cdf0e10cSrcweir } 188cdf0e10cSrcweir 189cdf0e10cSrcweir if (type == 'A') 190cdf0e10cSrcweir { 191cdf0e10cSrcweir if (trp->tp >= trp->lp || trp->tp->type != NAME) 192cdf0e10cSrcweir goto syntax; 193cdf0e10cSrcweir trp->tp->type = ARCHITECTURE; 194cdf0e10cSrcweir np = lookup(trp->tp, 1); 195cdf0e10cSrcweir np->flag |= ISARCHITECTURE; 196cdf0e10cSrcweir trp->tp += 1; 197cdf0e10cSrcweir if (trp->tp >= trp->lp || trp->tp->type == END) 198cdf0e10cSrcweir { 199cdf0e10cSrcweir np->vp = &onetr; 200cdf0e10cSrcweir return; 201cdf0e10cSrcweir } 202cdf0e10cSrcweir else 203cdf0e10cSrcweir error(FATAL, "Illegal -A argument %r", trp); 204cdf0e10cSrcweir } 205cdf0e10cSrcweir 206cdf0e10cSrcweir if (trp->tp >= trp->lp || trp->tp->type != NAME) 207cdf0e10cSrcweir goto syntax; 208cdf0e10cSrcweir np = lookup(trp->tp, 1); 209cdf0e10cSrcweir np->flag |= ISDEFINED; 210cdf0e10cSrcweir trp->tp += 1; 211cdf0e10cSrcweir if (trp->tp >= trp->lp || trp->tp->type == END) 212cdf0e10cSrcweir { 213cdf0e10cSrcweir np->vp = &onetr; 214cdf0e10cSrcweir return; 215cdf0e10cSrcweir } 216cdf0e10cSrcweir if (trp->tp->type != ASGN) 217cdf0e10cSrcweir goto syntax; 218cdf0e10cSrcweir trp->tp += 1; 219cdf0e10cSrcweir if ((trp->lp - 1)->type == END) 220cdf0e10cSrcweir trp->lp -= 1; 221cdf0e10cSrcweir np->vp = normtokenrow(trp); 222cdf0e10cSrcweir return; 223cdf0e10cSrcweir syntax: 224cdf0e10cSrcweir error(FATAL, "Illegal -D or -U argument %r", trp); 225cdf0e10cSrcweir } 226cdf0e10cSrcweir 227cdf0e10cSrcweir 228cdf0e10cSrcweir 229cdf0e10cSrcweir /* 230cdf0e10cSrcweir * Do macro expansion in a row of tokens. 231cdf0e10cSrcweir * Flag is NULL if more input can be gathered. 232cdf0e10cSrcweir */ 233cdf0e10cSrcweir void expandrow(Tokenrow * trp,char * flag)234cdf0e10cSrcweir expandrow(Tokenrow * trp, char *flag) 235cdf0e10cSrcweir { 236cdf0e10cSrcweir Token * tp; 237cdf0e10cSrcweir Nlist * np; 238cdf0e10cSrcweir 239cdf0e10cSrcweir MacroValidatorList validators; 240cdf0e10cSrcweir mvl_init(&validators); 241cdf0e10cSrcweir /* Sets all token-identifiers to 0 because tokens may not be initialised (never use C!) */ 242cdf0e10cSrcweir tokenrow_zeroTokenIdentifiers(trp); 243cdf0e10cSrcweir 244cdf0e10cSrcweir if (flag) 245cdf0e10cSrcweir setsource(flag, -1, -1, "", 0); 246cdf0e10cSrcweir for (tp = trp->tp; tp < trp->lp;) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir mvl_check(&validators, tp); 249cdf0e10cSrcweir 250cdf0e10cSrcweir if (tp->type != NAME 251cdf0e10cSrcweir || quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0) == 0 252cdf0e10cSrcweir || (np = lookup(tp, 0)) == NULL 253cdf0e10cSrcweir || (np->flag & (ISDEFINED | ISMAC)) == 0 254cdf0e10cSrcweir || (np->flag & ISACTIVE) != 0) 255cdf0e10cSrcweir { 256cdf0e10cSrcweir tp++; 257cdf0e10cSrcweir continue; 258cdf0e10cSrcweir } 259cdf0e10cSrcweir trp->tp = tp; 260cdf0e10cSrcweir if (np->val == KDEFINED) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir tp->type = DEFINED; 263cdf0e10cSrcweir if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) 264cdf0e10cSrcweir (tp + 1)->type = NAME1; 265cdf0e10cSrcweir else 266cdf0e10cSrcweir if ((tp + 3) < trp->lp && (tp + 1)->type == LP 267cdf0e10cSrcweir && (tp + 2)->type == NAME && (tp + 3)->type == RP) 268cdf0e10cSrcweir (tp + 2)->type = NAME1; 269cdf0e10cSrcweir else 270cdf0e10cSrcweir error(ERROR, "Incorrect syntax for `defined'"); 271cdf0e10cSrcweir tp++; 272cdf0e10cSrcweir continue; 273cdf0e10cSrcweir } 274cdf0e10cSrcweir else 275cdf0e10cSrcweir if (np->val == KMACHINE) 276cdf0e10cSrcweir { 277cdf0e10cSrcweir if (((tp - 1) >= trp->bp) && ((tp - 1)->type == SHARP)) 278cdf0e10cSrcweir { 279cdf0e10cSrcweir tp->type = ARCHITECTURE; 280cdf0e10cSrcweir if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) 281cdf0e10cSrcweir (tp + 1)->type = NAME2; 282cdf0e10cSrcweir else 283cdf0e10cSrcweir if ((tp + 3) < trp->lp && (tp + 1)->type == LP 284cdf0e10cSrcweir && (tp + 2)->type == NAME && (tp + 3)->type == RP) 285cdf0e10cSrcweir (tp + 2)->type = NAME2; 286cdf0e10cSrcweir else 287cdf0e10cSrcweir error(ERROR, "Incorrect syntax for `#machine'"); 288cdf0e10cSrcweir } 289cdf0e10cSrcweir tp++; 290cdf0e10cSrcweir continue; 291cdf0e10cSrcweir } 292cdf0e10cSrcweir 293cdf0e10cSrcweir if (np->flag & ISMAC) 294cdf0e10cSrcweir builtin(trp, np->val); 295cdf0e10cSrcweir else 296cdf0e10cSrcweir expand(trp, np, &validators); 297cdf0e10cSrcweir tp = trp->tp; 298cdf0e10cSrcweir } // end for 299cdf0e10cSrcweir if (flag) 300cdf0e10cSrcweir unsetsource(); 301cdf0e10cSrcweir 302cdf0e10cSrcweir mvl_destruct(&validators); 303cdf0e10cSrcweir } 304cdf0e10cSrcweir 305cdf0e10cSrcweir /* 306cdf0e10cSrcweir * Expand the macro whose name is np, at token trp->tp, in the tokenrow. 307cdf0e10cSrcweir * Return trp->tp at the first token next to be expanded 308cdf0e10cSrcweir * (ordinarily the beginning of the expansion) 309cdf0e10cSrcweir * I.e.: the same position as before! 310cdf0e10cSrcweir * Only one expansion is performed, then we return to the expandrow() 311cdf0e10cSrcweir * loop and start at same position. 312cdf0e10cSrcweir */ 313cdf0e10cSrcweir void expand(Tokenrow * trp,Nlist * np,MacroValidatorList * pValidators)314cdf0e10cSrcweir expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators) 315cdf0e10cSrcweir { 316cdf0e10cSrcweir // Token * pOldNextTp; 317cdf0e10cSrcweir Tokenrow ntr; 318cdf0e10cSrcweir int ntokc, narg, i; 319cdf0e10cSrcweir Tokenrow *atr[NARG + 1]; 320cdf0e10cSrcweir 321cdf0e10cSrcweir if (Mflag == 2) 322cdf0e10cSrcweir { 323cdf0e10cSrcweir if (np->ap) 324cdf0e10cSrcweir error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap); 325cdf0e10cSrcweir else 326cdf0e10cSrcweir error(INFO, "Macro expansion of %t with %s", trp->tp, np->name); 327cdf0e10cSrcweir } 328cdf0e10cSrcweir 329cdf0e10cSrcweir copytokenrow(&ntr, np->vp); /* copy macro value */ 330cdf0e10cSrcweir if (np->ap == NULL) /* parameterless */ 331cdf0e10cSrcweir ntokc = 1; 332cdf0e10cSrcweir else 333cdf0e10cSrcweir { 334cdf0e10cSrcweir ntokc = gatherargs(trp, atr, &narg); 335cdf0e10cSrcweir if (narg < 0) 336cdf0e10cSrcweir { /* not actually a call (no '(') */ 337cdf0e10cSrcweir trp->tp++; 338cdf0e10cSrcweir return; 339cdf0e10cSrcweir } 340cdf0e10cSrcweir if (narg != rowlen(np->ap)) 341cdf0e10cSrcweir { 342cdf0e10cSrcweir error(ERROR, "Disagreement in number of macro arguments"); 343cdf0e10cSrcweir trp->tp += ntokc; 344cdf0e10cSrcweir return; 345cdf0e10cSrcweir } 346cdf0e10cSrcweir 347cdf0e10cSrcweir /** If gatherargs passed a macro validating token, this token 348cdf0e10cSrcweir must become valid here. 349cdf0e10cSrcweir trp->tp+0 was checked in expandrow(), so we dont need to do it 350cdf0e10cSrcweir again here: 351cdf0e10cSrcweir */ 352cdf0e10cSrcweir for (i = 1; i < ntokc; i++) 353cdf0e10cSrcweir { 354cdf0e10cSrcweir mvl_check(pValidators,trp->tp+i); 355cdf0e10cSrcweir } 356cdf0e10cSrcweir 357cdf0e10cSrcweir substargs(np, &ntr, atr); /* put args into replacement */ 358cdf0e10cSrcweir for (i = 0; i < narg; i++) 359cdf0e10cSrcweir { 360cdf0e10cSrcweir dofree(atr[i]->bp); 361cdf0e10cSrcweir dofree(atr[i]); 362cdf0e10cSrcweir } 363cdf0e10cSrcweir } 364cdf0e10cSrcweir 365cdf0e10cSrcweir /* old 366cdf0e10cSrcweir np->flag |= ISACTIVE; 367cdf0e10cSrcweir */ 368cdf0e10cSrcweir 369cdf0e10cSrcweir /* rh 370cdf0e10cSrcweir */ 371cdf0e10cSrcweir doconcat(&ntr); /* execute ## operators */ 372cdf0e10cSrcweir ntr.tp = ntr.bp; 373cdf0e10cSrcweir makespace(&ntr, trp->tp); 374cdf0e10cSrcweir 375cdf0e10cSrcweir /* old 376cdf0e10cSrcweir // expandrow(&ntr, "<expand>"); 377cdf0e10cSrcweir // insertrow(trp, ntokc, &ntr); 378cdf0e10cSrcweir // dofree(ntr.bp); 379cdf0e10cSrcweir // np->flag &= ~ISACTIVE; 380cdf0e10cSrcweir */ 381cdf0e10cSrcweir 382cdf0e10cSrcweir /* NP 383cdf0e10cSrcweir // Replace macro by its value: 384cdf0e10cSrcweir */ 385cdf0e10cSrcweir // pOldNextTp = trp->tp+ntokc; 386cdf0e10cSrcweir tokenrow_zeroTokenIdentifiers(&ntr); 387cdf0e10cSrcweir insertrow(trp, ntokc, &ntr); 388cdf0e10cSrcweir /* Reassign old macro validators: 389cdf0e10cSrcweir */ 390cdf0e10cSrcweir // mvl_move(pValidators, trp->tp - pOldNextTp); 391cdf0e10cSrcweir 392cdf0e10cSrcweir /* add validator for just invalidated macro: 393cdf0e10cSrcweir */ 394cdf0e10cSrcweir np->flag |= ISACTIVE; 395cdf0e10cSrcweir if (trp->tp != trp->lp) 396cdf0e10cSrcweir { /* tp is a valid pointer: */ 397cdf0e10cSrcweir mvl_add(pValidators,np,trp->tp); 398cdf0e10cSrcweir } 399cdf0e10cSrcweir else 400cdf0e10cSrcweir { /* tp is == lp, therefore does not point to valid memory: */ 401cdf0e10cSrcweir mvl_add(pValidators,np,0); 402cdf0e10cSrcweir } 403cdf0e10cSrcweir /* reset trp->tp to original position: 404cdf0e10cSrcweir */ 405cdf0e10cSrcweir trp->tp -= ntr.lp - ntr.bp; /* so the result will be tested for macros from the same position again */ 406cdf0e10cSrcweir 407cdf0e10cSrcweir dofree(ntr.bp); 408cdf0e10cSrcweir 409cdf0e10cSrcweir return; 410cdf0e10cSrcweir } 411cdf0e10cSrcweir 412cdf0e10cSrcweir /* 413cdf0e10cSrcweir * Gather an arglist, starting in trp with tp pointing at the macro name. 414cdf0e10cSrcweir * Return total number of tokens passed, stash number of args found. 415cdf0e10cSrcweir * trp->tp is not changed relative to the tokenrow. 416cdf0e10cSrcweir */ 417cdf0e10cSrcweir int gatherargs(Tokenrow * trp,Tokenrow ** atr,int * narg)418cdf0e10cSrcweir gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg) 419cdf0e10cSrcweir { 420cdf0e10cSrcweir int parens = 1; 421cdf0e10cSrcweir int ntok = 0; 422cdf0e10cSrcweir Token *bp, *lp; 423cdf0e10cSrcweir Tokenrow ttr; 424cdf0e10cSrcweir int ntokp; 425cdf0e10cSrcweir int needspace; 426cdf0e10cSrcweir 427cdf0e10cSrcweir *narg = -1; /* means that there is no macro 428cdf0e10cSrcweir * call */ 429cdf0e10cSrcweir /* look for the ( */ 430cdf0e10cSrcweir for (;;) 431cdf0e10cSrcweir { 432cdf0e10cSrcweir trp->tp++; 433cdf0e10cSrcweir ntok++; 434cdf0e10cSrcweir if (trp->tp >= trp->lp) 435cdf0e10cSrcweir { 436cdf0e10cSrcweir gettokens(trp, 0); 437cdf0e10cSrcweir if ((trp->lp - 1)->type == END) 438cdf0e10cSrcweir { 439cdf0e10cSrcweir trp->lp -= 1; 440cdf0e10cSrcweir trp->tp -= ntok; 441cdf0e10cSrcweir return ntok; 442cdf0e10cSrcweir } 443cdf0e10cSrcweir } 444cdf0e10cSrcweir if (trp->tp->type == LP) 445cdf0e10cSrcweir break; 446cdf0e10cSrcweir if (trp->tp->type != NL) 447cdf0e10cSrcweir return ntok; 448cdf0e10cSrcweir } 449cdf0e10cSrcweir *narg = 0; 450cdf0e10cSrcweir ntok++; 451cdf0e10cSrcweir ntokp = ntok; 452cdf0e10cSrcweir trp->tp++; 453cdf0e10cSrcweir /* search for the terminating ), possibly extending the row */ 454cdf0e10cSrcweir needspace = 0; 455cdf0e10cSrcweir while (parens > 0) 456cdf0e10cSrcweir { 457cdf0e10cSrcweir if (trp->tp >= trp->lp) 458cdf0e10cSrcweir gettokens(trp, 0); 459cdf0e10cSrcweir if (needspace) 460cdf0e10cSrcweir { 461cdf0e10cSrcweir needspace = 0; 462cdf0e10cSrcweir /* makespace(trp); [rh] */ 463cdf0e10cSrcweir } 464cdf0e10cSrcweir if (trp->tp->type == END) 465cdf0e10cSrcweir { 466cdf0e10cSrcweir trp->lp -= 1; 467cdf0e10cSrcweir trp->tp -= ntok; 468cdf0e10cSrcweir error(ERROR, "EOF in macro arglist"); 469cdf0e10cSrcweir return ntok; 470cdf0e10cSrcweir } 471cdf0e10cSrcweir if (trp->tp->type == NL) 472cdf0e10cSrcweir { 473cdf0e10cSrcweir trp->tp += 1; 474cdf0e10cSrcweir adjustrow(trp, -1); 475cdf0e10cSrcweir trp->tp -= 1; 476cdf0e10cSrcweir /* makespace(trp); [rh] */ 477cdf0e10cSrcweir needspace = 1; 478cdf0e10cSrcweir continue; 479cdf0e10cSrcweir } 480cdf0e10cSrcweir if (trp->tp->type == LP) 481cdf0e10cSrcweir parens++; 482cdf0e10cSrcweir else 483cdf0e10cSrcweir if (trp->tp->type == RP) 484cdf0e10cSrcweir parens--; 485cdf0e10cSrcweir trp->tp++; 486cdf0e10cSrcweir ntok++; 487cdf0e10cSrcweir } 488cdf0e10cSrcweir trp->tp -= ntok; 489cdf0e10cSrcweir /* Now trp->tp won't move underneath us */ 490cdf0e10cSrcweir lp = bp = trp->tp + ntokp; 491cdf0e10cSrcweir for (; parens >= 0; lp++) 492cdf0e10cSrcweir { 493cdf0e10cSrcweir if (lp->type == LP) 494cdf0e10cSrcweir { 495cdf0e10cSrcweir parens++; 496cdf0e10cSrcweir continue; 497cdf0e10cSrcweir } 498cdf0e10cSrcweir if (lp->type == RP) 499cdf0e10cSrcweir parens--; 500cdf0e10cSrcweir if (lp->type == DSHARP) 501cdf0e10cSrcweir lp->type = DSHARP1; /* ## not special in arg */ 502cdf0e10cSrcweir if ((lp->type == COMMA && parens == 0) || 503cdf0e10cSrcweir ( parens < 0 && ((lp - 1)->type != LP))) 504cdf0e10cSrcweir { 505cdf0e10cSrcweir if (*narg >= NARG - 1) 506cdf0e10cSrcweir error(FATAL, "Sorry, too many macro arguments"); 507cdf0e10cSrcweir ttr.bp = ttr.tp = bp; 508cdf0e10cSrcweir ttr.lp = lp; 509cdf0e10cSrcweir atr[(*narg)++] = normtokenrow(&ttr); 510cdf0e10cSrcweir bp = lp + 1; 511cdf0e10cSrcweir } 512cdf0e10cSrcweir } 513cdf0e10cSrcweir return ntok; 514cdf0e10cSrcweir } 515cdf0e10cSrcweir 516cdf0e10cSrcweir /* 517cdf0e10cSrcweir * substitute the argument list into the replacement string 518cdf0e10cSrcweir * This would be simple except for ## and # 519cdf0e10cSrcweir */ 520cdf0e10cSrcweir void substargs(Nlist * np,Tokenrow * rtr,Tokenrow ** atr)521cdf0e10cSrcweir substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr) 522cdf0e10cSrcweir { 523cdf0e10cSrcweir Tokenrow tatr; 524cdf0e10cSrcweir Token *tp; 525cdf0e10cSrcweir int ntok, argno; 526cdf0e10cSrcweir 527cdf0e10cSrcweir for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;) 528cdf0e10cSrcweir { 529cdf0e10cSrcweir if (rtr->tp->type == SHARP) 530cdf0e10cSrcweir { /* string operator */ 531cdf0e10cSrcweir tp = rtr->tp; 532cdf0e10cSrcweir rtr->tp += 1; 533cdf0e10cSrcweir if ((argno = lookuparg(np, rtr->tp)) < 0) 534cdf0e10cSrcweir { 535cdf0e10cSrcweir error(ERROR, "# not followed by macro parameter"); 536cdf0e10cSrcweir continue; 537cdf0e10cSrcweir } 538cdf0e10cSrcweir ntok = 1 + (rtr->tp - tp); 539cdf0e10cSrcweir rtr->tp = tp; 540cdf0e10cSrcweir insertrow(rtr, ntok, stringify(atr[argno])); 541cdf0e10cSrcweir continue; 542cdf0e10cSrcweir } 543cdf0e10cSrcweir if (rtr->tp->type == NAME 544cdf0e10cSrcweir && (argno = lookuparg(np, rtr->tp)) >= 0) 545cdf0e10cSrcweir { 546cdf0e10cSrcweir if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP) 547cdf0e10cSrcweir || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) 548cdf0e10cSrcweir { 549cdf0e10cSrcweir copytokenrow(&tatr, atr[argno]); 550cdf0e10cSrcweir makespace(&tatr, rtr->tp); 551cdf0e10cSrcweir insertrow(rtr, 1, &tatr); 552cdf0e10cSrcweir dofree(tatr.bp); 553cdf0e10cSrcweir } 554cdf0e10cSrcweir else 555cdf0e10cSrcweir { 556cdf0e10cSrcweir copytokenrow(&tatr, atr[argno]); 557cdf0e10cSrcweir makespace(&tatr, rtr->tp); 558cdf0e10cSrcweir expandrow(&tatr, "<macro>"); 559cdf0e10cSrcweir insertrow(rtr, 1, &tatr); 560cdf0e10cSrcweir dofree(tatr.bp); 561cdf0e10cSrcweir } 562cdf0e10cSrcweir continue; 563cdf0e10cSrcweir } 564cdf0e10cSrcweir rtr->tp++; 565cdf0e10cSrcweir } 566cdf0e10cSrcweir } 567cdf0e10cSrcweir 568cdf0e10cSrcweir /* 569cdf0e10cSrcweir * Evaluate the ## operators in a tokenrow 570cdf0e10cSrcweir */ 571cdf0e10cSrcweir void doconcat(Tokenrow * trp)572cdf0e10cSrcweir doconcat(Tokenrow * trp) 573cdf0e10cSrcweir { 574cdf0e10cSrcweir Token *ltp, *ntp; 575cdf0e10cSrcweir Tokenrow ntr; 576cdf0e10cSrcweir int len; 577cdf0e10cSrcweir 578cdf0e10cSrcweir for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++) 579cdf0e10cSrcweir { 580cdf0e10cSrcweir if (trp->tp->type == DSHARP1) 581cdf0e10cSrcweir trp->tp->type = DSHARP; 582cdf0e10cSrcweir else 583cdf0e10cSrcweir if (trp->tp->type == DSHARP) 584cdf0e10cSrcweir { 585cdf0e10cSrcweir int i; 586cdf0e10cSrcweir char tt[NCONCAT]; 587cdf0e10cSrcweir 588cdf0e10cSrcweir ltp = trp->tp - 1; 589cdf0e10cSrcweir ntp = trp->tp + 1; 590cdf0e10cSrcweir 591cdf0e10cSrcweir if (ltp < trp->bp || ntp >= trp->lp) 592cdf0e10cSrcweir { 593cdf0e10cSrcweir error(ERROR, "## occurs at border of replacement"); 594cdf0e10cSrcweir continue; 595cdf0e10cSrcweir } 596cdf0e10cSrcweir 597cdf0e10cSrcweir ntp = ltp; 598cdf0e10cSrcweir i = 1; 599cdf0e10cSrcweir len = 0; 600cdf0e10cSrcweir 601cdf0e10cSrcweir do 602cdf0e10cSrcweir { 603cdf0e10cSrcweir if (len + ntp->len + ntp->wslen > sizeof(tt)) 604cdf0e10cSrcweir { 605cdf0e10cSrcweir error(ERROR, "## string concatination buffer overrun"); 606cdf0e10cSrcweir break; 607cdf0e10cSrcweir } 608cdf0e10cSrcweir 609cdf0e10cSrcweir if (ntp != trp->tp + 1) 610cdf0e10cSrcweir { 611cdf0e10cSrcweir strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen, 612cdf0e10cSrcweir ntp->len + ntp->wslen); 613cdf0e10cSrcweir len += ntp->len + ntp->wslen; 614cdf0e10cSrcweir } 615cdf0e10cSrcweir else // Leerzeichen um ## herum entfernen: 616cdf0e10cSrcweir { 617cdf0e10cSrcweir strncpy((char *) tt + len, (char *) ntp->t, ntp->len); 618cdf0e10cSrcweir len += ntp->len; 619cdf0e10cSrcweir } 620cdf0e10cSrcweir 621cdf0e10cSrcweir ntp = trp->tp + i; 622cdf0e10cSrcweir i++; 623cdf0e10cSrcweir } 624cdf0e10cSrcweir while (ntp < trp->lp); 625cdf0e10cSrcweir 626cdf0e10cSrcweir tt[len] = '\0'; 627cdf0e10cSrcweir setsource("<##>", -1, -1, tt, 0); 628cdf0e10cSrcweir maketokenrow(3, &ntr); 629cdf0e10cSrcweir gettokens(&ntr, 1); 630cdf0e10cSrcweir unsetsource(); 631cdf0e10cSrcweir if (ntr.bp->type == UNCLASS) 632cdf0e10cSrcweir error(WARNING, "Bad token %r produced by ##", &ntr); 633cdf0e10cSrcweir while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp) 634cdf0e10cSrcweir ntr.lp--; 635cdf0e10cSrcweir 636cdf0e10cSrcweir doconcat(&ntr); 637cdf0e10cSrcweir trp->tp = ltp; 638cdf0e10cSrcweir makespace(&ntr, ltp); 639cdf0e10cSrcweir insertrow(trp, ntp - ltp, &ntr); 640cdf0e10cSrcweir dofree(ntr.bp); 641cdf0e10cSrcweir trp->tp--; 642cdf0e10cSrcweir } 643cdf0e10cSrcweir } 644cdf0e10cSrcweir } 645cdf0e10cSrcweir 646cdf0e10cSrcweir /* 647cdf0e10cSrcweir * tp is a potential parameter name of macro mac; 648cdf0e10cSrcweir * look it up in mac's arglist, and if found, return the 649cdf0e10cSrcweir * corresponding index in the argname array. Return -1 if not found. 650cdf0e10cSrcweir */ 651cdf0e10cSrcweir int lookuparg(Nlist * mac,Token * tp)652cdf0e10cSrcweir lookuparg(Nlist * mac, Token * tp) 653cdf0e10cSrcweir { 654cdf0e10cSrcweir Token *ap; 655cdf0e10cSrcweir 656cdf0e10cSrcweir if (tp->type != NAME || mac->ap == NULL) 657cdf0e10cSrcweir return -1; 658cdf0e10cSrcweir for (ap = mac->ap->bp; ap < mac->ap->lp; ap++) 659cdf0e10cSrcweir { 660cdf0e10cSrcweir if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0) 661cdf0e10cSrcweir return ap - mac->ap->bp; 662cdf0e10cSrcweir } 663cdf0e10cSrcweir return -1; 664cdf0e10cSrcweir } 665cdf0e10cSrcweir 666cdf0e10cSrcweir /* 667cdf0e10cSrcweir * Return a quoted version of the tokenrow (from # arg) 668cdf0e10cSrcweir */ 669cdf0e10cSrcweir #define STRLEN 512 670cdf0e10cSrcweir Tokenrow * stringify(Tokenrow * vp)671cdf0e10cSrcweir stringify(Tokenrow * vp) 672cdf0e10cSrcweir { 673cdf0e10cSrcweir static Token t = {STRING, 0, 0, 0, NULL, 0}; 674cdf0e10cSrcweir static Tokenrow tr = {&t, &t, &t + 1, 1}; 675cdf0e10cSrcweir Token *tp; 676cdf0e10cSrcweir uchar s[STRLEN]; 677cdf0e10cSrcweir uchar *sp = s, *cp; 678cdf0e10cSrcweir int i, instring; 679cdf0e10cSrcweir 680cdf0e10cSrcweir *sp++ = '"'; 681cdf0e10cSrcweir for (tp = vp->bp; tp < vp->lp; tp++) 682cdf0e10cSrcweir { 683cdf0e10cSrcweir instring = tp->type == STRING || tp->type == CCON; 684cdf0e10cSrcweir if (sp + 2 * tp->len + tp->wslen >= &s[STRLEN - 10]) 685cdf0e10cSrcweir { 686cdf0e10cSrcweir error(ERROR, "Stringified macro arg is too long"); 687cdf0e10cSrcweir break; 688cdf0e10cSrcweir } 689cdf0e10cSrcweir 690cdf0e10cSrcweir // Change by np 31.10.2001, #93725 - begin 691cdf0e10cSrcweir if ( tp->wslen > 0 ) 692cdf0e10cSrcweir *sp++ = ' '; 693cdf0e10cSrcweir // change end. 694cdf0e10cSrcweir 695cdf0e10cSrcweir for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++) 696cdf0e10cSrcweir { 697cdf0e10cSrcweir if (instring && (*cp == '"' || *cp == '\\')) 698cdf0e10cSrcweir *sp++ = '\\'; 699cdf0e10cSrcweir *sp++ = *cp++; 700cdf0e10cSrcweir } 701cdf0e10cSrcweir } 702cdf0e10cSrcweir *sp++ = '"'; 703cdf0e10cSrcweir *sp = '\0'; 704cdf0e10cSrcweir sp = s; 705cdf0e10cSrcweir t.len = strlen((char *) sp); 706cdf0e10cSrcweir t.t = newstring(sp, t.len, 0); 707cdf0e10cSrcweir return &tr; 708cdf0e10cSrcweir } 709cdf0e10cSrcweir 710cdf0e10cSrcweir /* 711cdf0e10cSrcweir * expand a builtin name 712cdf0e10cSrcweir */ 713cdf0e10cSrcweir void builtin(Tokenrow * trp,int biname)714cdf0e10cSrcweir builtin(Tokenrow * trp, int biname) 715cdf0e10cSrcweir { 716cdf0e10cSrcweir char *op; 717cdf0e10cSrcweir Token *tp; 718cdf0e10cSrcweir Source *s; 719cdf0e10cSrcweir 720cdf0e10cSrcweir tp = trp->tp; 721cdf0e10cSrcweir trp->tp++; 722cdf0e10cSrcweir /* need to find the real source */ 723cdf0e10cSrcweir s = cursource; 724cdf0e10cSrcweir while (s && s->fd == -1) 725cdf0e10cSrcweir s = s->next; 726cdf0e10cSrcweir if (s == NULL) 727cdf0e10cSrcweir s = cursource; 728cdf0e10cSrcweir /* most are strings */ 729cdf0e10cSrcweir tp->type = STRING; 730cdf0e10cSrcweir if (tp->wslen) 731cdf0e10cSrcweir { 732cdf0e10cSrcweir *outptr++ = ' '; 733cdf0e10cSrcweir tp->wslen = 1; 734cdf0e10cSrcweir } 735cdf0e10cSrcweir op = outptr; 736cdf0e10cSrcweir *op++ = '"'; 737cdf0e10cSrcweir switch (biname) 738cdf0e10cSrcweir { 739cdf0e10cSrcweir 740cdf0e10cSrcweir case KLINENO: 741cdf0e10cSrcweir tp->type = NUMBER; 742cdf0e10cSrcweir op = outnum(op - 1, s->line); 743cdf0e10cSrcweir break; 744cdf0e10cSrcweir 745cdf0e10cSrcweir case KFILE: 746cdf0e10cSrcweir { 747cdf0e10cSrcweir char *src = s->filename; 748cdf0e10cSrcweir 749cdf0e10cSrcweir while ((*op++ = *src++) != 0) 750cdf0e10cSrcweir if (src[-1] == '\\') 751cdf0e10cSrcweir *op++ = '\\'; 752cdf0e10cSrcweir op--; 753cdf0e10cSrcweir break; 754cdf0e10cSrcweir } 755cdf0e10cSrcweir 756cdf0e10cSrcweir case KDATE: 757cdf0e10cSrcweir strncpy(op, curtime + 4, 7); 758cdf0e10cSrcweir strncpy(op + 7, curtime + 20, 4); 759cdf0e10cSrcweir op += 11; 760cdf0e10cSrcweir break; 761cdf0e10cSrcweir 762cdf0e10cSrcweir case KTIME: 763cdf0e10cSrcweir strncpy(op, curtime + 11, 8); 764cdf0e10cSrcweir op += 8; 765cdf0e10cSrcweir break; 766cdf0e10cSrcweir 767cdf0e10cSrcweir default: 768cdf0e10cSrcweir error(ERROR, "cpp botch: unknown internal macro"); 769cdf0e10cSrcweir return; 770cdf0e10cSrcweir } 771cdf0e10cSrcweir if (tp->type == STRING) 772cdf0e10cSrcweir *op++ = '"'; 773cdf0e10cSrcweir tp->t = (uchar *) outptr; 774cdf0e10cSrcweir tp->len = op - outptr; 775cdf0e10cSrcweir outptr = op; 776cdf0e10cSrcweir } 777cdf0e10cSrcweir 778