14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1986-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * Glenn Fowler 234887Schin * AT&T Research 244887Schin * 254887Schin * preprocessor stacked input stream support 264887Schin */ 274887Schin 284887Schin #include "pplib.h" 294887Schin 304887Schin 314887Schin /* 324887Schin * convert path to native representation 334887Schin */ 344887Schin 354887Schin #if 0 364887Schin #include "../../lib/libast/path/pathnative.c" /* drop in 2002 */ 374887Schin #else 384887Schin /* Modified by gisburn 2006-08-18 for OpenSolaris ksh93-integration */ 394887Schin #include "../../libast/common/path/pathnative.c" 404887Schin #endif 414887Schin 424887Schin static char* 434887Schin native(register const char* s) 444887Schin { 454887Schin register int c; 464887Schin register struct ppfile* xp; 474887Schin int m; 484887Schin int n; 494887Schin 504887Schin static Sfio_t* np; 514887Schin static Sfio_t* qp; 524887Schin 534887Schin if (!s) 544887Schin return 0; 554887Schin if (!np && !(np = sfstropen()) || !qp && !(qp = sfstropen())) 564887Schin return (char*)s; 574887Schin n = PATH_MAX; 584887Schin do 594887Schin { 604887Schin m = n; 614887Schin n = pathnative(s, sfstrrsrv(np, m), m); 624887Schin } while (n > m); 634887Schin sfstrseek(np, n, SEEK_CUR); 644887Schin s = (const char*)sfstruse(np); 654887Schin for (;;) 664887Schin { 674887Schin switch (c = *s++) 684887Schin { 694887Schin case 0: 704887Schin break; 714887Schin case '\\': 724887Schin case '"': 734887Schin sfputc(qp, '\\'); 744887Schin /*FALLTHROUGH*/ 754887Schin default: 764887Schin sfputc(qp, c); 774887Schin continue; 784887Schin } 794887Schin break; 804887Schin } 814887Schin if (!(xp = ppsetfile(sfstruse(qp)))) 824887Schin return (char*)s; 834887Schin return xp->name; 844887Schin } 854887Schin 864887Schin /* 874887Schin * push stream onto input stack 884887Schin * used by the PUSH_type macros 894887Schin */ 904887Schin 914887Schin void 924887Schin pppush(register int t, register char* s, register char* p, int n) 934887Schin { 944887Schin register struct ppinstk* cur; 954887Schin 964887Schin PUSH(t, cur); 974887Schin cur->line = error_info.line; 984887Schin cur->file = error_info.file; 994887Schin switch (t) 1004887Schin { 1014887Schin case IN_FILE: 1024887Schin if (pp.option & NATIVE) 1034887Schin s = native(s); 1044887Schin cur->flags |= IN_newline; 1054887Schin cur->fd = n; 1064887Schin cur->hide = ++pp.hide; 1074887Schin cur->symbol = 0; 1084887Schin #if CHECKPOINT 1094887Schin if ((pp.mode & (DUMP|INIT)) == DUMP) 1104887Schin { 1114887Schin cur->index = newof(0, struct ppindex, 1, 0); 1124887Schin if (pp.lastindex) pp.lastindex->next = cur->index; 1134887Schin else pp.firstindex = cur->index; 1144887Schin pp.lastindex = cur->index; 1154887Schin cur->index->file = pp.original; 1164887Schin cur->index->begin = ppoffset(); 1174887Schin } 1184887Schin #endif 1194887Schin n = 1; 1204887Schin #if CHECKPOINT 1214887Schin if (!(pp.mode & DUMP)) 1224887Schin #endif 1234887Schin if (!cur->prev->prev && !(pp.state & COMPILE) && isatty(0)) 1244887Schin cur->flags |= IN_flush; 1254887Schin #if ARCHIVE 1264887Schin if (pp.member) 1274887Schin { 1284887Schin switch (pp.member->archive->type & (TYPE_BUFFER|TYPE_CHECKPOINT)) 1294887Schin { 1304887Schin case 0: 1314887Schin #if CHECKPOINT 1324887Schin cur->buflen = pp.member->size; 1334887Schin #endif 1344887Schin p = (cur->buffer = oldof(0, char, 0, pp.member->size + PPBAKSIZ + 1)) + PPBAKSIZ; 1354887Schin if (sfseek(pp.member->archive->info.sp, pp.member->offset, SEEK_SET) != pp.member->offset) 1364887Schin error(3, "%s: archive seek error", pp.member->archive->name); 1374887Schin if (sfread(pp.member->archive->info.sp, p, pp.member->size) != pp.member->size) 1384887Schin error(3, "%s: archive read error", pp.member->archive->name); 1394887Schin pp.member = 0; 1404887Schin break; 1414887Schin case TYPE_BUFFER: 1424887Schin #if CHECKPOINT 1434887Schin case TYPE_CHECKPOINT|TYPE_BUFFER: 1444887Schin cur->buflen = pp.member->size; 1454887Schin #endif 1464887Schin p = cur->buffer = pp.member->archive->info.buffer + pp.member->offset; 1474887Schin cur->flags |= IN_static; 1484887Schin pp.member = 0; 1494887Schin break; 1504887Schin #if CHECKPOINT 1514887Schin case TYPE_CHECKPOINT: 1524887Schin p = cur->buffer = ""; 1534887Schin cur->flags |= IN_static; 1544887Schin break; 1554887Schin #endif 1564887Schin } 1574887Schin cur->flags |= IN_eof|IN_newline; 1584887Schin cur->fd = -1; 1594887Schin } 1604887Schin else 1614887Schin #endif 1624887Schin { 1634887Schin if (lseek(cur->fd, 0L, SEEK_END) > 0 && !lseek(cur->fd, 0L, SEEK_SET)) 1644887Schin cur->flags |= IN_regular; 1654887Schin errno = 0; 1664887Schin #if PROTOTYPE 1674887Schin 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)))) 1684887Schin { 1694887Schin *(p = cur->buffer - 1) = 0; 1704887Schin cur->buffer -= PPBAKSIZ; 1714887Schin cur->flags |= IN_prototype; 1724887Schin cur->fd = -1; 1734887Schin } 1744887Schin else 1754887Schin #endif 1764887Schin *(p = (cur->buffer = oldof(0, char, 0, PPBUFSIZ + PPBAKSIZ + 1)) + PPBAKSIZ) = 0; 1774887Schin } 1784887Schin if (pp.incref && !(pp.mode & INIT)) 1794887Schin (*pp.incref)(error_info.file, s, error_info.line - 1, PP_SYNC_PUSH); 1804887Schin if (pp.macref || (pp.option & IGNORELINE)) 1814887Schin cur->flags |= IN_ignoreline; 1824887Schin cur->prefix = pp.prefix; 1834887Schin /*FALLTHROUGH*/ 1844887Schin case IN_BUFFER: 1854887Schin case IN_INIT: 1864887Schin case IN_RESCAN: 1874887Schin pushcontrol(); 1884887Schin cur->control = pp.control; 1894887Schin *pp.control = 0; 1904887Schin cur->vendor = pp.vendor; 1914887Schin if (cur->type != IN_RESCAN) 1924887Schin { 1934887Schin if (cur->type == IN_INIT) 1944887Schin pp.mode |= MARKHOSTED; 1954887Schin error_info.file = s; 1964887Schin error_info.line = n; 1974887Schin } 1984887Schin if (pp.state & HIDDEN) 1994887Schin { 2004887Schin pp.state &= ~HIDDEN; 2014887Schin pp.hidden = 0; 2024887Schin if (!(pp.state & NOTEXT) && pplastout() != '\n') 2034887Schin ppputchar('\n'); 2044887Schin } 2054887Schin pp.state |= NEWLINE; 2064887Schin if (pp.mode & HOSTED) cur->flags |= IN_hosted; 2074887Schin else cur->flags &= ~IN_hosted; 2084887Schin if (pp.mode & (INIT|MARKHOSTED)) 2094887Schin { 2104887Schin pp.mode |= HOSTED; 2114887Schin pp.flags |= PP_hosted; 2124887Schin } 2134887Schin switch (cur->type) 2144887Schin { 2154887Schin case IN_FILE: 2164887Schin if (!(pp.mode & (INIT|MARKHOSTED))) 2174887Schin { 2184887Schin pp.mode &= ~HOSTED; 2194887Schin pp.flags &= ~PP_hosted; 2204887Schin } 2214887Schin #if CATSTRINGS 2224887Schin if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE; 2234887Schin else 2244887Schin #endif 2254887Schin if (pp.linesync) 2264887Schin (*pp.linesync)(error_info.line, error_info.file); 2274887Schin #if ARCHIVE && CHECKPOINT 2284887Schin if (pp.member) 2294887Schin ppload(NiL); 2304887Schin #endif 2314887Schin if (pp.mode & MARKC) 2324887Schin { 2334887Schin cur->flags |= IN_c; 2344887Schin pp.mode &= ~MARKC; 2354887Schin if (!(cur->prev->flags & IN_c)) 2364887Schin { 2374887Schin debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp.in), pptokchr(*pp.in->nextchr), pp.in->nextchr)); 2384887Schin PUSH_BUFFER("C", "extern \"C\" {\n", 1); 2394887Schin return; 2404887Schin } 2414887Schin } 2424887Schin else if (cur->prev->flags & IN_c) 2434887Schin { 2444887Schin debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp.in), pptokchr(*pp.in->nextchr), pp.in->nextchr)); 2454887Schin PUSH_BUFFER("C", "extern \"C++\" {\n", 1); 2464887Schin return; 2474887Schin } 2484887Schin break; 2494887Schin case IN_BUFFER: 2504887Schin cur->buffer = p = strdup(p); 2514887Schin break; 2524887Schin default: 2534887Schin cur->buffer = p; 2544887Schin break; 2554887Schin } 2564887Schin cur->nextchr = p; 2574887Schin break; 2584887Schin #if DEBUG 2594887Schin default: 2604887Schin error(PANIC, "use PUSH_<%d>(...) instead of pppush(IN_<%d>, ...)", cur->type, cur->type); 2614887Schin break; 2624887Schin #endif 2634887Schin } 2644887Schin debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); 2654887Schin } 2664887Schin 2674887Schin /* 2684887Schin * external buffer push 2694887Schin */ 2704887Schin 2714887Schin void 2724887Schin ppinput(char* b, char* f, int n) 2734887Schin { 2744887Schin PUSH_BUFFER(f, b, n); 2754887Schin } 2764887Schin 2774887Schin /* 2784887Schin * return expanded value of buffer p 2794887Schin */ 2804887Schin 2814887Schin char* 2824887Schin ppexpand(register char* p) 2834887Schin { 2844887Schin register char* m; 2854887Schin register int n; 2864887Schin register int c; 2874887Schin long restore; 2884887Schin char* pptoken; 2894887Schin char* ppmactop; 2904887Schin struct ppmacstk* nextmacp; 2914887Schin struct ppinstk* cur; 2924887Schin 2934887Schin debug((-7, "before expand: %s", p)); 2944887Schin if (ppmactop = pp.mactop) 2954887Schin { 2964887Schin nextmacp = pp.macp->next; 2974887Schin nextframe(pp.macp, pp.mactop); 2984887Schin } 2994887Schin restore = pp.state & (COLLECTING|DISABLE|STRIP); 3004887Schin pp.state &= ~restore; 3014887Schin pp.mode &= ~MARKMACRO; 3024887Schin PUSH_STRING(p); 3034887Schin cur = pp.in; 3044887Schin pp.in->flags |= IN_expand; 3054887Schin pptoken = pp.token; 3064887Schin n = 2 * MAXTOKEN; 3074887Schin pp.token = p = oldof(0, char, 0, n); 3084887Schin m = p + MAXTOKEN; 3094887Schin for (;;) 3104887Schin { 3114887Schin if (pplex()) 3124887Schin { 3134887Schin if ((pp.token = pp.toknxt) > m) 3144887Schin { 3154887Schin c = pp.token - p; 3164887Schin p = newof(p, char, n += MAXTOKEN, 0); 3174887Schin m = p + n - MAXTOKEN; 3184887Schin pp.token = p + c; 3194887Schin } 3204887Schin if (pp.mode & MARKMACRO) 3214887Schin { 3224887Schin pp.mode &= ~MARKMACRO; 3234887Schin *pp.token++ = MARK; 3244887Schin *pp.token++ = 'X'; 3254887Schin } 3264887Schin } 3274887Schin else if (pp.in == cur) 3284887Schin break; 3294887Schin } 3304887Schin *pp.token = 0; 3314887Schin if (ppmactop) 3324887Schin pp.macp->next = nextmacp; 3334887Schin debug((-7, "after expand: %s", p)); 3344887Schin pp.token = pptoken; 3354887Schin pp.state |= restore; 3364887Schin pp.in = pp.in->prev; 3374887Schin return p; 3384887Schin } 3394887Schin 3404887Schin #if CHECKPOINT 3414887Schin 3424887Schin #define LOAD_FUNCTION (1<<0) 3434887Schin #define LOAD_MULTILINE (1<<1) 3444887Schin #define LOAD_NOEXPAND (1<<2) 3454887Schin #define LOAD_PREDICATE (1<<3) 3464887Schin #define LOAD_READONLY (1<<4) 3474887Schin #define LOAD_VARIADIC (1<<5) 3484887Schin 3494887Schin /* 3504887Schin * macro definition dump 3514887Schin */ 3524887Schin 3534887Schin static int 3544887Schin dump(const char* name, char* v, void* handle) 3554887Schin { 3564887Schin register struct ppmacro* mac; 3574887Schin register struct ppsymbol* sym = (struct ppsymbol*)v; 3584887Schin register int flags; 3594887Schin 3604887Schin NoP(name); 3614887Schin NoP(handle); 3624887Schin if ((mac = sym->macro) && !(sym->flags & (SYM_BUILTIN|SYM_PREDEFINED))) 3634887Schin { 3644887Schin ppprintf("%s", sym->name); 3654887Schin ppputchar(0); 3664887Schin flags = 0; 3674887Schin if (sym->flags & SYM_FUNCTION) flags |= LOAD_FUNCTION; 3684887Schin if (sym->flags & SYM_MULTILINE) flags |= LOAD_MULTILINE; 3694887Schin if (sym->flags & SYM_NOEXPAND) flags |= LOAD_NOEXPAND; 3704887Schin if (sym->flags & SYM_PREDICATE) flags |= LOAD_PREDICATE; 3714887Schin if (sym->flags & SYM_READONLY) flags |= LOAD_READONLY; 3724887Schin if (sym->flags & SYM_VARIADIC) flags |= LOAD_VARIADIC; 3734887Schin ppputchar(flags); 3744887Schin if (sym->flags & SYM_FUNCTION) 3754887Schin { 3764887Schin ppprintf("%d", mac->arity); 3774887Schin ppputchar(0); 3784887Schin if (mac->arity) 3794887Schin { 3804887Schin ppprintf("%s", mac->formals); 3814887Schin ppputchar(0); 3824887Schin } 3834887Schin } 3844887Schin ppprintf("%s", mac->value); 3854887Schin ppputchar(0); 3864887Schin } 3874887Schin return(0); 3884887Schin } 3894887Schin 3904887Schin /* 3914887Schin * dump macro definitions for quick loading via ppload() 3924887Schin */ 3934887Schin 3944887Schin void 3954887Schin ppdump(void) 3964887Schin { 3974887Schin register struct ppindex* ip; 3984887Schin unsigned long macro_offset; 3994887Schin unsigned long index_offset; 4004887Schin 4014887Schin /* 4024887Schin * NOTE: we assume '\0' does not occur in valid preprocessed output 4034887Schin */ 4044887Schin 4054887Schin ppputchar(0); 4064887Schin 4074887Schin /* 4084887Schin * output global flags 4094887Schin */ 4104887Schin 4114887Schin macro_offset = ppoffset(); 4124887Schin ppputchar(0); 4134887Schin 4144887Schin /* 4154887Schin * output macro definitions 4164887Schin */ 4174887Schin 4184887Schin hashwalk(pp.symtab, 0, dump, NiL); 4194887Schin ppputchar(0); 4204887Schin 4214887Schin /* 4224887Schin * output include file index 4234887Schin */ 4244887Schin 4254887Schin index_offset = ppoffset(); 4264887Schin ip = pp.firstindex; 4274887Schin while (ip) 4284887Schin { 4294887Schin ppprintf("%s", ip->file->name); 4304887Schin ppputchar(0); 4314887Schin if (ip->file->guard != INC_CLEAR && ip->file->guard != INC_IGNORE && ip->file->guard != INC_TEST) 4324887Schin ppprintf("%s", ip->file->guard->name); 4334887Schin ppputchar(0); 4344887Schin ppprintf("%lu", ip->begin); 4354887Schin ppputchar(0); 4364887Schin ppprintf("%lu", ip->end); 4374887Schin ppputchar(0); 4384887Schin ip = ip->next; 4394887Schin } 4404887Schin ppputchar(0); 4414887Schin 4424887Schin /* 4434887Schin * output offset directory 4444887Schin */ 4454887Schin 4464887Schin ppprintf("%010lu", macro_offset); 4474887Schin ppputchar(0); 4484887Schin ppprintf("%010lu", index_offset); 4494887Schin ppputchar(0); 4504887Schin ppflushout(); 4514887Schin } 4524887Schin 4534887Schin /* 4544887Schin * load text and macro definitions from a previous ppdump() 4554887Schin * s is the string argument from the pragma (including quotes) 4564887Schin */ 4574887Schin 4584887Schin void 4594887Schin ppload(register char* s) 4604887Schin { 4614887Schin register char* b; 4624887Schin register Sfio_t* sp; 4634887Schin int m; 4644887Schin char* g; 4654887Schin char* t; 4664887Schin unsigned long n; 4674887Schin unsigned long p; 4684887Schin unsigned long macro_offset; 4694887Schin unsigned long index_offset; 4704887Schin unsigned long file_offset; 4714887Schin unsigned long file_size; 4724887Schin unsigned long keep_begin; 4734887Schin unsigned long keep_end; 4744887Schin unsigned long skip_end; 4754887Schin unsigned long next_begin; 4764887Schin unsigned long next_end; 4774887Schin struct ppfile* fp; 4784887Schin struct ppsymbol* sym; 4794887Schin struct ppmacro* mac; 4804887Schin 4814887Schin char* ip = 0; 4824887Schin 4834887Schin pp.mode |= LOADING; 4844887Schin if (!(pp.state & STANDALONE)) 4854887Schin error(3, "checkpoint load in standalone mode only"); 4864887Schin #if ARCHIVE 4874887Schin if (pp.member) 4884887Schin { 4894887Schin sp = pp.member->archive->info.sp; 4904887Schin file_offset = pp.member->offset; 4914887Schin file_size = pp.member->size; 4924887Schin if (sfseek(sp, file_offset + 22, SEEK_SET) != file_offset + 22 || !(s = sfgetr(sp, '\n', 1))) 4934887Schin error(3, "checkpoint magic error"); 4944887Schin } 4954887Schin else 4964887Schin #endif 4974887Schin { 4984887Schin if (pp.in->type != IN_FILE) 4994887Schin error(3, "checkpoint load from files only"); 5004887Schin if (pp.in->flags & IN_prototype) 5014887Schin pp.in->fd = pppdrop(pp.in->buffer + PPBAKSIZ); 5024887Schin file_offset = 0; 5034887Schin if (pp.in->fd >= 0) 5044887Schin { 5054887Schin if (!(sp = sfnew(NiL, NiL, SF_UNBOUND, pp.in->fd, SF_READ))) 5064887Schin error(3, "checkpoint read error"); 5074887Schin file_size = sfseek(sp, 0L, SEEK_END); 5084887Schin } 5094887Schin else 5104887Schin { 5114887Schin file_size = pp.in->buflen; 5124887Schin if (!(sp = sfnew(NiL, pp.in->buffer + ((pp.in->flags & IN_static) ? 0 : PPBAKSIZ), file_size, -1, SF_READ|SF_STRING))) 5134887Schin error(3, "checkpoint read error"); 5144887Schin } 5154887Schin } 5164887Schin if (!streq(s, pp.checkpoint)) 5174887Schin error(3, "checkpoint version %s does not match %s", s, pp.checkpoint); 5184887Schin 5194887Schin /* 5204887Schin * get the macro and index offsets 5214887Schin */ 5224887Schin 5234887Schin p = file_offset + file_size - 22; 5244887Schin if ((n = sfseek(sp, p, SEEK_SET)) != p) 5254887Schin error(3, "checkpoint directory seek error"); 5264887Schin if (!(t = sfreserve(sp, 22, 0))) 5274887Schin error(3, "checkpoint directory read error"); 5284887Schin macro_offset = file_offset + strtol(t, &t, 10); 5294887Schin index_offset = file_offset + strtol(t + 1, NiL, 10); 5304887Schin 5314887Schin /* 5324887Schin * read the include index 5334887Schin */ 5344887Schin 5354887Schin if (sfseek(sp, index_offset, SEEK_SET) != index_offset) 5364887Schin error(3, "checkpoint index seek error"); 5374887Schin if (!(s = sfreserve(sp, n - index_offset, 0))) 5384887Schin error(3, "checkpoint index read error"); 5394887Schin if (sfset(sp, 0, 0) & SF_STRING) 5404887Schin b = s; 5414887Schin else if (!(b = ip = memdup(s, n - index_offset))) 5424887Schin error(3, "checkpoint index alloc error"); 5434887Schin 5444887Schin /* 5454887Schin * loop on the index and copy the non-ignored chunks to the output 5464887Schin */ 5474887Schin 5484887Schin ppcheckout(); 5494887Schin p = PPBUFSIZ - (pp.outp - pp.outbuf); 5504887Schin keep_begin = 0; 5514887Schin keep_end = 0; 5524887Schin skip_end = 0; 5534887Schin while (*b) 5544887Schin { 5554887Schin fp = ppsetfile(b); 5564887Schin while (*b++); 5574887Schin g = b; 5584887Schin while (*b++); 5594887Schin next_begin = strtol(b, &t, 10); 5604887Schin next_end = strtol(t + 1, &t, 10); 5614887Schin 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); 5624887Schin b = t + 1; 5634887Schin if (next_begin >= skip_end) 5644887Schin { 5654887Schin if (!ppmultiple(fp, INC_TEST)) 5664887Schin { 5674887Schin if (pp.test & 0x0100) error(2, "%s: %s IGNORE", keyname(X_CHECKPOINT), fp->name); 5684887Schin if (!keep_begin && skip_end < next_begin) 5694887Schin keep_begin = skip_end; 5704887Schin if (keep_begin) 5714887Schin { 5724887Schin flush: 5734887Schin if (sfseek(sp, file_offset + keep_begin, SEEK_SET) != file_offset + keep_begin) 5744887Schin error(3, "checkpoint data seek error"); 5754887Schin n = next_begin - keep_begin; 5764887Schin if (pp.test & 0x0100) error(2, "%s: copy <%lu,%lu> n=%lu p=%lu", keyname(X_CHECKPOINT), keep_begin, next_begin - 1, n, p); 5774887Schin while (n > p) 5784887Schin { 5794887Schin if (sfread(sp, pp.outp, p) != p) 5804887Schin error(3, "checkpoint data read error"); 5814887Schin PPWRITE(PPBUFSIZ); 5824887Schin pp.outp = pp.outbuf; 5834887Schin n -= p; 5844887Schin p = PPBUFSIZ; 5854887Schin } 5864887Schin if (n) 5874887Schin { 5884887Schin if (sfread(sp, pp.outp, n) != n) 5894887Schin error(3, "checkpoint data read error"); 5904887Schin pp.outp += n; 5914887Schin p -= n; 5924887Schin } 5934887Schin keep_begin = 0; 5944887Schin if (keep_end <= next_end) 5954887Schin keep_end = 0; 5964887Schin } 5974887Schin skip_end = next_end; 5984887Schin } 5994887Schin else if (!keep_begin) 6004887Schin { 6014887Schin if (skip_end) 6024887Schin { 6034887Schin keep_begin = skip_end; 6044887Schin skip_end = 0; 6054887Schin } 6064887Schin else keep_begin = next_begin; 6074887Schin if (keep_end < next_end) 6084887Schin keep_end = next_end; 6094887Schin } 6104887Schin } 6114887Schin if (*g && fp->guard != INC_IGNORE) 6124887Schin fp->guard = ppsymset(pp.symtab, g); 6134887Schin } 6144887Schin if (keep_end) 6154887Schin { 6164887Schin if (!keep_begin) 6174887Schin keep_begin = skip_end > next_end ? skip_end : next_end; 6184887Schin next_begin = next_end = keep_end; 6194887Schin g = b; 6204887Schin goto flush; 6214887Schin } 6224887Schin if (pp.test & 0x0100) error(2, "%s: loop", keyname(X_CHECKPOINT)); 6234887Schin 6244887Schin /* 6254887Schin * read the compacted definitions 6264887Schin */ 6274887Schin 6284887Schin if (sfseek(sp, macro_offset, SEEK_SET) != macro_offset) 6294887Schin error(3, "checkpoint macro seek error"); 6304887Schin if (!(s = sfreserve(sp, index_offset - macro_offset, 0))) 6314887Schin error(3, "checkpoint macro read error"); 6324887Schin 6334887Schin /* 6344887Schin * read the flags 6354887Schin */ 6364887Schin 6374887Schin while (*s) 6384887Schin { 6394887Schin #if _options_dumped_ 6404887Schin if (streq(s, "OPTION")) /* ... */; 6414887Schin else 6424887Schin #endif 6434887Schin error(3, "%-.48s: unknown flags in checkpoint file", s); 6444887Schin } 6454887Schin s++; 6464887Schin 6474887Schin /* 6484887Schin * unpack and enter the definitions 6494887Schin */ 6504887Schin 6514887Schin while (*s) 6524887Schin { 6534887Schin b = s; 6544887Schin while (*s++); 6554887Schin m = *s++; 6564887Schin sym = ppsymset(pp.symtab, b); 6574887Schin if (sym->macro) 6584887Schin { 6594887Schin if (m & LOAD_FUNCTION) 6604887Schin { 6614887Schin if (*s++ != '0') 6624887Schin while (*s++); 6634887Schin while (*s++); 6644887Schin } 6654887Schin if (pp.test & 0x1000) error(2, "checkpoint SKIP %s=%s [%s]", sym->name, s, sym->macro->value); 6664887Schin while (*s++); 6674887Schin } 6684887Schin else 6694887Schin { 6704887Schin ppfsm(FSM_MACRO, b); 6714887Schin sym->flags = 0; 6724887Schin if (m & LOAD_FUNCTION) sym->flags |= SYM_FUNCTION; 6734887Schin if (m & LOAD_MULTILINE) sym->flags |= SYM_MULTILINE; 6744887Schin if (m & LOAD_NOEXPAND) sym->flags |= SYM_NOEXPAND; 6754887Schin if (m & LOAD_PREDICATE) sym->flags |= SYM_PREDICATE; 6764887Schin if (m & LOAD_READONLY) sym->flags |= SYM_READONLY; 6774887Schin if (m & LOAD_VARIADIC) sym->flags |= SYM_VARIADIC; 6784887Schin mac = sym->macro = newof(0, struct ppmacro, 1, 0); 6794887Schin if (sym->flags & SYM_FUNCTION) 6804887Schin { 6814887Schin for (n = 0; *s >= '0' && *s <= '9'; n = n * 10 + *s++ - '0'); 6824887Schin if (*s++) error(3, "%-.48: checkpoint macro arity botched", sym->name); 6834887Schin if (mac->arity = n) 6844887Schin { 6854887Schin b = s; 6864887Schin while (*s++); 6874887Schin mac->formals = (char*)memcpy(oldof(0, char, 0, s - b), b, s - b); 6884887Schin } 6894887Schin } 6904887Schin b = s; 6914887Schin while (*s++); 6924887Schin mac->size = s - b - 1; 6934887Schin mac->value = (char*)memcpy(oldof(0, char, 0, mac->size + 1), b, mac->size + 1); 6944887Schin if (pp.test & 0x1000) error(2, "checkpoint LOAD %s=%s", sym->name, mac->value); 6954887Schin } 6964887Schin } 6974887Schin 6984887Schin /* 6994887Schin * we are now at EOF 7004887Schin */ 7014887Schin 7024887Schin if (ip) 7034887Schin { 7044887Schin pp.in->fd = -1; 7054887Schin free(ip); 7064887Schin } 7074887Schin #if ARCHIVE 7084887Schin if (pp.member) pp.member = 0; 7094887Schin else 7104887Schin #endif 7114887Schin { 7124887Schin sfclose(sp); 7134887Schin pp.in->flags |= IN_eof|IN_newline; 7144887Schin pp.in->nextchr = pp.in->buffer + PPBAKSIZ; 7154887Schin *pp.in->nextchr++ = 0; 7164887Schin *pp.in->nextchr = 0; 7174887Schin } 7184887Schin pp.mode &= ~LOADING; 7194887Schin } 7204887Schin 7214887Schin #endif 722