mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
416 lines
12 KiB
C
416 lines
12 KiB
C
#ifndef COSMOPOLITAN_THIRD_PARTY_AWK_AWK_H_
|
|
#define COSMOPOLITAN_THIRD_PARTY_AWK_AWK_H_
|
|
#include "libc/assert.h"
|
|
#include "libc/limits.h"
|
|
#include "libc/literal.h"
|
|
#include "libc/stdio/stdio.h"
|
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
COSMOPOLITAN_C_START_
|
|
/* clang-format off */
|
|
|
|
typedef double Awkfloat;
|
|
|
|
/* unsigned char is more trouble than it's worth */
|
|
|
|
typedef unsigned char uschar;
|
|
|
|
#define xfree(a) { if ((a) != NULL) { free((void *)(intptr_t)(a)); (a) = NULL; } }
|
|
/*
|
|
* We sometimes cheat writing read-only pointers to NUL-terminate them
|
|
* and then put back the original value
|
|
*/
|
|
#define setptr(ptr, a) (*(char *)(intptr_t)(ptr)) = (a)
|
|
|
|
#define NN(p) ((p) ? (p) : "(null)") /* guaranteed non-null for DPRINTF
|
|
*/
|
|
#define DEBUG
|
|
#ifdef DEBUG
|
|
# define DPRINTF(...) if (dbg) printf(__VA_ARGS__)
|
|
#else
|
|
# define DPRINTF(...)
|
|
#endif
|
|
|
|
extern enum compile_states {
|
|
RUNNING,
|
|
COMPILING,
|
|
ERROR_PRINTING
|
|
} compile_time;
|
|
|
|
extern bool safe; /* false => unsafe, true => safe */
|
|
|
|
#define RECSIZE (8 * 1024) /* sets limit on records, fields, etc., etc. */
|
|
extern int recsize; /* size of current record, orig RECSIZE */
|
|
|
|
extern char EMPTY[]; /* this avoid -Wwritable-strings issues */
|
|
extern char **FS;
|
|
extern char **RS;
|
|
extern char **ORS;
|
|
extern char **OFS;
|
|
extern char **OFMT;
|
|
extern Awkfloat *NR;
|
|
extern Awkfloat *FNR;
|
|
extern Awkfloat *NF;
|
|
extern char **FILENAME;
|
|
extern char **SUBSEP;
|
|
extern Awkfloat *RSTART;
|
|
extern Awkfloat *RLENGTH;
|
|
|
|
extern char *record; /* points to $0 */
|
|
extern int lineno; /* line number in awk program */
|
|
extern int errorflag; /* 1 if error has occurred */
|
|
extern bool donefld; /* true if record broken into fields */
|
|
extern bool donerec; /* true if record is valid (no fld has changed */
|
|
extern int dbg;
|
|
|
|
extern const char *patbeg; /* beginning of pattern matched */
|
|
extern int patlen; /* length of pattern matched. set in b.c */
|
|
|
|
/* Cell: all information about a variable or constant */
|
|
|
|
typedef struct Cell {
|
|
uschar ctype; /* OCELL, OBOOL, OJUMP, etc. */
|
|
uschar csub; /* CCON, CTEMP, CFLD, etc. */
|
|
char *nval; /* name, for variables only */
|
|
char *sval; /* string value */
|
|
Awkfloat fval; /* value as number */
|
|
int tval; /* type info: STR|NUM|ARR|FCN|FLD|CON|DONTFREE|CONVC|CONVO */
|
|
char *fmt; /* CONVFMT/OFMT value used to convert from number */
|
|
struct Cell *cnext; /* ptr to next if chained */
|
|
} Cell;
|
|
|
|
typedef struct Array { /* symbol table array */
|
|
int nelem; /* elements in table right now */
|
|
int size; /* size of tab */
|
|
Cell **tab; /* hash table pointers */
|
|
} Array;
|
|
|
|
#define NSYMTAB 50 /* initial size of a symbol table */
|
|
extern Array *symtab;
|
|
|
|
extern Cell *nrloc; /* NR */
|
|
extern Cell *fnrloc; /* FNR */
|
|
extern Cell *fsloc; /* FS */
|
|
extern Cell *nfloc; /* NF */
|
|
extern Cell *ofsloc; /* OFS */
|
|
extern Cell *orsloc; /* ORS */
|
|
extern Cell *rsloc; /* RS */
|
|
extern Cell *rstartloc; /* RSTART */
|
|
extern Cell *rlengthloc; /* RLENGTH */
|
|
extern Cell *subseploc; /* SUBSEP */
|
|
extern Cell *symtabloc; /* SYMTAB */
|
|
|
|
/* Cell.tval values: */
|
|
#define NUM 01 /* number value is valid */
|
|
#define STR 02 /* string value is valid */
|
|
#define DONTFREE 04 /* string space is not freeable */
|
|
#define CON 010 /* this is a constant */
|
|
#define ARR 020 /* this is an array */
|
|
#define FCN 040 /* this is a function name */
|
|
#define FLD 0100 /* this is a field $1, $2, ... */
|
|
#define REC 0200 /* this is $0 */
|
|
#define CONVC 0400 /* string was converted from number via CONVFMT */
|
|
#define CONVO 01000 /* string was converted from number via OFMT */
|
|
|
|
|
|
/* function types */
|
|
#define FLENGTH 1
|
|
#define FSQRT 2
|
|
#define FEXP 3
|
|
#define FLOG 4
|
|
#define FINT 5
|
|
#define FSYSTEM 6
|
|
#define FRAND 7
|
|
#define FSRAND 8
|
|
#define FSIN 9
|
|
#define FCOS 10
|
|
#define FATAN 11
|
|
#define FTOUPPER 12
|
|
#define FTOLOWER 13
|
|
#define FFLUSH 14
|
|
|
|
/* Node: parse tree is made of nodes, with Cell's at bottom */
|
|
|
|
typedef struct Node {
|
|
int ntype;
|
|
struct Node *nnext;
|
|
int lineno;
|
|
int nobj;
|
|
struct Node *narg[1]; /* variable: actual size set by calling malloc */
|
|
} Node;
|
|
|
|
#define NIL ((Node *) 0)
|
|
|
|
extern Node *winner;
|
|
extern Node *nullstat;
|
|
extern Node *nullnode;
|
|
|
|
/* ctypes */
|
|
#define OCELL 1
|
|
#define OBOOL 2
|
|
#define OJUMP 3
|
|
|
|
/* Cell subtypes: csub */
|
|
#define CFREE 7
|
|
#define CCOPY 6
|
|
#define CCON 5
|
|
#define CTEMP 4
|
|
#define CNAME 3
|
|
#define CVAR 2
|
|
#define CFLD 1
|
|
#define CUNK 0
|
|
|
|
/* bool subtypes */
|
|
#define BTRUE 11
|
|
#define BFALSE 12
|
|
|
|
/* jump subtypes */
|
|
#define JEXIT 21
|
|
#define JNEXT 22
|
|
#define JBREAK 23
|
|
#define JCONT 24
|
|
#define JRET 25
|
|
#define JNEXTFILE 26
|
|
|
|
/* node types */
|
|
#define NVALUE 1
|
|
#define NSTAT 2
|
|
#define NEXPR 3
|
|
|
|
|
|
extern int pairstack[], paircnt;
|
|
|
|
#define notlegal(n) (n <= FIRSTTOKEN || n >= LASTTOKEN || proctab[n-FIRSTTOKEN] == nullproc)
|
|
#define isvalue(n) ((n)->ntype == NVALUE)
|
|
#define isexpr(n) ((n)->ntype == NEXPR)
|
|
#define isjump(n) ((n)->ctype == OJUMP)
|
|
#define isexit(n) ((n)->csub == JEXIT)
|
|
#define isbreak(n) ((n)->csub == JBREAK)
|
|
#define iscont(n) ((n)->csub == JCONT)
|
|
#define isnext(n) ((n)->csub == JNEXT || (n)->csub == JNEXTFILE)
|
|
#define isret(n) ((n)->csub == JRET)
|
|
#define isrec(n) ((n)->tval & REC)
|
|
#define isfld(n) ((n)->tval & FLD)
|
|
#define isstr(n) ((n)->tval & STR)
|
|
#define isnum(n) ((n)->tval & NUM)
|
|
#define isarr(n) ((n)->tval & ARR)
|
|
#define isfcn(n) ((n)->tval & FCN)
|
|
#define istrue(n) ((n)->csub == BTRUE)
|
|
#define istemp(n) ((n)->csub == CTEMP)
|
|
#define isargument(n) ((n)->nobj == ARG)
|
|
/* #define freeable(p) (!((p)->tval & DONTFREE)) */
|
|
#define freeable(p) ( ((p)->tval & (STR|DONTFREE)) == STR )
|
|
|
|
/* structures used by regular expression matching machinery, mostly b.c: */
|
|
|
|
#define NCHARS (256+3) /* 256 handles 8-bit chars; 128 does 7-bit */
|
|
/* watch out in match(), etc. */
|
|
#define HAT (NCHARS+2) /* matches ^ in regular expr */
|
|
#define NSTATES 32
|
|
|
|
typedef struct rrow {
|
|
long ltype; /* long avoids pointer warnings on 64-bit */
|
|
union {
|
|
int i;
|
|
Node *np;
|
|
uschar *up;
|
|
} lval; /* because Al stores a pointer in it! */
|
|
int *lfollow;
|
|
} rrow;
|
|
|
|
typedef struct fa {
|
|
unsigned int **gototab;
|
|
uschar *out;
|
|
uschar *restr;
|
|
int **posns;
|
|
int state_count;
|
|
bool anchor;
|
|
int use;
|
|
int initstat;
|
|
int curstat;
|
|
int accept;
|
|
struct rrow re[1]; /* variable: actual size set by calling malloc */
|
|
} fa;
|
|
|
|
extern int yywrap(void);
|
|
extern void setfname(Cell *);
|
|
extern int constnode(Node *);
|
|
extern char *strnode(Node *);
|
|
extern Node *notnull(Node *);
|
|
extern int yyparse(void);
|
|
|
|
extern int yylex(void);
|
|
extern void startreg(void);
|
|
extern int input(void);
|
|
extern void unput(int);
|
|
extern void unputstr(const char *);
|
|
extern int yylook(void);
|
|
extern int yyback(int *, int);
|
|
extern int yyinput(void);
|
|
|
|
extern fa *makedfa(const char *, bool);
|
|
extern fa *mkdfa(const char *, bool);
|
|
extern int makeinit(fa *, bool);
|
|
extern void penter(Node *);
|
|
extern void freetr(Node *);
|
|
extern int hexstr(const uschar **);
|
|
extern int quoted(const uschar **);
|
|
extern char *cclenter(const char *);
|
|
extern wontreturn void overflo(const char *);
|
|
extern void cfoll(fa *, Node *);
|
|
extern int first(Node *);
|
|
extern void follow(Node *);
|
|
extern int member(int, const char *);
|
|
extern int match(fa *, const char *);
|
|
extern int pmatch(fa *, const char *);
|
|
extern int nematch(fa *, const char *);
|
|
extern bool fnematch(fa *, FILE *, char **, int *, int);
|
|
extern Node *reparse(const char *);
|
|
extern Node *regexp(void);
|
|
extern Node *primary(void);
|
|
extern Node *concat(Node *);
|
|
extern Node *alt(Node *);
|
|
extern Node *unary(Node *);
|
|
extern int relex(void);
|
|
extern int cgoto(fa *, int, int);
|
|
extern void freefa(fa *);
|
|
|
|
extern int pgetc(void);
|
|
extern char *cursource(void);
|
|
|
|
extern Node *nodealloc(int);
|
|
extern Node *exptostat(Node *);
|
|
extern Node *node1(int, Node *);
|
|
extern Node *node2(int, Node *, Node *);
|
|
extern Node *node3(int, Node *, Node *, Node *);
|
|
extern Node *node4(int, Node *, Node *, Node *, Node *);
|
|
extern Node *stat3(int, Node *, Node *, Node *);
|
|
extern Node *op2(int, Node *, Node *);
|
|
extern Node *op1(int, Node *);
|
|
extern Node *stat1(int, Node *);
|
|
extern Node *op3(int, Node *, Node *, Node *);
|
|
extern Node *op4(int, Node *, Node *, Node *, Node *);
|
|
extern Node *stat2(int, Node *, Node *);
|
|
extern Node *stat4(int, Node *, Node *, Node *, Node *);
|
|
extern Node *celltonode(Cell *, int);
|
|
extern Node *rectonode(void);
|
|
extern Node *makearr(Node *);
|
|
extern Node *pa2stat(Node *, Node *, Node *);
|
|
extern Node *linkum(Node *, Node *);
|
|
extern void defn(Cell *, Node *, Node *);
|
|
extern int isarg(const char *);
|
|
extern const char *tokname(int);
|
|
extern Cell *(*proctab[])(Node **, int);
|
|
extern int ptoi(void *);
|
|
extern Node *itonp(int);
|
|
|
|
extern void syminit(void);
|
|
extern void arginit(int, char **);
|
|
extern void envinit(char **);
|
|
extern Array *makesymtab(int);
|
|
extern void freesymtab(Cell *);
|
|
extern void freeelem(Cell *, const char *);
|
|
extern Cell *setsymtab(const char *, const char *, double, unsigned int, Array *);
|
|
extern int hash(const char *, int);
|
|
extern void rehash(Array *);
|
|
extern Cell *lookup(const char *, Array *);
|
|
extern double setfval(Cell *, double);
|
|
extern void funnyvar(Cell *, const char *);
|
|
extern char *setsval(Cell *, const char *);
|
|
extern double getfval(Cell *);
|
|
extern char *getsval(Cell *);
|
|
extern char *getpssval(Cell *); /* for print */
|
|
extern char *tostring(const char *);
|
|
extern char *tostringN(const char *, size_t);
|
|
extern char *qstring(const char *, int);
|
|
extern Cell *catstr(Cell *, Cell *);
|
|
|
|
extern void recinit(unsigned int);
|
|
extern void initgetrec(void);
|
|
extern void makefields(int, int);
|
|
extern void growfldtab(int n);
|
|
extern void savefs(void);
|
|
extern int getrec(char **, int *, bool);
|
|
extern void nextfile(void);
|
|
extern int readrec(char **buf, int *bufsize, FILE *inf, bool isnew);
|
|
extern char *getargv(int);
|
|
extern void setclvar(char *);
|
|
extern void fldbld(void);
|
|
extern void cleanfld(int, int);
|
|
extern void newfld(int);
|
|
extern void setlastfld(int);
|
|
extern int refldbld(const char *, const char *);
|
|
extern void recbld(void);
|
|
extern Cell *fieldadr(int);
|
|
extern void yyerror(const char *);
|
|
extern void bracecheck(void);
|
|
extern void bcheck2(int, int, int);
|
|
extern void SYNTAX(const char *, ...)
|
|
__attribute__((__format__(__printf__, 1, 2)));
|
|
extern wontreturn void FATAL(const char *, ...)
|
|
__attribute__((__format__(__printf__, 1, 2)));
|
|
extern void WARNING(const char *, ...)
|
|
__attribute__((__format__(__printf__, 1, 2)));
|
|
extern void error(void);
|
|
extern void eprint(void);
|
|
extern void bclass(int);
|
|
extern double errcheck(double, const char *);
|
|
extern int isclvar(const char *);
|
|
extern bool is_valid_number(const char *s, bool trailing_stuff_ok,
|
|
bool *no_trailing, double *result);
|
|
#define is_number(s, val) is_valid_number(s, false, NULL, val)
|
|
|
|
extern int adjbuf(char **pb, int *sz, int min, int q, char **pbp, const char *what);
|
|
extern void run(Node *);
|
|
extern Cell *execute(Node *);
|
|
extern Cell *program(Node **, int);
|
|
extern Cell *call(Node **, int);
|
|
extern Cell *copycell(Cell *);
|
|
extern Cell *arg(Node **, int);
|
|
extern Cell *jump(Node **, int);
|
|
extern Cell *awkgetline(Node **, int);
|
|
extern Cell *getnf(Node **, int);
|
|
extern Cell *array(Node **, int);
|
|
extern Cell *awkdelete(Node **, int);
|
|
extern Cell *intest(Node **, int);
|
|
extern Cell *matchop(Node **, int);
|
|
extern Cell *boolop(Node **, int);
|
|
extern Cell *relop(Node **, int);
|
|
extern void tfree(Cell *);
|
|
extern Cell *gettemp(void);
|
|
extern Cell *field(Node **, int);
|
|
extern Cell *indirect(Node **, int);
|
|
extern Cell *substr(Node **, int);
|
|
extern Cell *sindex(Node **, int);
|
|
extern int format(char **, int *, const char *, Node *);
|
|
extern Cell *awksprintf(Node **, int);
|
|
extern Cell *awkprintf(Node **, int);
|
|
extern Cell *arith(Node **, int);
|
|
extern double ipow(double, int);
|
|
extern Cell *incrdecr(Node **, int);
|
|
extern Cell *assign(Node **, int);
|
|
extern Cell *cat(Node **, int);
|
|
extern Cell *pastat(Node **, int);
|
|
extern Cell *dopa2(Node **, int);
|
|
extern Cell *split(Node **, int);
|
|
extern Cell *condexpr(Node **, int);
|
|
extern Cell *ifstat(Node **, int);
|
|
extern Cell *whilestat(Node **, int);
|
|
extern Cell *dostat(Node **, int);
|
|
extern Cell *forstat(Node **, int);
|
|
extern Cell *instat(Node **, int);
|
|
extern Cell *bltin(Node **, int);
|
|
extern Cell *printstat(Node **, int);
|
|
extern Cell *nullproc(Node **, int);
|
|
extern FILE *redirect(int, Node *);
|
|
extern FILE *openfile(int, const char *, bool *);
|
|
extern const char *filename(FILE *);
|
|
extern Cell *closefile(Node **, int);
|
|
extern void closeall(void);
|
|
extern Cell *sub(Node **, int);
|
|
extern Cell *gsub(Node **, int);
|
|
|
|
extern const char *flags2str(int flags);
|
|
|
|
COSMOPOLITAN_C_END_
|
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
#endif /* COSMOPOLITAN_THIRD_PARTY_AWK_AWK_H_ */
|