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