1 #ifndef lint 2 static char sccsid[] = "@(#)cpp.c 1.16 05/22/87"; 3 #endif lint 4 5 #ifdef FLEXNAMES 6 #define NCPS 128 7 #else 8 #define NCPS 8 9 #endif 10 11 # include "sys/param.h" 12 # include "stdio.h" 13 # include "ctype.h" 14 /* C command 15 /* written by John F. Reiser 16 /* July/August 1978 17 */ 18 19 #define STATIC 20 21 #define FIRSTOPEN -2 22 #define STDIN 0 23 #define READ 0 24 #define WRITE 1 25 #define SALT '#' 26 #if !defined BUFSIZ || BUFSIZ < 8192 27 #undef BUFSIZ 28 #define BUFSIZ 8192 29 #endif 30 31 char *pbeg,*pbuf,*pend; 32 char *outp,*inp; 33 char *newp; 34 char cinit; 35 36 /* some code depends on whether characters are sign or zero extended */ 37 /* #if '\377' < 0 not used here, old cpp doesn't understand */ 38 #if pdp11 | vax | mc68000 | tahoe 39 #define COFF 128 40 #else 41 #define COFF 0 42 #endif 43 44 # if gcos 45 #define ALFSIZ 512 /* alphabet size */ 46 # else 47 #define ALFSIZ 256 /* alphabet size */ 48 # endif 49 char macbit[ALFSIZ+11]; 50 char toktyp[ALFSIZ]; 51 #define BLANK 1 52 #define IDENT 2 53 #define NUMBR 3 54 55 /* a superimposed code is used to reduce the number of calls to the 56 /* symbol table lookup routine. (if the kth character of an identifier 57 /* is 'a' and there are no macro names whose kth character is 'a' 58 /* then the identifier cannot be a macro name, hence there is no need 59 /* to look in the symbol table.) 'scw1' enables the test based on 60 /* single characters and their position in the identifier. 'scw2' 61 /* enables the test based on adjacent pairs of characters and their 62 /* position in the identifier. scw1 typically costs 1 indexed fetch, 63 /* an AND, and a jump per character of identifier, until the identifier 64 /* is known as a non-macro name or until the end of the identifier. 65 /* scw1 is inexpensive. scw2 typically costs 4 indexed fetches, 66 /* an add, an AND, and a jump per character of identifier, but it is also 67 /* slightly more effective at reducing symbol table searches. 68 /* scw2 usually costs too much because the symbol table search is 69 /* usually short; but if symbol table search should become expensive, 70 /* the code is here. 71 /* using both scw1 and scw2 is of dubious value. 72 */ 73 #define scw1 1 74 #define scw2 0 75 76 #if scw2 77 char t21[ALFSIZ],t22[ALFSIZ],t23[ALFSIZ+NCPS]; 78 #endif 79 80 #if scw1 81 #define b0 1 82 #define b1 2 83 #define b2 4 84 #define b3 8 85 #define b4 16 86 #define b5 32 87 #define b6 64 88 #define b7 128 89 #endif 90 91 #define IB 1 92 #define SB 2 93 #define NB 4 94 #define CB 8 95 #define QB 16 96 #define WB 32 97 char fastab[ALFSIZ]; 98 char slotab[ALFSIZ]; 99 char *ptrtab; 100 #define isslo (ptrtab==(slotab+COFF)) 101 #define isid(a) ((fastab+COFF)[a]&IB) 102 #define isspc(a) (ptrtab[a]&SB) 103 #define isnum(a) ((fastab+COFF)[a]&NB) 104 #define iscom(a) ((fastab+COFF)[a]&CB) 105 #define isquo(a) ((fastab+COFF)[a]&QB) 106 #define iswarn(a) ((fastab+COFF)[a]&WB) 107 108 #define eob(a) ((a)>=pend) 109 #define bob(a) (pbeg>=(a)) 110 111 # define cputc(a,b) if(!flslvl) putc(a,b) 112 113 char buffer[NCPS+BUFSIZ+BUFSIZ+NCPS]; 114 115 char *lastcopy; 116 117 char *malloc(), *realloc(); 118 119 # define DROP 0xFE /* special character not legal ASCII or EBCDIC */ 120 # define WARN DROP 121 # define SAME 0 122 # define MAXINC 10 123 # define MAXFRE 14 /* max buffers of macro pushback */ 124 # define MAXFRM 31 /* max number of formals/actuals to a macro */ 125 126 static char warnc = WARN; 127 128 int mactop,fretop; 129 char *instack[MAXFRE],*bufstack[MAXFRE],*endbuf[MAXFRE]; 130 131 int plvl; /* parenthesis level during scan for macro actuals */ 132 int maclin; /* line number of macro call requiring actuals */ 133 char *macfil; /* file name of macro call requiring actuals */ 134 char *macnam; /* name of macro requiring actuals */ 135 int maclvl; /* # calls since last decrease in nesting level */ 136 char *macforw; /* pointer which must be exceeded to decrease nesting level */ 137 int macdam; /* offset to macforw due to buffer shifting */ 138 139 #if tgp 140 int tgpscan; /* flag for dump(); */ 141 #endif 142 143 STATIC int inctop[MAXINC]; 144 STATIC char *fnames[MAXINC]; 145 STATIC char *dirnams[MAXINC]; /* actual directory of #include files */ 146 STATIC int fins[MAXINC]; 147 STATIC int lineno[MAXINC]; 148 149 STATIC char *dirs[10]; /* -I and <> directories */ 150 char *strdex(), *copy(), *subst(), *trmdir(); 151 struct symtab *stsym(); 152 STATIC int fin = FIRSTOPEN; 153 STATIC FILE *fout = stdout; 154 STATIC int nd = 1; 155 STATIC int pflag; /* don't put out lines "# 12 foo.c" */ 156 int passcom; /* don't delete comments */ 157 int incomment; /* True if parsing a comment */ 158 STATIC int rflag; /* allow macro recursion */ 159 STATIC int mflag; /* generate makefile dependencies */ 160 STATIC char *infile; /* name of .o file to build dependencies from */ 161 STATIC FILE *mout; /* file to place dependencies on */ 162 #define START 1 163 #define CONT 2 164 #define BACK 3 165 STATIC int ifno; 166 # define NPREDEF 20 167 STATIC char *prespc[NPREDEF]; 168 STATIC char **predef = prespc; 169 STATIC char *punspc[NPREDEF]; 170 STATIC char **prund = punspc; 171 STATIC int exfail; 172 struct symtab { 173 char *name; 174 char *value; 175 } *lastsym, *lookup(), *slookup(); 176 177 # if gcos 178 #include <setjmp.h> 179 static jmp_buf env; 180 # define main mainpp 181 # undef exit 182 # define exit(S) longjmp(env, 1) 183 # define open(S,D) fileno(fopen(S, "r")) 184 # define close(F) fclose(_f[F]) 185 extern FILE *_f[]; 186 # define symsiz 500 187 # else 188 # define symsiz 2000 /* std = 500, wnj aug 1979 */ 189 # endif 190 STATIC struct symtab stab[symsiz]; 191 192 STATIC struct symtab *defloc; 193 STATIC struct symtab *udfloc; 194 STATIC struct symtab *incloc; 195 STATIC struct symtab *ifloc; 196 STATIC struct symtab *elsloc; 197 STATIC struct symtab *eifloc; 198 STATIC struct symtab *ifdloc; 199 STATIC struct symtab *ifnloc; 200 STATIC struct symtab *ysysloc; 201 STATIC struct symtab *varloc; 202 STATIC struct symtab *lneloc; 203 STATIC struct symtab *ulnloc; 204 STATIC struct symtab *uflloc; 205 STATIC struct symtab *identloc; /* Sys 5r3 compatibility */ 206 STATIC int trulvl; 207 STATIC int flslvl; 208 209 sayline(where) 210 int where; 211 { 212 if (mflag && where==START) fprintf(mout, "%s: %s\n", infile, fnames[ifno]); 213 if (pflag==0) fprintf(fout,"# %d \"%s\"\n", lineno[ifno], fnames[ifno]); 214 } 215 216 /* data structure guide 217 /* 218 /* most of the scanning takes place in the buffer: 219 /* 220 /* (low address) (high address) 221 /* pbeg pbuf pend 222 /* | <-- BUFSIZ chars --> | <-- BUFSIZ chars --> | 223 /* _______________________________________________________________________ 224 /* |_______________________________________________________________________| 225 /* | | | 226 /* |<-- waiting -->| |<-- waiting --> 227 /* | to be |<-- current -->| to be 228 /* | written | token | scanned 229 /* | | | 230 /* outp inp p 231 /* 232 /* *outp first char not yet written to output file 233 /* *inp first char of current token 234 /* *p first char not yet scanned 235 /* 236 /* macro expansion: write from *outp to *inp (chars waiting to be written), 237 /* ignore from *inp to *p (chars of the macro call), place generated 238 /* characters in front of *p (in reverse order), update pointers, 239 /* resume scanning. 240 /* 241 /* symbol table pointers point to just beyond the end of macro definitions; 242 /* the first preceding character is the number of formal parameters. 243 /* the appearance of a formal in the body of a definition is marked by 244 /* 2 chars: the char WARN, and a char containing the parameter number. 245 /* the first char of a definition is preceded by a zero character. 246 /* 247 /* when macro expansion attempts to back up over the beginning of the 248 /* buffer, some characters preceding *pend are saved in a side buffer, 249 /* the address of the side buffer is put on 'instack', and the rest 250 /* of the main buffer is moved to the right. the end of the saved buffer 251 /* is kept in 'endbuf' since there may be nulls in the saved buffer. 252 /* 253 /* similar action is taken when an 'include' statement is processed, 254 /* except that the main buffer must be completely emptied. the array 255 /* element 'inctop[ifno]' records the last side buffer saved when 256 /* file 'ifno' was included. these buffers remain dormant while 257 /* the file is being read, and are reactivated at end-of-file. 258 /* 259 /* instack[0 : mactop] holds the addresses of all pending side buffers. 260 /* instack[inctop[ifno]+1 : mactop-1] holds the addresses of the side 261 /* buffers which are "live"; the side buffers instack[0 : inctop[ifno]] 262 /* are dormant, waiting for end-of-file on the current file. 263 /* 264 /* space for side buffers is obtained from 'malloc' and is never returned. 265 /* bufstack[0:fretop-1] holds addresses of side buffers which 266 /* are available for use. 267 */ 268 269 dump() { 270 /* write part of buffer which lies between outp and inp . 271 /* this should be a direct call to 'write', but the system slows to a crawl 272 /* if it has to do an unaligned copy. thus we buffer. this silly loop 273 /* is 15% of the total time, thus even the 'putc' macro is too slow. 274 */ 275 register char *p1,*p2; register FILE *f; 276 if ((p1=outp)==inp || flslvl!=0) return; 277 #if tgp 278 #define MAXOUT 80 279 if (!tgpscan) {/* scan again to insure <= MAXOUT chars between linefeeds */ 280 register char c,*pblank; char savc,stopc,brk; 281 tgpscan=1; brk=stopc=pblank=0; p2=inp; savc= *p2; *p2='\0'; 282 while (c= *p1++) { 283 if (c=='\\') c= *p1++; 284 if (stopc==c) stopc=0; 285 else if (c=='"' || c=='\'') stopc=c; 286 if (p1-outp>MAXOUT && pblank!=0) { 287 *pblank++='\n'; inp=pblank; dump(); brk=1; pblank=0; 288 } 289 if (c==' ' && stopc==0) pblank=p1-1; 290 } 291 if (brk) sayline(CONT); 292 *p2=savc; inp=p2; p1=outp; tgpscan=0; 293 } 294 #endif 295 f=fout; 296 # if gcos 297 /* filter out "$ program c" card if first line of input */ 298 /* gmatch is a simple pattern matcher in the GCOS Standard Library */ 299 { static int gmfirst = 0; 300 if (!gmfirst) { 301 ++gmfirst; 302 if (gmatch(p1, "^$*program[ \t]*c*")) 303 p1 = strdex(p1, '\n'); 304 } 305 } 306 # endif 307 while (p1<inp) putc(*p1++,f); 308 outp=p1; 309 } 310 311 char * 312 refill(p) register char *p; { 313 /* dump buffer. save chars from inp to p. read into buffer at pbuf, 314 /* contiguous with p. update pointers, return new p. 315 */ 316 register char *np,*op; register int ninbuf; 317 dump(); np=pbuf-(p-inp); op=inp; 318 if (bob(np+1)) {pperror("token too long"); np=pbeg; p=inp+BUFSIZ;} 319 macdam += np-inp; outp=inp=np; 320 while (op<p) *np++= *op++; 321 p=np; 322 for (;;) { 323 if (mactop>inctop[ifno]) {/* retrieve hunk of pushed-back macro text */ 324 op=instack[--mactop]; np=pbuf; 325 do {while (*np++= *op++);} while (op<endbuf[mactop]); pend=np-1; 326 /* make buffer space avail for 'include' processing */ 327 if (fretop<MAXFRE) bufstack[fretop++]=instack[mactop]; 328 return(p); 329 } else {/* get more text from file(s) */ 330 maclvl=0; 331 if (0<(ninbuf=read(fin,pbuf,BUFSIZ))) { 332 pend=pbuf+ninbuf; *pend='\0'; 333 return(p); 334 } 335 /* end of #include file */ 336 if (ifno==0) {/* end of input */ 337 if (plvl!=0) { 338 int n=plvl,tlin=lineno[ifno]; char *tfil=fnames[ifno]; 339 lineno[ifno]=maclin; fnames[ifno]=macfil; 340 pperror("%s: unterminated macro call",macnam); 341 lineno[ifno]=tlin; fnames[ifno]=tfil; 342 np=p; *np++='\n'; /* shut off unterminated quoted string */ 343 while (--n>=0) *np++=')'; /* supply missing parens */ 344 pend=np; *np='\0'; if (plvl<0) plvl=0; 345 return(p); 346 } 347 if (trulvl || flslvl) 348 if (incomment) 349 pperror("unterminated comment"); 350 else 351 pperror("missing endif"); 352 inp=p; dump(); exit(exfail); 353 } 354 close(fin); fin=fins[--ifno]; dirs[0]=dirnams[ifno]; sayline(BACK); 355 } 356 } 357 } 358 359 #define BEG 0 360 #define LF 1 361 362 char * 363 cotoken(p) register char *p; { 364 register int c,i; char quoc; 365 static int state = BEG; 366 367 if (state!=BEG) goto prevlf; 368 for (;;) { 369 again: 370 while (!isspc(*p++)); 371 switch (*(inp=p-1)) { 372 case 0: { 373 if (eob(--p)) {p=refill(p); goto again;} 374 else ++p; /* ignore null byte */ 375 } break; 376 case '|': case '&': for (;;) {/* sloscan only */ 377 if (*p++== *inp) break; 378 if (eob(--p)) p=refill(p); 379 else break; 380 } break; 381 case '=': case '!': for (;;) {/* sloscan only */ 382 if (*p++=='=') break; 383 if (eob(--p)) p=refill(p); 384 else break; 385 } break; 386 case '<': case '>': for (;;) {/* sloscan only */ 387 if (*p++=='=' || p[-2]==p[-1]) break; 388 if (eob(--p)) p=refill(p); 389 else break; 390 } break; 391 case '\\': for (;;) { 392 if (*p++=='\n') {++lineno[ifno]; break;} 393 if (eob(--p)) p=refill(p); 394 else {++p; break;} 395 } break; 396 case '/': for (;;) { 397 if (*p++=='*') {/* comment */ 398 incomment++; 399 if (!passcom) {inp=p-2; dump(); ++flslvl;} 400 for (;;) { 401 while (!iscom(*p++)); 402 if (p[-1]=='*') for (;;) { 403 if (*p++=='/') goto endcom; 404 if (eob(--p)) { 405 if (!passcom) {inp=p; p=refill(p);} 406 else if ((p-inp)>=BUFSIZ) {/* split long comment */ 407 inp=p; p=refill(p); /* last char written is '*' */ 408 cputc('/',fout); /* terminate first part */ 409 /* and fake start of 2nd */ 410 outp=inp=p-=3; *p++='/'; *p++='*'; *p++='*'; 411 } else p=refill(p); 412 } else break; 413 } else if (p[-1]=='\n') { 414 ++lineno[ifno]; if (!passcom) putc('\n',fout); 415 } else if (eob(--p)) { 416 if (!passcom) {inp=p; p=refill(p);} 417 else if ((p-inp)>=BUFSIZ) {/* split long comment */ 418 inp=p; p=refill(p); 419 cputc('*',fout); cputc('/',fout); 420 outp=inp=p-=2; *p++='/'; *p++='*'; 421 } else p=refill(p); 422 } else ++p; /* ignore null byte */ 423 } 424 endcom: 425 incomment--; 426 if (!passcom) {outp=inp=p; --flslvl; goto again;} 427 break; 428 } 429 if (eob(--p)) p=refill(p); 430 else break; 431 } break; 432 # if gcos 433 case '`': 434 # endif 435 case '"': case '\'': { 436 quoc=p[-1]; 437 for (;;) { 438 while (!isquo(*p++)); 439 if (p[-1]==quoc) break; 440 if (p[-1]=='\n') {--p; break;} /* bare \n terminates quotation */ 441 if (p[-1]=='\\') for (;;) { 442 if (*p++=='\n') {++lineno[ifno]; break;} /* escaped \n ignored */ 443 if (eob(--p)) p=refill(p); 444 else {++p; break;} 445 } else if (eob(--p)) p=refill(p); 446 else ++p; /* it was a different quote character */ 447 } 448 } break; 449 case '\n': { 450 ++lineno[ifno]; if (isslo) {state=LF; return(p);} 451 prevlf: 452 state=BEG; 453 for (;;) { 454 if (*p++=='#') return(p); 455 if (eob(inp= --p)) p=refill(p); 456 else goto again; 457 } 458 } break; 459 case '0': case '1': case '2': case '3': case '4': 460 case '5': case '6': case '7': case '8': case '9': 461 for (;;) { 462 while (isnum(*p++)); 463 if (eob(--p)) p=refill(p); 464 else break; 465 } break; 466 case 'A': case 'B': case 'C': case 'D': case 'E': 467 case 'F': case 'G': case 'H': case 'I': case 'J': 468 case 'K': case 'L': case 'M': case 'N': case 'O': 469 case 'P': case 'Q': case 'R': case 'S': case 'T': 470 case 'U': case 'V': case 'W': case 'X': case 'Y': 471 case 'Z': case '_': 472 case 'a': case 'b': case 'c': case 'd': case 'e': 473 case 'f': case 'g': case 'h': case 'i': case 'j': 474 case 'k': case 'l': case 'm': case 'n': case 'o': 475 case 'p': case 'q': case 'r': case 's': case 't': 476 case 'u': case 'v': case 'w': case 'x': case 'y': 477 case 'z': 478 #if scw1 479 #define tmac1(c,bit) if (!xmac1(c,bit,&)) goto nomac 480 #define xmac1(c,bit,op) ((macbit+COFF)[c] op (bit)) 481 #else 482 #define tmac1(c,bit) 483 #define xmac1(c,bit,op) 484 #endif 485 486 #if scw2 487 #define tmac2(c0,c1,cpos) if (!xmac2(c0,c1,cpos,&)) goto nomac 488 #define xmac2(c0,c1,cpos,op)\ 489 ((macbit+COFF)[(t21+COFF)[c0]+(t22+COFF)[c1]] op (t23+COFF+cpos)[c0]) 490 #else 491 #define tmac2(c0,c1,cpos) 492 #define xmac2(c0,c1,cpos,op) 493 #endif 494 495 if (flslvl) goto nomac; 496 for (;;) { 497 c= p[-1]; tmac1(c,b0); 498 i= *p++; if (!isid(i)) goto endid; tmac1(i,b1); tmac2(c,i,0); 499 c= *p++; if (!isid(c)) goto endid; tmac1(c,b2); tmac2(i,c,1); 500 i= *p++; if (!isid(i)) goto endid; tmac1(i,b3); tmac2(c,i,2); 501 c= *p++; if (!isid(c)) goto endid; tmac1(c,b4); tmac2(i,c,3); 502 i= *p++; if (!isid(i)) goto endid; tmac1(i,b5); tmac2(c,i,4); 503 c= *p++; if (!isid(c)) goto endid; tmac1(c,b6); tmac2(i,c,5); 504 i= *p++; if (!isid(i)) goto endid; tmac1(i,b7); tmac2(c,i,6); 505 tmac2(i,0,7); 506 while (isid(*p++)); 507 if (eob(--p)) {refill(p); p=inp+1; continue;} 508 goto lokid; 509 endid: 510 if (eob(--p)) {refill(p); p=inp+1; continue;} 511 tmac2(p[-1],0,-1+(p-inp)); 512 lokid: 513 slookup(inp,p,0); if (newp) {p=newp; goto again;} 514 else break; 515 nomac: 516 while (isid(*p++)); 517 if (eob(--p)) {p=refill(p); goto nomac;} 518 else break; 519 } break; 520 } /* end of switch */ 521 522 if (isslo) return(p); 523 } /* end of infinite loop */ 524 } 525 526 char * 527 skipbl(p) register char *p; {/* get next non-blank token */ 528 do {outp=inp=p; p=cotoken(p);} while ((toktyp+COFF)[*inp]==BLANK); 529 return(p); 530 } 531 532 char * 533 unfill(p) register char *p; { 534 /* take <= BUFSIZ chars from right end of buffer and put them on instack . 535 /* slide rest of buffer to the right, update pointers, return new p. 536 */ 537 register char *np,*op; register int d; 538 if (mactop>=MAXFRE) { 539 pperror("%s: too much pushback",macnam); 540 p=inp=pend; dump(); /* begin flushing pushback */ 541 while (mactop>inctop[ifno]) {p=refill(p); p=inp=pend; dump();} 542 } 543 if (fretop>0) np=bufstack[--fretop]; 544 else { 545 np=malloc(BUFSIZ+1); 546 if (np==NULL) {pperror("no space"); exit(exfail);} 547 np[BUFSIZ]='\0'; 548 } 549 instack[mactop]=np; op=pend-BUFSIZ; if (op<p) op=p; 550 for (;;) {while (*np++= *op++); if (eob(op)) break;} /* out with old */ 551 endbuf[mactop++]=np; /* mark end of saved text */ 552 np=pbuf+BUFSIZ; op=pend-BUFSIZ; pend=np; if (op<p) op=p; 553 while (outp<op) *--np= *--op; /* slide over new */ 554 if (bob(np)) pperror("token too long"); 555 d=np-outp; outp+=d; inp+=d; macdam+=d; return(p+d); 556 } 557 558 char * 559 doincl(p) register char *p; { 560 int filok,inctype; 561 register char *cp; char **dirp,*nfil; char filname[BUFSIZ]; 562 563 p=skipbl(p); cp=filname; 564 if (*inp++=='<') {/* special <> syntax */ 565 inctype=1; 566 ++flslvl; /* prevent macro expansion */ 567 for (;;) { 568 outp=inp=p; p=cotoken(p); 569 if (*inp=='\n') {--p; *cp='\0'; break;} 570 if (*inp=='>') { *cp='\0'; break;} 571 # ifdef gimpel 572 if (*inp=='.' && !intss()) *inp='#'; 573 # endif 574 while (inp<p) *cp++= *inp++; 575 } 576 --flslvl; /* reenable macro expansion */ 577 } else if (inp[-1]=='"') {/* regular "" syntax */ 578 inctype=0; 579 # ifdef gimpel 580 while (inp<p) {if (*inp=='.' && !intss()) *inp='#'; *cp++= *inp++;} 581 # else 582 while (inp<p) *cp++= *inp++; 583 # endif 584 if (*--cp=='"') *cp='\0'; 585 } else {pperror("bad include syntax",0); inctype=2;} 586 /* flush current file to \n , then write \n */ 587 ++flslvl; do {outp=inp=p; p=cotoken(p);} while (*inp!='\n'); --flslvl; 588 inp=p; dump(); if (inctype==2) return(p); 589 /* look for included file */ 590 if (ifno+1 >=MAXINC) { 591 pperror("Unreasonable include nesting",0); return(p); 592 } 593 if((nfil=malloc(BUFSIZ))==NULL) {pperror("no space"); exit(exfail);} 594 filok=0; 595 for (dirp=dirs+inctype; *dirp; ++dirp) { 596 if ( 597 # if gcos 598 strdex(filname, '/') 599 # else 600 filname[0]=='/' 601 # endif 602 || **dirp=='\0') strcpy(nfil,filname); 603 else { 604 strcpy(nfil,*dirp); 605 # if unix || gcos 606 strcat(nfil,"/"); 607 # endif 608 #ifdef ibm 609 #ifndef gimpel 610 strcat(nfil,"."); 611 #endif 612 #endif 613 strcat(nfil,filname); 614 } 615 if (0<(fins[ifno+1]=open(nfil,READ))) { 616 filok=1; fin=fins[++ifno]; break; 617 } 618 } 619 if(filok==0){pperror("Can't find include file %s",filname);free(nfil);} 620 else { 621 nfil=realloc(nfil,strlen(nfil)+1); 622 lineno[ifno]=1; fnames[ifno]=nfil; 623 dirnams[ifno]=dirs[0]=trmdir(copy(nfil)); 624 sayline(START); 625 /* save current contents of buffer */ 626 while (!eob(p)) p=unfill(p); 627 inctop[ifno]=mactop; 628 } 629 return(p); 630 } 631 632 equfrm(a,p1,p2) register char *a,*p1,*p2; { 633 register char c; int flag; 634 c= *p2; *p2='\0'; 635 flag=strcmp(a,p1); *p2=c; return(flag==SAME); 636 } 637 638 char * 639 dodef(p) char *p; {/* process '#define' */ 640 register char *pin,*psav,*cf; 641 char **pf,**qf; int b,c,params; struct symtab *np; 642 char *oldval; 643 char *space, *newspace; 644 char *formal[MAXFRM]; /* formal[n] is name of nth formal */ 645 char formtxt[BUFSIZ]; /* space for formal names */ 646 int opt_passcom=passcom; 647 648 passcom=0; /* don't put comments in macro expansions */ 649 650 ++flslvl; /* prevent macro expansion during 'define' */ 651 p=skipbl(p); pin=inp; 652 if ((toktyp+COFF)[*pin]!=IDENT) { 653 ppwarn("illegal macro name"); while (*inp!='\n') p=skipbl(p); 654 passcom=opt_passcom; return(p); 655 } 656 np=slookup(pin,p,1); 657 if (oldval=np->value) free(lastcopy); /* was previously defined */ 658 b=1; cf=pin; 659 while (cf<p) {/* update macbit */ 660 c= *cf++; xmac1(c,b,|=); b=(b+b)&0xFF; 661 if (cf!=p) xmac2(c,*cf,-1+(cf-pin),|=); 662 else xmac2(c,0,-1+(cf-pin),|=); 663 } 664 params=0; outp=inp=p; p=cotoken(p); pin=inp; 665 if (*pin=='(') {/* with parameters; identify the formals */ 666 cf=formtxt; pf=formal; 667 for (;;) { 668 p=skipbl(p); pin=inp; 669 if (*pin=='\n') { 670 --lineno[ifno]; --p; pperror("%s: missing )",np->name); break; 671 } 672 if (*pin==')') break; 673 if (*pin==',') continue; 674 if ((toktyp+COFF)[*pin]!=IDENT) { 675 c= *p; *p='\0'; pperror("bad formal: %s",pin); *p=c; 676 } else if (pf>= &formal[MAXFRM]) { 677 c= *p; *p='\0'; pperror("too many formals: %s",pin); *p=c; 678 } else { 679 *pf++=cf; while (pin<p) *cf++= *pin++; *cf++='\0'; ++params; 680 } 681 } 682 if (params==0) --params; /* #define foo() ... */ 683 } else if (*pin=='\n') {--lineno[ifno]; --p;} 684 /* remember beginning of macro body, so that we can 685 /* warn if a redefinition is different from old value. 686 */ 687 space=psav=malloc(BUFSIZ); 688 if (space==NULL) { 689 pperror("too much defining"); 690 passcom=opt_passcom; 691 return(p); 692 } 693 *psav++ = '\0'; 694 for (;;) {/* accumulate definition until linefeed */ 695 outp=inp=p; p=cotoken(p); pin=inp; 696 if (*pin=='\\' && pin[1]=='\n') {putc('\n',fout); continue;} /* ignore escaped lf */ 697 if (*pin=='\n') break; 698 if (params) {/* mark the appearance of formals in the definiton */ 699 if ((toktyp+COFF)[*pin]==IDENT) { 700 for (qf=pf; --qf>=formal; ) { 701 if (equfrm(*qf,pin,p)) { 702 *psav++=qf-formal+1; *psav++=WARN; pin=p; break; 703 } 704 } 705 } else if (*pin=='"' || *pin=='\'' 706 # if gcos 707 || *pin=='`' 708 # endif 709 ) {/* inside quotation marks, too */ 710 char quoc= *pin; 711 for (*psav++= *pin++; pin<p && *pin!=quoc; ) { 712 while (pin<p && !isid(*pin)) *psav++= *pin++; 713 cf=pin; while (cf<p && isid(*cf)) ++cf; 714 for (qf=pf; --qf>=formal; ) { 715 if (equfrm(*qf,pin,cf)) { 716 *psav++=qf-formal+1; *psav++=WARN; pin=cf; break; 717 } 718 } 719 while (pin<cf) *psav++= *pin++; 720 } 721 } 722 } 723 while (pin<p) *psav++= *pin++; 724 } 725 *psav++=params; *psav++='\0'; 726 if ((cf=oldval)!=NULL) {/* redefinition */ 727 --cf; /* skip no. of params, which may be zero */ 728 while (*--cf); /* go back to the beginning */ 729 if (0!=strcmp(++cf,space+1)) {/* redefinition different from old */ 730 --lineno[ifno]; ppwarn("%s redefined",np->name); ++lineno[ifno]; 731 np->value=psav-1; 732 } else free(space); /* identical redef.; reclaim space */ 733 } else np->value=psav-1; 734 --flslvl; inp=pin; 735 if (np->value == psav-1) { 736 newspace = realloc(space, psav-space); 737 if (newspace==NULL) {pperror("no space"); exit(exfail);} 738 /* 739 * Adjust pointer in case this moved. 740 */ 741 np->value += newspace-space; 742 } 743 passcom=opt_passcom; 744 return(p); 745 } 746 747 #define fasscan() ptrtab=fastab+COFF 748 #define sloscan() ptrtab=slotab+COFF 749 750 char * 751 control(p) register char *p; {/* find and handle preprocessor control lines */ 752 register struct symtab *np; 753 for (;;) { 754 fasscan(); p=cotoken(p); if (*inp=='\n') ++inp; dump(); 755 sloscan(); p=skipbl(p); 756 *--inp=SALT; outp=inp; ++flslvl; np=slookup(inp,p,0); --flslvl; 757 if (np==defloc) {/* define */ 758 if (flslvl==0) {p=dodef(p); continue;} 759 } else if (np==incloc) {/* include */ 760 if (flslvl==0) {p=doincl(p); continue;} 761 } else if (np==ifnloc) {/* ifndef */ 762 ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl; 763 if (flslvl==0 && np->value==0) ++trulvl; 764 else ++flslvl; 765 } else if (np==ifdloc) {/* ifdef */ 766 ++flslvl; p=skipbl(p); np=slookup(inp,p,0); --flslvl; 767 if (flslvl==0 && np->value!=0) ++trulvl; 768 else ++flslvl; 769 } else if (np==eifloc) {/* endif */ 770 if (flslvl) {if (--flslvl==0) sayline(CONT);} 771 else if (trulvl) --trulvl; 772 else pperror("If-less endif",0); 773 } else if (np==elsloc) {/* else */ 774 if (flslvl) { 775 if (--flslvl!=0) ++flslvl; 776 else {++trulvl; sayline(CONT);} 777 } 778 else if (trulvl) {++flslvl; --trulvl;} 779 else pperror("If-less else",0); 780 } else if (np==udfloc) {/* undefine */ 781 if (flslvl==0) { 782 ++flslvl; p=skipbl(p); slookup(inp,p,DROP); --flslvl; 783 } 784 } else if (np==ifloc) {/* if */ 785 #if tgp 786 pperror(" IF not implemented, true assumed", 0); 787 if (flslvl==0) ++trulvl; else ++flslvl; 788 #else 789 newp=p; 790 if (flslvl==0 && yyparse()) ++trulvl; else ++flslvl; 791 p=newp; 792 #endif 793 } else if (np==lneloc) {/* line */ 794 if (flslvl==0 && pflag==0) { 795 char *savestring(); 796 char filename[BUFSIZ], *cp = filename; 797 outp=inp=p; *--outp='#'; 798 /* Find the line number.. */ 799 do { 800 p = cotoken(p); 801 } while (!isnum(*inp) && *inp != '\n'); 802 if (isnum(*inp)) 803 lineno[ifno] = atoi(inp)-1; 804 /* Skip over the blank token */ 805 inp = p; 806 if (*inp != '\n') { 807 p = cotoken(p); inp = p; 808 } 809 /* Add a quote if missing.. */ 810 if (*inp != '\n') { 811 p = cotoken(p); 812 /* Add a quote if missing.. */ 813 if (*inp == '"') 814 inp++; 815 else { 816 dump(); 817 *--outp = '"'; 818 } 819 while (*inp != '\n') { 820 while (inp < p && *inp != '"' && 821 cp < filename+sizeof(filename)) 822 *cp++ = *inp++; 823 if (*inp == '"') 824 break; 825 inp = p; p = cotoken(p); 826 } 827 fnames[ifno] = savestring(filename, cp); 828 /* Add a quote if missing.. */ 829 if (*inp != '"') { 830 dump(); 831 *--outp = '"'; 832 } 833 } 834 while (*inp != '\n') 835 p = cotoken(p); 836 continue; 837 } 838 } else if (np==identloc) {/* ident (for Sys 5r3 compat) */ 839 while(*inp!='\n') p=cotoken(p); 840 } else if (*++inp=='\n') outp=inp; /* allows blank line after # */ 841 else pperror("undefined control",0); 842 /* flush to lf */ 843 ++flslvl; while (*inp!='\n') {outp=inp=p; p=cotoken(p);} --flslvl; 844 } 845 } 846 847 char * 848 savestring(start, finish) 849 register char *start, *finish; 850 { 851 char *retbuf; 852 register char *cp; 853 854 retbuf = (char *) calloc(finish - start + 1, sizeof (char)); 855 cp = retbuf; 856 while (start < finish) 857 *cp++ = *start++; 858 *cp = 0; 859 return(retbuf); 860 } 861 862 struct symtab * 863 stsym(s) register char *s; { 864 char buf[BUFSIZ]; register char *p; 865 866 /* make definition look exactly like end of #define line */ 867 /* copy to avoid running off end of world when param list is at end */ 868 p=buf; while (*p++= *s++); 869 p=buf; while (isid(*p++)); /* skip first identifier */ 870 if (*--p=='=') {*p++=' '; while (*p++);} 871 else {s=" 1"; while (*p++= *s++);} 872 pend=p; *--p='\n'; 873 sloscan(); dodef(buf); return(lastsym); 874 } 875 876 struct symtab * 877 ppsym(s) char *s; {/* kluge */ 878 register struct symtab *sp; 879 register char *name; 880 881 cinit=SALT; sp=stsym(s); name = malloc(strlen(sp->name)+1+1); 882 name[0] = '#'; strcpy(name+1, sp->name); sp->name = name; 883 cinit=0; return(sp); 884 } 885 886 /* VARARGS1 */ 887 pperror(s,x,y) char *s; { 888 if (fnames[ifno][0]) fprintf(stderr, 889 # if gcos 890 "*%c* \"%s\", line ", exfail >= 0 ? 'F' : 'W', 891 # else 892 "%s: ", 893 # endif 894 fnames[ifno]); 895 fprintf(stderr, "%d: ",lineno[ifno]); 896 fprintf(stderr, s, x, y); 897 fprintf(stderr,"\n"); 898 ++exfail; 899 } 900 901 yyerror(s,a,b) char *s; { 902 pperror(s,a,b); 903 } 904 905 ppwarn(s,x) char *s; { 906 int fail = exfail; 907 exfail = -1; 908 pperror(s,x); 909 exfail = fail; 910 } 911 912 struct symtab * 913 lookup(namep, enterf) 914 char *namep; 915 { 916 register char *np, *snp; 917 register int c, i; int around; 918 register struct symtab *sp; 919 920 /* namep had better not be too long (currently, <=NCPS chars) */ 921 np=namep; around=0; i=cinit; 922 while (c= *np++) i += i+c; c=i; /* c=i for register usage on pdp11 */ 923 c %= symsiz; if (c<0) c += symsiz; 924 sp = &stab[c]; 925 while (snp=sp->name) { 926 np = namep; 927 while (*snp++ == *np) if (*np++ == '\0') { 928 if (enterf==DROP) {sp->name[0]= DROP; sp->value=0;} 929 return(lastsym=sp); 930 } 931 if (--sp < &stab[0]) 932 if (around) {pperror("too many defines", 0); exit(exfail);} 933 else {++around; sp = &stab[symsiz-1];} 934 } 935 if (enterf==1) sp->name=namep; 936 return(lastsym=sp); 937 } 938 939 struct symtab * 940 slookup(p1,p2,enterf) register char *p1,*p2; int enterf;{ 941 register char *p3; char c2,c3; struct symtab *np; 942 c2= *p2; *p2='\0'; /* mark end of token */ 943 if ((p2-p1)>NCPS) p3=p1+NCPS; else p3=p2; 944 c3= *p3; *p3='\0'; /* truncate to NCPS chars or less */ 945 if (enterf==1) p1=copy(p1); 946 np=lookup(p1,enterf); *p3=c3; *p2=c2; 947 if (np->value!=0 && flslvl==0) newp=subst(p2,np); 948 else newp=0; 949 return(np); 950 } 951 952 char * 953 subst(p,sp) register char *p; struct symtab *sp; { 954 static char match[]="%s: argument mismatch"; 955 register char *ca,*vp; int params; 956 char *actual[MAXFRM]; /* actual[n] is text of nth actual */ 957 char actused[MAXFRM]; /* for newline processing in actuals */ 958 char acttxt[BUFSIZ]; /* space for actuals */ 959 int nlines = 0; 960 961 if (0==(vp=sp->value)) return(p); 962 if ((p-macforw)<=macdam) { 963 if (++maclvl>symsiz && !rflag) { 964 pperror("%s: macro recursion",sp->name); return(p); 965 } 966 } else maclvl=0; /* level decreased */ 967 macforw=p; macdam=0; /* new target for decrease in level */ 968 macnam=sp->name; 969 dump(); 970 if (sp==ulnloc) { 971 vp=acttxt; *vp++='\0'; 972 sprintf(vp,"%d",lineno[ifno]); while (*vp++); 973 } else if (sp==uflloc) { 974 vp=acttxt; *vp++='\0'; 975 sprintf(vp,"\"%s\"",fnames[ifno]); while (*vp++); 976 } 977 if (0!=(params= *--vp&0xFF)) {/* definition calls for params */ 978 register char **pa; 979 ca=acttxt; pa=actual; 980 if (params==0xFF) params=1; /* #define foo() ... */ 981 sloscan(); ++flslvl; /* no expansion during search for actuals */ 982 plvl= -1; 983 do p=skipbl(p); while (*inp=='\n'); /* skip \n too */ 984 if (*inp=='(') { 985 maclin=lineno[ifno]; macfil=fnames[ifno]; 986 for (plvl=1; plvl!=0; ) { 987 *ca++='\0'; 988 for (;;) { 989 outp=inp=p; p=cotoken(p); 990 if (*inp=='(') ++plvl; 991 if (*inp==')' && --plvl==0) {--params; break;} 992 if (plvl==1 && *inp==',') {--params; break;} 993 while (inp<p) *ca++= *inp++; 994 if (ca> &acttxt[BUFSIZ]) 995 pperror("%s: actuals too long",sp->name); 996 } 997 if (pa>= &actual[MAXFRM]) ppwarn(match,sp->name); 998 else { actused[pa-actual]=0; *pa++=ca; } 999 } 1000 nlines = lineno[ifno] - maclin; 1001 lineno[ifno] = maclin; /* don't count newlines here */ 1002 } 1003 if (params!=0) ppwarn(match,sp->name); 1004 while (--params>=0) *pa++=""+1; /* null string for missing actuals */ 1005 --flslvl; fasscan(); 1006 } 1007 for (;;) {/* push definition onto front of input stack */ 1008 while (!iswarn(*--vp)) { 1009 if (bob(p)) {outp=inp=p; p=unfill(p);} 1010 *--p= *vp; 1011 } 1012 if (*vp==warnc) {/* insert actual param */ 1013 ca=actual[*--vp-1]; 1014 while (*--ca) { 1015 if (bob(p)) {outp=inp=p; p=unfill(p);} 1016 /* Actuals with newlines confuse line numbering */ 1017 if (*ca == '\n' && actused[*vp-1]) 1018 if (*(ca-1) == '\\') ca--; 1019 else *--p = ' '; 1020 else { *--p= *ca; if (*ca == '\n') nlines--; } 1021 } 1022 actused[*vp-1] = 1; 1023 } else { 1024 if (nlines > 0 ) 1025 while (nlines-- > 0) 1026 *--p = '\n'; 1027 break; 1028 } 1029 } 1030 outp=inp=p; 1031 return(p); 1032 } 1033 1034 1035 1036 1037 char * 1038 trmdir(s) register char *s; { 1039 register char *p = s; 1040 while (*p++); --p; while (p>s && *--p!='/'); 1041 # if unix 1042 if (p==s) *p++='.'; 1043 # endif 1044 *p='\0'; 1045 return(s); 1046 } 1047 1048 STATIC char * 1049 copy(s) register char *s; { 1050 register char *old; 1051 1052 old = malloc(strlen(s)+1); 1053 if (old==NULL) {pperror("no space"); exit(exfail);} 1054 strcpy(old, s); 1055 return(lastcopy=old); 1056 } 1057 1058 char * 1059 strdex(s,c) char *s,c; { 1060 while (*s) if (*s++==c) return(--s); 1061 return(0); 1062 } 1063 1064 yywrap(){ return(1); } 1065 1066 main(argc,argv) 1067 char *argv[]; 1068 { 1069 register int i,c; 1070 register char *p; 1071 char *tf,**cp2; 1072 1073 # if gcos 1074 if (setjmp(env)) return (exfail); 1075 # endif 1076 p="_$ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 1077 i=0; 1078 while (c= *p++) { 1079 (fastab+COFF)[c] |= IB|NB|SB; (toktyp+COFF)[c]=IDENT; 1080 #if scw2 1081 /* 53 == 63-10; digits rarely appear in identifiers, 1082 /* and can never be the first char of an identifier. 1083 /* 11 == 53*53/sizeof(macbit) . 1084 */ 1085 ++i; (t21+COFF)[c]=(53*i)/11; (t22+COFF)[c]=i%11; 1086 #endif 1087 } 1088 p="0123456789."; 1089 while (c= *p++) {(fastab+COFF)[c] |= NB|SB; (toktyp+COFF)[c]=NUMBR;} 1090 # if gcos 1091 p="\n\"'`/\\"; 1092 # else 1093 p="\n\"'/\\"; 1094 # endif 1095 while (c= *p++) (fastab+COFF)[c] |= SB; 1096 # if gcos 1097 p="\n\"'`\\"; 1098 # else 1099 p="\n\"'\\"; 1100 # endif 1101 while (c= *p++) (fastab+COFF)[c] |= QB; 1102 p="*\n"; while (c= *p++) (fastab+COFF)[c] |= CB; 1103 (fastab+COFF)[warnc] |= WB; 1104 (fastab+COFF)['\0'] |= CB|QB|SB|WB; 1105 for (i=ALFSIZ; --i>=0; ) slotab[i]=fastab[i]|SB; 1106 p=" \t\013\f\r"; /* note no \n; \v not legal for vertical tab? */ 1107 while (c= *p++) (toktyp+COFF)[c]=BLANK; 1108 #if scw2 1109 for ((t23+COFF)[i=ALFSIZ+7-COFF]=1; --i>=-COFF; ) 1110 if (((t23+COFF)[i]=(t23+COFF+1)[i]<<1)==0) (t23+COFF)[i]=1; 1111 #endif 1112 1113 # if unix 1114 fnames[ifno=0] = ""; dirnams[0]=dirs[0]="."; 1115 # endif 1116 # if ibm 1117 fnames[ifno=0] = ""; 1118 # endif 1119 # if gcos 1120 if (inquire(stdin, _TTY)) freopen("*src", "rt", stdin); 1121 # endif 1122 # if gimpel || gcos 1123 fnames[ifno=0] = (char *)inquire(stdin, _FILENAME); 1124 dirnams[0] = dirs[0] = trmdir(copy(fnames[0])); 1125 # endif 1126 for(i=1; i<argc; i++) 1127 { 1128 switch(argv[i][0]) 1129 { 1130 case '-': 1131 # if gcos 1132 switch(toupper(argv[i][1])) { /* case-independent on GCOS */ 1133 # else 1134 switch(argv[i][1]) { 1135 # endif 1136 case 'M': mflag++; 1137 case 'P': pflag++; 1138 case 'E': continue; 1139 case 'R': ++rflag; continue; 1140 case 'C': passcom++; continue; 1141 case 'D': 1142 if (predef>prespc+NPREDEF) { 1143 pperror("too many -D options, ignoring %s",argv[i]); 1144 continue; 1145 } 1146 /* ignore plain "-D" (no argument) */ 1147 if (*(argv[i]+2)) *predef++ = argv[i]+2; 1148 continue; 1149 case 'U': 1150 if (prund>punspc+NPREDEF) { 1151 pperror("too many -U options, ignoring %s",argv[i]); 1152 continue; 1153 } 1154 *prund++ = argv[i]+2; 1155 continue; 1156 case 'I': 1157 if (nd>8) pperror("excessive -I file (%s) ignored",argv[i]); 1158 else dirs[nd++] = argv[i]+2; 1159 continue; 1160 case '\0': continue; 1161 default: 1162 pperror("unknown flag %s", argv[i]); 1163 continue; 1164 } 1165 default: 1166 if (fin==FIRSTOPEN) { 1167 if (0>(fin=open(argv[i], READ))) { 1168 pperror("No source file %s",argv[i]); exit(8); 1169 } 1170 fnames[ifno]=copy(argv[i]); 1171 infile=copy(argv[i]); 1172 dirs[0]=dirnams[ifno]=trmdir(argv[i]); 1173 # ifndef gcos 1174 /* too dangerous to have file name in same syntactic position 1175 be input or output file depending on file redirections, 1176 so force output to stdout, willy-nilly 1177 [i don't see what the problem is. jfr] 1178 */ 1179 } else if (fout==stdout) { 1180 if (NULL==(fout=fopen(argv[i], "w"))) { 1181 pperror("Can't create %s", argv[i]); exit(8); 1182 } else fclose(stdout); 1183 # endif 1184 } else pperror("extraneous name %s", argv[i]); 1185 } 1186 } 1187 if (fin == FIRSTOPEN) 1188 fin = STDIN; 1189 1190 if (mflag) { 1191 if (infile==(char *)0) { 1192 fprintf(stderr, 1193 "no input file specified with -M flag\n"); 1194 exit(8); 1195 } 1196 tf=(char *)rindex(infile, '.'); 1197 if (tf==0) { 1198 fprintf(stderr, "missing component name on %s\n", 1199 infile); 1200 exit(8); 1201 } 1202 tf[1]='o'; 1203 tf=(char *)rindex(infile, '/'); 1204 if (tf!=(char *)0) 1205 infile = tf + 1; 1206 mout=fout; 1207 if (NULL==(fout=fopen("/dev/null", "w"))) { 1208 pperror("Can't open /dev/null"); 1209 exit(8); 1210 } 1211 } 1212 fins[ifno]=fin; 1213 exfail = 0; 1214 /* after user -I files here are the standard include libraries */ 1215 # if unix 1216 dirs[nd++] = "/usr/include"; 1217 # endif 1218 # if gcos 1219 dirs[nd++] = "cc/include"; 1220 # endif 1221 # if ibm 1222 # ifndef gimpel 1223 dirs[nd++] = "BTL$CLIB"; 1224 # endif 1225 # endif 1226 # ifdef gimpel 1227 dirs[nd++] = intss() ? "SYS3.C." : "" ; 1228 # endif 1229 /* dirs[nd++] = "/compool"; */ 1230 dirs[nd++] = 0; 1231 defloc=ppsym("define"); 1232 udfloc=ppsym("undef"); 1233 incloc=ppsym("include"); 1234 elsloc=ppsym("else"); 1235 eifloc=ppsym("endif"); 1236 ifdloc=ppsym("ifdef"); 1237 ifnloc=ppsym("ifndef"); 1238 ifloc=ppsym("if"); 1239 lneloc=ppsym("line"); 1240 identloc=ppsym("ident"); /* Sys 5r3 compatibility */ 1241 for (i=sizeof(macbit)/sizeof(macbit[0]); --i>=0; ) macbit[i]=0; 1242 # if unix 1243 ysysloc=stsym("unix"); 1244 # endif 1245 ysysloc=stsym(MACHINE); 1246 ulnloc=stsym ("__LINE__"); 1247 uflloc=stsym ("__FILE__"); 1248 1249 tf=fnames[ifno]; fnames[ifno]="command line"; lineno[ifno]=1; 1250 cp2=prespc; 1251 while (cp2<predef) stsym(*cp2++); 1252 cp2=punspc; 1253 while (cp2<prund) { 1254 if (p=strdex(*cp2, '=')) *p++='\0'; 1255 lookup(*cp2++, DROP); 1256 } 1257 fnames[ifno]=tf; 1258 pbeg=buffer+NCPS; pbuf=pbeg+BUFSIZ; pend=pbuf+BUFSIZ; 1259 1260 trulvl = 0; flslvl = 0; 1261 lineno[0] = 1; sayline(START); 1262 outp=inp=pend; 1263 control(pend); 1264 return (exfail); 1265 } 1266