#pragma prototyped
#ifndef _PPLIB_H
#define _PPLIB_H
#ifndef ARCHIVE
#define ARCHIVE 1
#endif
#ifndef CATSTRINGS
#define CATSTRINGS 1
#endif
#ifndef CHECKPOINT
#define CHECKPOINT 1
#endif
#ifndef COMPATIBLE
#define COMPATIBLE 1
#endif
#ifndef MACKEYARGS
#define MACKEYARGS _BLD_DEBUG
#endif
#ifndef POOL
#define POOL 1
#endif
#ifndef PROTOTYPE
#define PROTOTYPE 1
#endif
#define TRUNCLENGTH 8
#if _BLD_DEBUG
#undef DEBUG
#define DEBUG (TRACE_message|TRACE_count|TRACE_debug)
#else
#ifndef DEBUG
#define DEBUG (TRACE_message)
#endif
#endif
#define TEST_count (1L<<24)
#define TEST_hashcount (1L<<25)
#define TEST_hashdump (1L<<26)
#define TEST_hit (1L<<27)
#define TEST_noinit (1L<<28)
#define TEST_nonoise (1L<<29)
#define TEST_noproto (1L<<30)
#define TEST_INVERT (1L<<31)
#define PROTO_CLASSIC (1<<0)
#define PROTO_DISABLE (1<<1)
#define PROTO_EXTERNALIZE (1<<2)
#define PROTO_FORCE (1<<3)
#define PROTO_HEADER (1<<4)
#define PROTO_INCLUDE (1<<5)
#define PROTO_INITIALIZED (1<<6)
#define PROTO_LINESYNC (1<<7)
#define PROTO_NOPRAGMA (1<<8)
#define PROTO_PASS (1<<9)
#define PROTO_PLUSPLUS (1<<10)
#define PROTO_RETAIN (1<<11)
#define PROTO_TEST (1<<12)
#define PROTO_USER (1<<13)
#define SEARCH_EXISTS 0
#define SEARCH_HOSTED (1<<0)
#define SEARCH_IGNORE (1<<1)
#define SEARCH_INCLUDE (1<<2)
#define SEARCH_VENDOR (1<<3)
#define SEARCH_USER (1<<4)
#define STYLE_gnu (1<<0)
#define IN_c (1<<0)
#define IN_defguard (1<<1)
#define IN_disable (1<<2)
#define IN_endguard (1<<3)
#define IN_eof (1<<4)
#define IN_expand (1<<5)
#define IN_flush (1<<6)
#define IN_hosted (1<<7)
#define IN_ignoreline (1<<8)
#define IN_newline (1<<9)
#define IN_noguard (1<<10)
#define IN_prototype (1<<11)
#define IN_regular (1<<12)
#define IN_static (1<<13)
#define IN_sync (1<<14)
#define IN_tokens (1L<<15)
#define OPT_GLOBAL (1<<0)
#define OPT_PASS (1<<1)
struct ppsymbol;
struct ppindex;
typedef char* (*PPBUILTIN)(char*, const char*, const char*);
typedef void (*PPCOMMENT)(const char*, const char*, const char*, int);
typedef void (*PPINCREF)(const char*, const char*, int, int);
typedef void (*PPLINESYNC)(int, const char*);
typedef void (*PPMACREF)(struct ppsymbol*, const char*, int, int, unsigned long);
typedef int (*PPOPTARG)(int, int, const char*);
typedef void (*PPPRAGMA)(const char*, const char*, const char*, const char*, int);
struct ppinstk
{
char* nextchr;
struct ppinstk* next;
struct ppinstk* prev;
long* control;
char* buffer;
char* file;
char* prefix;
struct ppsymbol* symbol;
#if CHECKPOINT
struct ppindex* index;
int buflen;
#endif
int line;
int vendor;
short fd;
short hide;
short flags;
char type;
};
#if MACKEYARGS
struct ppkeyarg
{
char* name;
char* value;
};
#endif
struct pplist
{
char* value;
struct pplist* next;
};
struct oplist
{
int op;
char* value;
struct oplist* next;
};
struct pphide
{
struct ppmacro* macro;
unsigned long flags;
int level;
};
struct ppmacstk
{
struct ppmacstk* next;
struct ppmacstk* prev;
int line;
char* arg[1];
};
struct ppmember
{
struct ppdirs* archive;
unsigned long offset;
unsigned long size;
};
struct counter
{
int candidate;
int function;
int macro;
int pplex;
int push;
int terminal;
int token;
};
struct pptuple
{
struct pptuple* nomatch;
struct pptuple* match;
char token[1];
};
struct ppfileid
{
unsigned long st_dev;
unsigned long st_ino;
};
struct pathid
{
char* path;
struct ppfileid id;
};
#define SAMEID(a,b) ((a)->st_ino==(unsigned long)(b)->st_ino&&(a)->st_dev==(unsigned long)(b)->st_dev)
#define SAVEID(a,b) ((a)->st_ino=(unsigned long)(b)->st_ino,(a)->st_dev=(unsigned long)(b)->st_dev)
#define _PP_CONTEXT_PRIVATE_ \
struct ppcontext* context; \
long state; \
long mode; \
long option; \
long test; \
struct \
{ \
Sfio_t* sp; \
long flags; \
} filedeps; \
struct ppdirs* firstdir; \
struct ppdirs* lastdir; \
int hide; \
int column; \
int pending; \
char* firstfile; \
char* lastfile; \
char* ignore; \
char* probe; \
Hash_table_t* filtab; \
Hash_table_t* prdtab; \
char* date; \
char* time; \
char* maps; \
long ro_state; \
long ro_mode; \
long ro_option; \
long ro_op[2]; \
struct pathid cdir; \
struct pathid hostdir; \
char* ppdefault; \
struct ppindex* firstindex; \
struct ppindex* lastindex; \
struct oplist* firstop; \
struct oplist* lastop; \
struct oplist* firsttx; \
struct oplist* lasttx; \
unsigned char arg_file; \
unsigned char arg_mode; \
unsigned char arg_style; \
unsigned char c; \
unsigned char hosted; \
unsigned char ignoresrc; \
unsigned char initialized; \
unsigned char standalone; \
unsigned char spare_1;
#define _PP_GLOBALS_PRIVATE_ \
char* checkpoint; \
int constack; \
struct ppinstk* in; \
char* addp; \
char* args; \
char* addbuf; \
char* catbuf; \
char* hdrbuf; \
char* hidebuf; \
char* path; \
char* tmpbuf; \
char* valbuf; \
char* optflags; \
int lastout; \
\
char* include; \
char* prefix; \
struct ppmember* member; \
int hidden; \
int hiding; \
int level; \
struct \
{ \
int input; \
int output; \
} pool; \
struct \
{ \
long ro_state; \
long ro_mode; \
long ro_option; \
long ro_op[2]; \
int on; \
Hash_table_t* symtab; \
} reset; \
int truncate; \
struct ppmacstk* macp; \
char* maxmac; \
char* mactop; \
char* toknxt; \
long* control; \
long* maxcon; \
struct oplist* chop; \
struct ppfile* insert; \
struct ppfile* original; \
struct ppdirs* found; \
int vendor; \
Hash_table_t* dirtab; \
Hash_table_t* strtab; \
PPBUILTIN builtin; \
PPCOMMENT comment; \
PPINCREF incref; \
PPLINESYNC linesync; \
PPLINESYNC olinesync; \
PPMACREF macref; \
PPOPTARG optarg; \
PPPRAGMA pragma; \
struct counter counter; \
char funbuf[256];
#define _PP_SYMBOL_PRIVATE_ \
struct pphide* hidden;
#if MACKEYARGS
#define _PP_MACRO_PRIVATE_ \
struct pptuple* tuple; \
union \
{ \
char* formal; \
struct ppkeyarg* key; \
} args; \
int size;
#define formals args.formal
#define formkeys args.key
#else
#define _PP_MACRO_PRIVATE_ \
struct pptuple* tuple; \
char* formals; \
int size;
#endif
#define _PP_DIRS_PRIVATE_ \
unsigned char c; \
unsigned char index; \
unsigned char type; \
union \
{ \
char* buffer; \
Sfio_t* sp; \
struct ppdirs* subdir; \
} info; \
struct ppfileid id; \
#if !PROTOMAIN
#include <ast.h>
#include <error.h>
#endif
#undef newof
#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
#include "pp.h"
#include "ppdef.h"
#include "ppkey.h"
#undef setstate
#define TRACE_message 01
#define TRACE_count 02
#define TRACE_debug 04
#if DEBUG && !lint
#define PANIC (ERROR_PANIC|ERROR_SOURCE|ERROR_SYSTEM),__FILE__,__LINE__
#else
#define PANIC ERROR_PANIC
#endif
#if DEBUG & TRACE_count
#define count(x) pp.counter.x++
#else
#define count(x)
#endif
#if DEBUG & TRACE_message
#define message(x) do { if (tracing) error x; } while (0)
#else
#define message(x)
#endif
#if DEBUG & TRACE_debug
#define debug(x) do { if (tracing) error x; } while (0)
#else
#define debug(x)
#endif
#define MEMCPY(to,fr,n) \
do switch(n) \
{ default : memcpy(to,fr,n); to += n; fr += n; break; \
case 7 : *to++ = *fr++; \
case 6 : *to++ = *fr++; \
case 5 : *to++ = *fr++; \
case 4 : *to++ = *fr++; \
case 3 : *to++ = *fr++; \
case 2 : *to++ = *fr++; \
case 1 : *to++ = *fr++; \
case 0 : break; \
} while (0)
#define NEWDIRECTIVE (-1)
#undef dirname
#undef error
#define dirname(x) ppkeyname(x,1)
#define error pperror
#define keyname(x) ppkeyname(x,0)
#define nextframe(m,p) (m->next=m+(p-(char*)m+sizeof(struct ppmacstk)-1)/sizeof(struct ppmacstk)+1)
#define popframe(m) (m=m->prev)
#define pptokchr(c) pptokstr(NiL,(c))
#define pushcontrol() do { if (pp.control++ >= pp.maxcon) ppnest(); } while (0)
#define pushframe(m) (m->next->prev=m,m=m->next)
#define setmode(m,v) ppset(&pp.mode,m,v)
#define setoption(m,v) ppset(&pp.option,m,v)
#define setstate(m,v) ppset(&pp.state,m,v)
#define tracing (error_info.trace<0)
#define ppgetfile(x) ((struct ppfile*)hashlook(pp.filtab,x,HASH_LOOKUP,NiL))
#define ppsetfile(x) ((struct ppfile*)hashlook(pp.filtab,x,HASH_CREATE|HASH_SIZE(sizeof(struct ppfile)),NiL))
#define ppkeyget(t,n) (struct ppsymkey*)hashlook(t,n,HASH_LOOKUP,NiL)
#define ppkeyref(t,n) (struct ppsymkey*)hashlook(t,n,HASH_LOOKUP|HASH_INTERNAL,NiL)
#define ppkeyset(t,n) (struct ppsymkey*)hashlook(t,n,HASH_CREATE|HASH_SIZE(sizeof(struct ppsymkey)),NiL)
#define MARK '@'
#define ARGOFFSET '1'
#define STRAPP(p,v,r) do{r=(v);while((*p++)=(*r++));}while(0)
#define STRCOPY(p,v,r) do{r=(v);while((*p++)=(*r++));p--;}while(0)
#define STRCOPY2(p,r) do{while((*p++)=(*r++));p--;}while(0)
#define SETFILE(p,v) (p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'F',(long)v,MARK))
#define SETLINE(p,v) (p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'L',(long)v,MARK))
#define peekchr() (*pp.in->nextchr)
#define ungetchr(c) (*--pp.in->nextchr=(c))
#define MAXID 255
#define MAXTOKEN PPTOKSIZ
#define MAXFORMALS 64
#define MAXHIDDEN 8
#define DEFMACSTACK (MAXFORMALS*32*32)
#define FSM_COMPATIBILITY 1
#define FSM_IDADD 2
#define FSM_IDDEL 3
#define FSM_INIT 4
#define FSM_MACRO 5
#define FSM_OPSPACE 6
#define FSM_PLUSPLUS 7
#define FSM_QUOTADD 8
#define FSM_QUOTDEL 9
#define IN_TOP 01
#define IN_BUFFER (2|IN_TOP)
#define IN_COPY 2
#define IN_EXPAND 4
#define IN_FILE (4|IN_TOP)
#define IN_INIT (6|IN_TOP)
#define IN_MACRO 8
#define IN_MULTILINE (8|IN_TOP)
#define IN_QUOTE 10
#define IN_RESCAN (10|IN_TOP)
#define IN_SQUOTE 12
#define IN_STRING 14
#define INC_CLEAR ((struct ppsymbol*)0)
#define INC_IGNORE ((struct ppsymbol*)pp.addbuf)
#define INC_TEST ((struct ppsymbol*)pp.catbuf)
#define INC_BOUND(n) (1<<(n))
#define INC_MEMBER(n) (1<<((n)+INC_MAX))
#define INC_PREFIX 0
#define INC_LOCAL 1
#define INC_STANDARD 2
#define INC_VENDOR 3
#define INC_MAX 4
#define INC_SELF (1<<(2*INC_MAX+0))
#define INC_EXISTS (1<<(2*INC_MAX+1))
#define INC_LISTED (1<<(2*INC_MAX+2))
#define INC_MAPALL (1<<(2*INC_MAX+3))
#define INC_MAPHOSTED (1<<(2*INC_MAX+4))
#define INC_MAPNOHOSTED (1<<(2*INC_MAX+5))
#define INC_MAPNOLOCAL (1<<(2*INC_MAX+6))
#define INC_HOSTED (1<<(2*INC_MAX+7))
#define TYPE_ARCHIVE (1<<0)
#define TYPE_BUFFER (1<<1)
#define TYPE_CHECKPOINT (1<<2)
#define TYPE_DIRECTORY (1<<3)
#define TYPE_HOSTED (1<<4)
#define TYPE_INCLUDE (1<<5)
#define TYPE_VENDOR (1<<6)
#define TOK_BUILTIN (1<<0)
#define TOK_FORMAL (1<<1)
#define TOK_ID (1<<2)
#define TOK_TOKCAT (1<<3)
#define HADELSE (1<<0)
#define KEPT (1<<1)
#define SKIP (1<<2)
#define BLOCKBITS 3
#define SETIFBLOCK(p) (*(p)=(*((p)-1)&SKIP)|((long)error_info.line<<BLOCKBITS))
#define GETIFLINE(p) ((*(p)>>BLOCKBITS)&((1L<<(sizeof(long)*CHAR_BIT-BLOCKBITS))-1))
#define PUSH(t,p) \
do \
{ \
count(push); \
if (!pp.in->next) \
{ \
pp.in->next = newof(0, struct ppinstk, 1, 0); \
pp.in->next->prev = pp.in; \
} \
p = pp.in = pp.in->next; \
p->type = t; \
p->flags = 0; \
} while (0)
#define PUSH_BUFFER(f,p,n) \
pppush(IN_BUFFER,f,p,n)
#define PUSH_COPY(p,n) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_COPY, cur); \
cur->line = error_info.line; \
error_info.line = n; \
cur->nextchr = p; \
cur->prev->symbol->flags &= ~SYM_DISABLED; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_EXPAND(p,n) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_EXPAND, cur); \
cur->line = error_info.line; \
error_info.line = n; \
cur->prev->symbol->flags &= ~SYM_DISABLED; \
cur->buffer = cur->nextchr = ppexpand(p); \
if (!(cur->prev->symbol->flags & SYM_MULTILINE)) \
cur->prev->symbol->flags |= SYM_DISABLED; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_FILE(f,d) \
pppush(IN_FILE,f,NiL,d)
#define PUSH_INIT(f,p) \
pppush(IN_INIT,f,p,1)
#define PUSH_MACRO(p) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_MACRO, cur); \
cur->symbol = p; \
cur->nextchr = p->macro->value; \
p->flags |= SYM_DISABLED; \
if (p->flags & SYM_FUNCTION) pushframe(pp.macp); \
pp.state &= ~NEWLINE; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_TUPLE(p,v) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_MACRO, cur); \
cur->symbol = p; \
cur->nextchr = v; \
p->flags |= SYM_DISABLED; \
pp.state &= ~NEWLINE; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_MULTILINE(p) \
do \
{ \
register struct ppinstk* cur; \
register int n; \
PUSH(IN_MULTILINE, cur); \
cur->symbol = p; \
cur->flags |= IN_defguard|IN_endguard|IN_noguard; \
pushcontrol(); \
cur->control = pp.control; \
*pp.control = 0; \
cur->file = error_info.file; \
n = strlen(error_info.file) + strlen(((struct ppsymbol*)p)->name) + 24; \
error_info.file = cur->buffer = newof(0, char, n, 0); \
sfsprintf(error_info.file, n, "%s:%s,%d", cur->file, p->name, error_info.line); \
cur->line = error_info.line; \
error_info.line = 1; \
cur->nextchr = p->macro->value; \
if (p->flags & SYM_FUNCTION) pushframe(pp.macp); \
pp.state &= ~NEWLINE; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_QUOTE(p,n) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_QUOTE, cur); \
cur->nextchr = p; \
pp.state |= QUOTE; \
cur->line = error_info.line; \
error_info.line = n; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_RESCAN(p) \
pppush(IN_RESCAN,NiL,p,0)
#define PUSH_SQUOTE(p,n) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_SQUOTE, cur); \
cur->nextchr = p; \
pp.state |= SQUOTE; \
cur->line = error_info.line; \
error_info.line = n; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_STRING(p) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_STRING, cur); \
cur->nextchr = p; \
if (pp.state & DISABLE) cur->flags |= IN_disable; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define PUSH_LINE(p) \
do \
{ \
register struct ppinstk* cur; \
PUSH(IN_STRING, cur); \
cur->nextchr = p; \
pp.state |= DISABLE|NOSPACE|PASSEOF|STRIP; \
debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
} while (0)
#define POP_LINE() \
do \
{ \
debug((-7, "POP in=%s", ppinstr(pp.in))); \
pp.in = pp.in->prev; \
pp.state &= ~(DISABLE|NOSPACE|PASSEOF|STRIP); \
} while (0)
struct ppcontext
{
_PP_CONTEXT_PUBLIC_
_PP_CONTEXT_PRIVATE_
};
struct ppfile
{
HASH_HEADER;
struct ppsymbol* guard;
struct ppfile* bound[INC_MAX];
int flags;
};
#if CHECKPOINT
struct ppindex
{
struct ppindex* next;
struct ppfile* file;
unsigned long begin;
unsigned long end;
};
#endif
struct ppsymkey
{
struct ppsymbol sym;
int lex;
};
#if PROTOMAIN && PROTO_STANDALONE
#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
#define NiL 0
#define NoP(x) (&x,1)
#else
#define NiL ((char*)0)
#define NoP(x)
#endif
#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
#define _PP_DELAY_ #
_PP_DELAY_ ifdef __STDC__
_PP_DELAY_ include <stdlib.h>
_PP_DELAY_ include <unistd.h>
_PP_DELAY_ include <time.h>
_PP_DELAY_ include <string.h>
_PP_DELAY_ else
_PP_DELAY_ define size_t int
extern void* realloc(void*, size_t);
extern void* calloc(size_t, size_t);
extern char* ctime(time_t*);
extern void free(void*);
_PP_DELAY_ ifndef O_RDONLY
extern int access(const char*, int);
extern int close(int);
extern int creat(const char*, int);
extern void exit(int);
extern int link(const char*, const char*);
extern int open(const char*, int, ...);
extern int read(int, void*, int);
extern time_t time(time_t*);
extern int unlink(const char*);
extern int write(int, const void*, int);
_PP_DELAY_ endif
_PP_DELAY_ endif
#else
#define ppassert _pp_assert
#define ppbuiltin _pp_builtin
#define ppcall _pp_call
#define ppcontrol _pp_control
#define ppdump _pp_dump
#define ppexpand _pp_expand
#define ppexpr _pp_expr
#define ppfsm _pp_fsm
#define ppinmap _pp_inmap
#define ppinstr _pp_instr
#define ppkeyname _pp_keyname
#define pplexmap _pp_lexmap
#define pplexstr _pp_lexstr
#define ppload _pp_load
#define ppmodestr _pp_modestr
#define ppmultiple _pp_multiple
#define ppnest _pp_nest
#define ppoption _pp_option
#define ppoptionstr _pp_optionstr
#define pppclose _pp_pclose
#define pppdrop _pp_pdrop
#define pppopen _pp_popen
#define pppread _pp_pread
#define pppredargs _pp_predargs
#define pppush _pp_push
#define pprefmac _pp_refmac
#define ppsearch _pp_search
#define ppset _pp_set
#define ppstatestr _pp_statestr
#define pptokstr _pp_tokstr
#define pptrace _pp_trace
#endif
extern void ppassert(int, char*, char*);
extern void ppbuiltin(void);
extern int ppcall(struct ppsymbol*, int);
extern int ppcontrol(void);
extern void ppdump(void);
extern char* ppexpand(char*);
extern long ppexpr(int*);
extern void ppfsm(int, char*);
extern char* ppinstr(struct ppinstk*);
extern char* ppkeyname(int, int);
extern char* pplexstr(int);
extern void ppload(char*);
extern void ppmapinclude(char*, char*);
extern char* ppmodestr(long);
extern int ppmultiple(struct ppfile*, struct ppsymbol*);
extern void ppnest(void);
extern int ppoption(char*);
extern char* ppoptionstr(long);
extern void pppclose(char*);
extern int pppdrop(char*);
extern char* pppopen(char*, int, char*, char*, char*, char*, int);
extern int pppread(char*);
extern int pppredargs(void);
extern void pppush(int, char*, char*, int);
extern struct ppsymbol* pprefmac(char*, int);
extern int ppsearch(char*, int, int);
extern int ppset(long*, long, int);
extern char* ppstatestr(long);
extern char* pptokstr(char*, int);
extern void pptrace(int);
#if _std_malloc
#include <vmalloc.h>
#undef free
#define free(p) vmfree(Vmregion,(void*)p)
#undef newof
#define newof(p,t,n,x) vmnewof(Vmregion,p,t,n,x)
#undef oldof
#define oldof(p,t,n,x) vmoldof(Vmregion,p,t,n,x)
#undef strdup
#define strdup(s) vmstrdup(Vmregion,s)
#endif
#endif