1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1986-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* 22*4887Schin * Glenn Fowler 23*4887Schin * AT&T Research 24*4887Schin * 25*4887Schin * preprocessor stacked input stream support 26*4887Schin */ 27*4887Schin 28*4887Schin #include "pplib.h" 29*4887Schin 30*4887Schin 31*4887Schin /* 32*4887Schin * convert path to native representation 33*4887Schin */ 34*4887Schin 35*4887Schin #if 0 36*4887Schin #include "../../lib/libast/path/pathnative.c" /* drop in 2002 */ 37*4887Schin #else 38*4887Schin /* Modified by gisburn 2006-08-18 for OpenSolaris ksh93-integration */ 39*4887Schin #include "../../libast/common/path/pathnative.c" 40*4887Schin #endif 41*4887Schin 42*4887Schin static char* 43*4887Schin native(register const char* s) 44*4887Schin { 45*4887Schin register int c; 46*4887Schin register struct ppfile* xp; 47*4887Schin int m; 48*4887Schin int n; 49*4887Schin 50*4887Schin static Sfio_t* np; 51*4887Schin static Sfio_t* qp; 52*4887Schin 53*4887Schin if (!s) 54*4887Schin return 0; 55*4887Schin if (!np && !(np = sfstropen()) || !qp && !(qp = sfstropen())) 56*4887Schin return (char*)s; 57*4887Schin n = PATH_MAX; 58*4887Schin do 59*4887Schin { 60*4887Schin m = n; 61*4887Schin n = pathnative(s, sfstrrsrv(np, m), m); 62*4887Schin } while (n > m); 63*4887Schin sfstrseek(np, n, SEEK_CUR); 64*4887Schin s = (const char*)sfstruse(np); 65*4887Schin for (;;) 66*4887Schin { 67*4887Schin switch (c = *s++) 68*4887Schin { 69*4887Schin case 0: 70*4887Schin break; 71*4887Schin case '\\': 72*4887Schin case '"': 73*4887Schin sfputc(qp, '\\'); 74*4887Schin /*FALLTHROUGH*/ 75*4887Schin default: 76*4887Schin sfputc(qp, c); 77*4887Schin continue; 78*4887Schin } 79*4887Schin break; 80*4887Schin } 81*4887Schin if (!(xp = ppsetfile(sfstruse(qp)))) 82*4887Schin return (char*)s; 83*4887Schin return xp->name; 84*4887Schin } 85*4887Schin 86*4887Schin /* 87*4887Schin * push stream onto input stack 88*4887Schin * used by the PUSH_type macros 89*4887Schin */ 90*4887Schin 91*4887Schin void 92*4887Schin pppush(register int t, register char* s, register char* p, int n) 93*4887Schin { 94*4887Schin register struct ppinstk* cur; 95*4887Schin 96*4887Schin PUSH(t, cur); 97*4887Schin cur->line = error_info.line; 98*4887Schin cur->file = error_info.file; 99*4887Schin switch (t) 100*4887Schin { 101*4887Schin case IN_FILE: 102*4887Schin if (pp.option & NATIVE) 103*4887Schin s = native(s); 104*4887Schin cur->flags |= IN_newline; 105*4887Schin cur->fd = n; 106*4887Schin cur->hide = ++pp.hide; 107*4887Schin cur->symbol = 0; 108*4887Schin #if CHECKPOINT 109*4887Schin if ((pp.mode & (DUMP|INIT)) == DUMP) 110*4887Schin { 111*4887Schin cur->index = newof(0, struct ppindex, 1, 0); 112*4887Schin if (pp.lastindex) pp.lastindex->next = cur->index; 113*4887Schin else pp.firstindex = cur->index; 114*4887Schin pp.lastindex = cur->index; 115*4887Schin cur->index->file = pp.original; 116*4887Schin cur->index->begin = ppoffset(); 117*4887Schin } 118*4887Schin #endif 119*4887Schin n = 1; 120*4887Schin #if CHECKPOINT 121*4887Schin if (!(pp.mode & DUMP)) 122*4887Schin #endif 123*4887Schin if (!cur->prev->prev && !(pp.state & COMPILE) && isatty(0)) 124*4887Schin cur->flags |= IN_flush; 125*4887Schin #if ARCHIVE 126*4887Schin if (pp.member) 127*4887Schin { 128*4887Schin switch (pp.member->archive->type & (TYPE_BUFFER|TYPE_CHECKPOINT)) 129*4887Schin { 130*4887Schin case 0: 131*4887Schin #if CHECKPOINT 132*4887Schin cur->buflen = pp.member->size; 133*4887Schin #endif 134*4887Schin p = (cur->buffer = oldof(0, char, 0, pp.member->size + PPBAKSIZ + 1)) + PPBAKSIZ; 135*4887Schin if (sfseek(pp.member->archive->info.sp, pp.member->offset, SEEK_SET) != pp.member->offset) 136*4887Schin error(3, "%s: archive seek error", pp.member->archive->name); 137*4887Schin if (sfread(pp.member->archive->info.sp, p, pp.member->size) != pp.member->size) 138*4887Schin error(3, "%s: archive read error", pp.member->archive->name); 139*4887Schin pp.member = 0; 140*4887Schin break; 141*4887Schin case TYPE_BUFFER: 142*4887Schin #if CHECKPOINT 143*4887Schin case TYPE_CHECKPOINT|TYPE_BUFFER: 144*4887Schin cur->buflen = pp.member->size; 145*4887Schin #endif 146*4887Schin p = cur->buffer = pp.member->archive->info.buffer + pp.member->offset; 147*4887Schin cur->flags |= IN_static; 148*4887Schin pp.member = 0; 149*4887Schin break; 150*4887Schin #if CHECKPOINT 151*4887Schin case TYPE_CHECKPOINT: 152*4887Schin p = cur->buffer = ""; 153*4887Schin cur->flags |= IN_static; 154*4887Schin break; 155*4887Schin #endif 156*4887Schin } 157*4887Schin cur->flags |= IN_eof|IN_newline; 158*4887Schin cur->fd = -1; 159*4887Schin } 160*4887Schin else 161*4887Schin #endif 162*4887Schin { 163*4887Schin if (lseek(cur->fd, 0L, SEEK_END) > 0 && !lseek(cur->fd, 0L, SEEK_SET)) 164*4887Schin cur->flags |= IN_regular; 165*4887Schin errno = 0; 166*4887Schin #if PROTOTYPE 167*4887Schin if (!(pp.option & NOPROTO) && !(pp.test & TEST_noproto) && ((pp.state & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY || (pp.option & PLUSPLUS) || (pp.mode & EXTERNALIZE)) && (cur->buffer = pppopen(NiL, cur->fd, NiL, NiL, NiL, NiL, (PROTO_HEADER|PROTO_RETAIN)|(((pp.mode & EXTERNALIZE) || (pp.option & PROTOTYPED)) ? PROTO_FORCE : PROTO_PASS)|((pp.mode & EXTERNALIZE) ? PROTO_EXTERNALIZE : 0)|((pp.mode & MARKC) ? PROTO_PLUSPLUS : 0)))) 168*4887Schin { 169*4887Schin *(p = cur->buffer - 1) = 0; 170*4887Schin cur->buffer -= PPBAKSIZ; 171*4887Schin cur->flags |= IN_prototype; 172*4887Schin cur->fd = -1; 173*4887Schin } 174*4887Schin else 175*4887Schin #endif 176*4887Schin *(p = (cur->buffer = oldof(0, char, 0, PPBUFSIZ + PPBAKSIZ + 1)) + PPBAKSIZ) = 0; 177*4887Schin } 178*4887Schin if (pp.incref && !(pp.mode & INIT)) 179*4887Schin (*pp.incref)(error_info.file, s, error_info.line - 1, PP_SYNC_PUSH); 180*4887Schin if (pp.macref || (pp.option & IGNORELINE)) 181*4887Schin cur->flags |= IN_ignoreline; 182*4887Schin cur->prefix = pp.prefix; 183*4887Schin /*FALLTHROUGH*/ 184*4887Schin case IN_BUFFER: 185*4887Schin case IN_INIT: 186*4887Schin case IN_RESCAN: 187*4887Schin pushcontrol(); 188*4887Schin cur->control = pp.control; 189*4887Schin *pp.control = 0; 190*4887Schin cur->vendor = pp.vendor; 191*4887Schin if (cur->type != IN_RESCAN) 192*4887Schin { 193*4887Schin if (cur->type == IN_INIT) 194*4887Schin pp.mode |= MARKHOSTED; 195*4887Schin error_info.file = s; 196*4887Schin error_info.line = n; 197*4887Schin } 198*4887Schin if (pp.state & HIDDEN) 199*4887Schin { 200*4887Schin pp.state &= ~HIDDEN; 201*4887Schin pp.hidden = 0; 202*4887Schin if (!(pp.state & NOTEXT) && pplastout() != '\n') 203*4887Schin ppputchar('\n'); 204*4887Schin } 205*4887Schin pp.state |= NEWLINE; 206*4887Schin if (pp.mode & HOSTED) cur->flags |= IN_hosted; 207*4887Schin else cur->flags &= ~IN_hosted; 208*4887Schin if (pp.mode & (INIT|MARKHOSTED)) 209*4887Schin { 210*4887Schin pp.mode |= HOSTED; 211*4887Schin pp.flags |= PP_hosted; 212*4887Schin } 213*4887Schin switch (cur->type) 214*4887Schin { 215*4887Schin case IN_FILE: 216*4887Schin if (!(pp.mode & (INIT|MARKHOSTED))) 217*4887Schin { 218*4887Schin pp.mode &= ~HOSTED; 219*4887Schin pp.flags &= ~PP_hosted; 220*4887Schin } 221*4887Schin #if CATSTRINGS 222*4887Schin if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE; 223*4887Schin else 224*4887Schin #endif 225*4887Schin if (pp.linesync) 226*4887Schin (*pp.linesync)(error_info.line, error_info.file); 227*4887Schin #if ARCHIVE && CHECKPOINT 228*4887Schin if (pp.member) 229*4887Schin ppload(NiL); 230*4887Schin #endif 231*4887Schin if (pp.mode & MARKC) 232*4887Schin { 233*4887Schin cur->flags |= IN_c; 234*4887Schin pp.mode &= ~MARKC; 235*4887Schin if (!(cur->prev->flags & IN_c)) 236*4887Schin { 237*4887Schin debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp.in), pptokchr(*pp.in->nextchr), pp.in->nextchr)); 238*4887Schin PUSH_BUFFER("C", "extern \"C\" {\n", 1); 239*4887Schin return; 240*4887Schin } 241*4887Schin } 242*4887Schin else if (cur->prev->flags & IN_c) 243*4887Schin { 244*4887Schin debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp.in), pptokchr(*pp.in->nextchr), pp.in->nextchr)); 245*4887Schin PUSH_BUFFER("C", "extern \"C++\" {\n", 1); 246*4887Schin return; 247*4887Schin } 248*4887Schin break; 249*4887Schin case IN_BUFFER: 250*4887Schin cur->buffer = p = strdup(p); 251*4887Schin break; 252*4887Schin default: 253*4887Schin cur->buffer = p; 254*4887Schin break; 255*4887Schin } 256*4887Schin cur->nextchr = p; 257*4887Schin break; 258*4887Schin #if DEBUG 259*4887Schin default: 260*4887Schin error(PANIC, "use PUSH_<%d>(...) instead of pppush(IN_<%d>, ...)", cur->type, cur->type); 261*4887Schin break; 262*4887Schin #endif 263*4887Schin } 264*4887Schin debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); 265*4887Schin } 266*4887Schin 267*4887Schin /* 268*4887Schin * external buffer push 269*4887Schin */ 270*4887Schin 271*4887Schin void 272*4887Schin ppinput(char* b, char* f, int n) 273*4887Schin { 274*4887Schin PUSH_BUFFER(f, b, n); 275*4887Schin } 276*4887Schin 277*4887Schin /* 278*4887Schin * return expanded value of buffer p 279*4887Schin */ 280*4887Schin 281*4887Schin char* 282*4887Schin ppexpand(register char* p) 283*4887Schin { 284*4887Schin register char* m; 285*4887Schin register int n; 286*4887Schin register int c; 287*4887Schin long restore; 288*4887Schin char* pptoken; 289*4887Schin char* ppmactop; 290*4887Schin struct ppmacstk* nextmacp; 291*4887Schin struct ppinstk* cur; 292*4887Schin 293*4887Schin debug((-7, "before expand: %s", p)); 294*4887Schin if (ppmactop = pp.mactop) 295*4887Schin { 296*4887Schin nextmacp = pp.macp->next; 297*4887Schin nextframe(pp.macp, pp.mactop); 298*4887Schin } 299*4887Schin restore = pp.state & (COLLECTING|DISABLE|STRIP); 300*4887Schin pp.state &= ~restore; 301*4887Schin pp.mode &= ~MARKMACRO; 302*4887Schin PUSH_STRING(p); 303*4887Schin cur = pp.in; 304*4887Schin pp.in->flags |= IN_expand; 305*4887Schin pptoken = pp.token; 306*4887Schin n = 2 * MAXTOKEN; 307*4887Schin pp.token = p = oldof(0, char, 0, n); 308*4887Schin m = p + MAXTOKEN; 309*4887Schin for (;;) 310*4887Schin { 311*4887Schin if (pplex()) 312*4887Schin { 313*4887Schin if ((pp.token = pp.toknxt) > m) 314*4887Schin { 315*4887Schin c = pp.token - p; 316*4887Schin p = newof(p, char, n += MAXTOKEN, 0); 317*4887Schin m = p + n - MAXTOKEN; 318*4887Schin pp.token = p + c; 319*4887Schin } 320*4887Schin if (pp.mode & MARKMACRO) 321*4887Schin { 322*4887Schin pp.mode &= ~MARKMACRO; 323*4887Schin *pp.token++ = MARK; 324*4887Schin *pp.token++ = 'X'; 325*4887Schin } 326*4887Schin } 327*4887Schin else if (pp.in == cur) 328*4887Schin break; 329*4887Schin } 330*4887Schin *pp.token = 0; 331*4887Schin if (ppmactop) 332*4887Schin pp.macp->next = nextmacp; 333*4887Schin debug((-7, "after expand: %s", p)); 334*4887Schin pp.token = pptoken; 335*4887Schin pp.state |= restore; 336*4887Schin pp.in = pp.in->prev; 337*4887Schin return p; 338*4887Schin } 339*4887Schin 340*4887Schin #if CHECKPOINT 341*4887Schin 342*4887Schin #define LOAD_FUNCTION (1<<0) 343*4887Schin #define LOAD_MULTILINE (1<<1) 344*4887Schin #define LOAD_NOEXPAND (1<<2) 345*4887Schin #define LOAD_PREDICATE (1<<3) 346*4887Schin #define LOAD_READONLY (1<<4) 347*4887Schin #define LOAD_VARIADIC (1<<5) 348*4887Schin 349*4887Schin /* 350*4887Schin * macro definition dump 351*4887Schin */ 352*4887Schin 353*4887Schin static int 354*4887Schin dump(const char* name, char* v, void* handle) 355*4887Schin { 356*4887Schin register struct ppmacro* mac; 357*4887Schin register struct ppsymbol* sym = (struct ppsymbol*)v; 358*4887Schin register int flags; 359*4887Schin 360*4887Schin NoP(name); 361*4887Schin NoP(handle); 362*4887Schin if ((mac = sym->macro) && !(sym->flags & (SYM_BUILTIN|SYM_PREDEFINED))) 363*4887Schin { 364*4887Schin ppprintf("%s", sym->name); 365*4887Schin ppputchar(0); 366*4887Schin flags = 0; 367*4887Schin if (sym->flags & SYM_FUNCTION) flags |= LOAD_FUNCTION; 368*4887Schin if (sym->flags & SYM_MULTILINE) flags |= LOAD_MULTILINE; 369*4887Schin if (sym->flags & SYM_NOEXPAND) flags |= LOAD_NOEXPAND; 370*4887Schin if (sym->flags & SYM_PREDICATE) flags |= LOAD_PREDICATE; 371*4887Schin if (sym->flags & SYM_READONLY) flags |= LOAD_READONLY; 372*4887Schin if (sym->flags & SYM_VARIADIC) flags |= LOAD_VARIADIC; 373*4887Schin ppputchar(flags); 374*4887Schin if (sym->flags & SYM_FUNCTION) 375*4887Schin { 376*4887Schin ppprintf("%d", mac->arity); 377*4887Schin ppputchar(0); 378*4887Schin if (mac->arity) 379*4887Schin { 380*4887Schin ppprintf("%s", mac->formals); 381*4887Schin ppputchar(0); 382*4887Schin } 383*4887Schin } 384*4887Schin ppprintf("%s", mac->value); 385*4887Schin ppputchar(0); 386*4887Schin } 387*4887Schin return(0); 388*4887Schin } 389*4887Schin 390*4887Schin /* 391*4887Schin * dump macro definitions for quick loading via ppload() 392*4887Schin */ 393*4887Schin 394*4887Schin void 395*4887Schin ppdump(void) 396*4887Schin { 397*4887Schin register struct ppindex* ip; 398*4887Schin unsigned long macro_offset; 399*4887Schin unsigned long index_offset; 400*4887Schin 401*4887Schin /* 402*4887Schin * NOTE: we assume '\0' does not occur in valid preprocessed output 403*4887Schin */ 404*4887Schin 405*4887Schin ppputchar(0); 406*4887Schin 407*4887Schin /* 408*4887Schin * output global flags 409*4887Schin */ 410*4887Schin 411*4887Schin macro_offset = ppoffset(); 412*4887Schin ppputchar(0); 413*4887Schin 414*4887Schin /* 415*4887Schin * output macro definitions 416*4887Schin */ 417*4887Schin 418*4887Schin hashwalk(pp.symtab, 0, dump, NiL); 419*4887Schin ppputchar(0); 420*4887Schin 421*4887Schin /* 422*4887Schin * output include file index 423*4887Schin */ 424*4887Schin 425*4887Schin index_offset = ppoffset(); 426*4887Schin ip = pp.firstindex; 427*4887Schin while (ip) 428*4887Schin { 429*4887Schin ppprintf("%s", ip->file->name); 430*4887Schin ppputchar(0); 431*4887Schin if (ip->file->guard != INC_CLEAR && ip->file->guard != INC_IGNORE && ip->file->guard != INC_TEST) 432*4887Schin ppprintf("%s", ip->file->guard->name); 433*4887Schin ppputchar(0); 434*4887Schin ppprintf("%lu", ip->begin); 435*4887Schin ppputchar(0); 436*4887Schin ppprintf("%lu", ip->end); 437*4887Schin ppputchar(0); 438*4887Schin ip = ip->next; 439*4887Schin } 440*4887Schin ppputchar(0); 441*4887Schin 442*4887Schin /* 443*4887Schin * output offset directory 444*4887Schin */ 445*4887Schin 446*4887Schin ppprintf("%010lu", macro_offset); 447*4887Schin ppputchar(0); 448*4887Schin ppprintf("%010lu", index_offset); 449*4887Schin ppputchar(0); 450*4887Schin ppflushout(); 451*4887Schin } 452*4887Schin 453*4887Schin /* 454*4887Schin * load text and macro definitions from a previous ppdump() 455*4887Schin * s is the string argument from the pragma (including quotes) 456*4887Schin */ 457*4887Schin 458*4887Schin void 459*4887Schin ppload(register char* s) 460*4887Schin { 461*4887Schin register char* b; 462*4887Schin register Sfio_t* sp; 463*4887Schin int m; 464*4887Schin char* g; 465*4887Schin char* t; 466*4887Schin unsigned long n; 467*4887Schin unsigned long p; 468*4887Schin unsigned long macro_offset; 469*4887Schin unsigned long index_offset; 470*4887Schin unsigned long file_offset; 471*4887Schin unsigned long file_size; 472*4887Schin unsigned long keep_begin; 473*4887Schin unsigned long keep_end; 474*4887Schin unsigned long skip_end; 475*4887Schin unsigned long next_begin; 476*4887Schin unsigned long next_end; 477*4887Schin struct ppfile* fp; 478*4887Schin struct ppsymbol* sym; 479*4887Schin struct ppmacro* mac; 480*4887Schin 481*4887Schin char* ip = 0; 482*4887Schin 483*4887Schin pp.mode |= LOADING; 484*4887Schin if (!(pp.state & STANDALONE)) 485*4887Schin error(3, "checkpoint load in standalone mode only"); 486*4887Schin #if ARCHIVE 487*4887Schin if (pp.member) 488*4887Schin { 489*4887Schin sp = pp.member->archive->info.sp; 490*4887Schin file_offset = pp.member->offset; 491*4887Schin file_size = pp.member->size; 492*4887Schin if (sfseek(sp, file_offset + 22, SEEK_SET) != file_offset + 22 || !(s = sfgetr(sp, '\n', 1))) 493*4887Schin error(3, "checkpoint magic error"); 494*4887Schin } 495*4887Schin else 496*4887Schin #endif 497*4887Schin { 498*4887Schin if (pp.in->type != IN_FILE) 499*4887Schin error(3, "checkpoint load from files only"); 500*4887Schin if (pp.in->flags & IN_prototype) 501*4887Schin pp.in->fd = pppdrop(pp.in->buffer + PPBAKSIZ); 502*4887Schin file_offset = 0; 503*4887Schin if (pp.in->fd >= 0) 504*4887Schin { 505*4887Schin if (!(sp = sfnew(NiL, NiL, SF_UNBOUND, pp.in->fd, SF_READ))) 506*4887Schin error(3, "checkpoint read error"); 507*4887Schin file_size = sfseek(sp, 0L, SEEK_END); 508*4887Schin } 509*4887Schin else 510*4887Schin { 511*4887Schin file_size = pp.in->buflen; 512*4887Schin if (!(sp = sfnew(NiL, pp.in->buffer + ((pp.in->flags & IN_static) ? 0 : PPBAKSIZ), file_size, -1, SF_READ|SF_STRING))) 513*4887Schin error(3, "checkpoint read error"); 514*4887Schin } 515*4887Schin } 516*4887Schin if (!streq(s, pp.checkpoint)) 517*4887Schin error(3, "checkpoint version %s does not match %s", s, pp.checkpoint); 518*4887Schin 519*4887Schin /* 520*4887Schin * get the macro and index offsets 521*4887Schin */ 522*4887Schin 523*4887Schin p = file_offset + file_size - 22; 524*4887Schin if ((n = sfseek(sp, p, SEEK_SET)) != p) 525*4887Schin error(3, "checkpoint directory seek error"); 526*4887Schin if (!(t = sfreserve(sp, 22, 0))) 527*4887Schin error(3, "checkpoint directory read error"); 528*4887Schin macro_offset = file_offset + strtol(t, &t, 10); 529*4887Schin index_offset = file_offset + strtol(t + 1, NiL, 10); 530*4887Schin 531*4887Schin /* 532*4887Schin * read the include index 533*4887Schin */ 534*4887Schin 535*4887Schin if (sfseek(sp, index_offset, SEEK_SET) != index_offset) 536*4887Schin error(3, "checkpoint index seek error"); 537*4887Schin if (!(s = sfreserve(sp, n - index_offset, 0))) 538*4887Schin error(3, "checkpoint index read error"); 539*4887Schin if (sfset(sp, 0, 0) & SF_STRING) 540*4887Schin b = s; 541*4887Schin else if (!(b = ip = memdup(s, n - index_offset))) 542*4887Schin error(3, "checkpoint index alloc error"); 543*4887Schin 544*4887Schin /* 545*4887Schin * loop on the index and copy the non-ignored chunks to the output 546*4887Schin */ 547*4887Schin 548*4887Schin ppcheckout(); 549*4887Schin p = PPBUFSIZ - (pp.outp - pp.outbuf); 550*4887Schin keep_begin = 0; 551*4887Schin keep_end = 0; 552*4887Schin skip_end = 0; 553*4887Schin while (*b) 554*4887Schin { 555*4887Schin fp = ppsetfile(b); 556*4887Schin while (*b++); 557*4887Schin g = b; 558*4887Schin while (*b++); 559*4887Schin next_begin = strtol(b, &t, 10); 560*4887Schin next_end = strtol(t + 1, &t, 10); 561*4887Schin if (pp.test & 0x0200) error(2, "%s: %s p=%lu next=<%lu,%lu> keep=<%lu,%lu> skip=<-,%lu> guard=%s", keyname(X_CHECKPOINT), fp->name, p, next_begin, next_end, keep_begin, keep_end, skip_end, fp->guard == INC_CLEAR ? "[CLEAR]" : fp->guard == INC_TEST ? "[TEST]" : fp->guard == INC_IGNORE ? "[IGNORE]" : fp->guard->name); 562*4887Schin b = t + 1; 563*4887Schin if (next_begin >= skip_end) 564*4887Schin { 565*4887Schin if (!ppmultiple(fp, INC_TEST)) 566*4887Schin { 567*4887Schin if (pp.test & 0x0100) error(2, "%s: %s IGNORE", keyname(X_CHECKPOINT), fp->name); 568*4887Schin if (!keep_begin && skip_end < next_begin) 569*4887Schin keep_begin = skip_end; 570*4887Schin if (keep_begin) 571*4887Schin { 572*4887Schin flush: 573*4887Schin if (sfseek(sp, file_offset + keep_begin, SEEK_SET) != file_offset + keep_begin) 574*4887Schin error(3, "checkpoint data seek error"); 575*4887Schin n = next_begin - keep_begin; 576*4887Schin if (pp.test & 0x0100) error(2, "%s: copy <%lu,%lu> n=%lu p=%lu", keyname(X_CHECKPOINT), keep_begin, next_begin - 1, n, p); 577*4887Schin while (n > p) 578*4887Schin { 579*4887Schin if (sfread(sp, pp.outp, p) != p) 580*4887Schin error(3, "checkpoint data read error"); 581*4887Schin PPWRITE(PPBUFSIZ); 582*4887Schin pp.outp = pp.outbuf; 583*4887Schin n -= p; 584*4887Schin p = PPBUFSIZ; 585*4887Schin } 586*4887Schin if (n) 587*4887Schin { 588*4887Schin if (sfread(sp, pp.outp, n) != n) 589*4887Schin error(3, "checkpoint data read error"); 590*4887Schin pp.outp += n; 591*4887Schin p -= n; 592*4887Schin } 593*4887Schin keep_begin = 0; 594*4887Schin if (keep_end <= next_end) 595*4887Schin keep_end = 0; 596*4887Schin } 597*4887Schin skip_end = next_end; 598*4887Schin } 599*4887Schin else if (!keep_begin) 600*4887Schin { 601*4887Schin if (skip_end) 602*4887Schin { 603*4887Schin keep_begin = skip_end; 604*4887Schin skip_end = 0; 605*4887Schin } 606*4887Schin else keep_begin = next_begin; 607*4887Schin if (keep_end < next_end) 608*4887Schin keep_end = next_end; 609*4887Schin } 610*4887Schin } 611*4887Schin if (*g && fp->guard != INC_IGNORE) 612*4887Schin fp->guard = ppsymset(pp.symtab, g); 613*4887Schin } 614*4887Schin if (keep_end) 615*4887Schin { 616*4887Schin if (!keep_begin) 617*4887Schin keep_begin = skip_end > next_end ? skip_end : next_end; 618*4887Schin next_begin = next_end = keep_end; 619*4887Schin g = b; 620*4887Schin goto flush; 621*4887Schin } 622*4887Schin if (pp.test & 0x0100) error(2, "%s: loop", keyname(X_CHECKPOINT)); 623*4887Schin 624*4887Schin /* 625*4887Schin * read the compacted definitions 626*4887Schin */ 627*4887Schin 628*4887Schin if (sfseek(sp, macro_offset, SEEK_SET) != macro_offset) 629*4887Schin error(3, "checkpoint macro seek error"); 630*4887Schin if (!(s = sfreserve(sp, index_offset - macro_offset, 0))) 631*4887Schin error(3, "checkpoint macro read error"); 632*4887Schin 633*4887Schin /* 634*4887Schin * read the flags 635*4887Schin */ 636*4887Schin 637*4887Schin while (*s) 638*4887Schin { 639*4887Schin #if _options_dumped_ 640*4887Schin if (streq(s, "OPTION")) /* ... */; 641*4887Schin else 642*4887Schin #endif 643*4887Schin error(3, "%-.48s: unknown flags in checkpoint file", s); 644*4887Schin } 645*4887Schin s++; 646*4887Schin 647*4887Schin /* 648*4887Schin * unpack and enter the definitions 649*4887Schin */ 650*4887Schin 651*4887Schin while (*s) 652*4887Schin { 653*4887Schin b = s; 654*4887Schin while (*s++); 655*4887Schin m = *s++; 656*4887Schin sym = ppsymset(pp.symtab, b); 657*4887Schin if (sym->macro) 658*4887Schin { 659*4887Schin if (m & LOAD_FUNCTION) 660*4887Schin { 661*4887Schin if (*s++ != '0') 662*4887Schin while (*s++); 663*4887Schin while (*s++); 664*4887Schin } 665*4887Schin if (pp.test & 0x1000) error(2, "checkpoint SKIP %s=%s [%s]", sym->name, s, sym->macro->value); 666*4887Schin while (*s++); 667*4887Schin } 668*4887Schin else 669*4887Schin { 670*4887Schin ppfsm(FSM_MACRO, b); 671*4887Schin sym->flags = 0; 672*4887Schin if (m & LOAD_FUNCTION) sym->flags |= SYM_FUNCTION; 673*4887Schin if (m & LOAD_MULTILINE) sym->flags |= SYM_MULTILINE; 674*4887Schin if (m & LOAD_NOEXPAND) sym->flags |= SYM_NOEXPAND; 675*4887Schin if (m & LOAD_PREDICATE) sym->flags |= SYM_PREDICATE; 676*4887Schin if (m & LOAD_READONLY) sym->flags |= SYM_READONLY; 677*4887Schin if (m & LOAD_VARIADIC) sym->flags |= SYM_VARIADIC; 678*4887Schin mac = sym->macro = newof(0, struct ppmacro, 1, 0); 679*4887Schin if (sym->flags & SYM_FUNCTION) 680*4887Schin { 681*4887Schin for (n = 0; *s >= '0' && *s <= '9'; n = n * 10 + *s++ - '0'); 682*4887Schin if (*s++) error(3, "%-.48: checkpoint macro arity botched", sym->name); 683*4887Schin if (mac->arity = n) 684*4887Schin { 685*4887Schin b = s; 686*4887Schin while (*s++); 687*4887Schin mac->formals = (char*)memcpy(oldof(0, char, 0, s - b), b, s - b); 688*4887Schin } 689*4887Schin } 690*4887Schin b = s; 691*4887Schin while (*s++); 692*4887Schin mac->size = s - b - 1; 693*4887Schin mac->value = (char*)memcpy(oldof(0, char, 0, mac->size + 1), b, mac->size + 1); 694*4887Schin if (pp.test & 0x1000) error(2, "checkpoint LOAD %s=%s", sym->name, mac->value); 695*4887Schin } 696*4887Schin } 697*4887Schin 698*4887Schin /* 699*4887Schin * we are now at EOF 700*4887Schin */ 701*4887Schin 702*4887Schin if (ip) 703*4887Schin { 704*4887Schin pp.in->fd = -1; 705*4887Schin free(ip); 706*4887Schin } 707*4887Schin #if ARCHIVE 708*4887Schin if (pp.member) pp.member = 0; 709*4887Schin else 710*4887Schin #endif 711*4887Schin { 712*4887Schin sfclose(sp); 713*4887Schin pp.in->flags |= IN_eof|IN_newline; 714*4887Schin pp.in->nextchr = pp.in->buffer + PPBAKSIZ; 715*4887Schin *pp.in->nextchr++ = 0; 716*4887Schin *pp.in->nextchr = 0; 717*4887Schin } 718*4887Schin pp.mode &= ~LOADING; 719*4887Schin } 720*4887Schin 721*4887Schin #endif 722