14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1986-2009 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.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*
native(register const char * s)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
pppush(register int t,register char * s,register char * p,int n)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
ppinput(char * b,char * f,int n)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*
ppexpand(register char * p)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
dump(const char * name,char * v,void * handle)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
ppdump(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
ppload(register char * s)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