+++ /dev/null
-# Makefile for awk.
-
-CC = exec cc
-CFLAGS = -D_MINIX -D_POSIX_SOURCE -wo -w
-LDFLAGS = -i -f
-
-OBJS = m.o e.o n.o l.o r.o v.o y.o regexp.o k.o
-
-all: awk.old
-
-awk.old: $(OBJS)
- $(CC) $(LDFLAGS) -o $@ $(OBJS) #-lm
- install -S 32kw $@
-
-install: /usr/bin/awk.old
-
-/usr/bin/awk.old: awk.old
- install -cs -o bin $? $@
-
-clean:
- rm -f awk awk.old *.o a.out *.bak core
-
-e.o: awk.h regexp.h
-l.o: awk.h
-m.o: awk.h
-n.o: awk.h
-r.o: awk.h regexp.h
-regexp.o: regexp.h
-v.o: awk.h regexp.h
-y.o: awk.h
+++ /dev/null
-A small AWK clone for the 16-bit Minix
-
- We have written this program for the Minix 1.2 to fit into 64K+64K
-memory. When compiling this program, you need the Peter S. Housel's
-Floating Math Package with corrected the atan() function. Original atan()
-function has incorrect argument sequence.
-
- This program supports Japanese Shift-JIS KANJI code and passes
-all the test program of the "AWK programming language" written by original
-AWK authors except some programs relied upon the way of regular expression
-evaluation.
-
-Kouichi Hirabayashi (kh@mogami-wire.co.jp)
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-/* lexical/parser tokens and executable statements */
-
-#define FIRSTP 256
-#define ARG 256
-#define ARITH 257
-#define ARRAY 258
-#define ASSIGN 259
-#define CALL 260
-#define CAT 261
-#define COND 262
-#define DELETE 263
-#define DO 264
-#define ELEMENT 265
-#define FIELD 266
-#define FOR 267
-#define FORIN 268
-#define GETLINE 269
-#define IF 270
-#define IN 271
-#define JUMP 272
-#define MATHFUN 273
-#define NULPROC 274
-#define P1STAT 275
-#define P2STAT 276
-#define PRINT 277
-#define PRINT0 278
-#define STRFUN 279
-#define SUBST 280
-#define USRFUN 281
-#define WHILE 282
-#define LASTP 282
- /* lexical token */
-
-#define ADD 300 /* + */
-#define ADDEQ 301 /* += */
-#define AND 302 /* && */
-#define BEGIN 303 /* BEGIN */
-#define BINAND 304 /* & */
-#define BINOR 305 /* | */
-#define BREAK 306 /* break */
-#define CLOSE 307 /* close */
-#define CONTIN 308 /* continue */
-#define DEC 309 /* -- */
-#define DIV 310 /* / */
-#define DIVEQ 311 /* /= */
-#define ELSE 312 /* else */
-#define END 313 /* END */
-#define EOL 314 /* ; or '\n' */
-#define EQ 315 /* == */
-#define EXIT 316 /* exit */
-#define FUNC 317 /* function */
-#define GE 318 /* >= */
-#define GT 319 /* > */
-#define IDENT 320 /* identifier */
-#define INC 321 /* ++ */
-#define LE 322 /* <= */
-#define LT 323 /* < */
-#define MATCH 324 /* ~ */
-#define MOD 325 /* % */
-#define MODEQ 326 /* %= */
-#define MULT 327 /* * */
-#define MULTEQ 328 /* *= */
-#define NE 329 /* != */
-#define NEXT 330 /* next */
-#define NOMATCH 331 /* !~ */
-#define NOT 332 /* ! */
-#define NUMBER 333 /* integer or floating number */
-#define OR 334 /* || */
-#define POWEQ 335 /* ^= */
-#define POWER 336 /* ^ */
-#define PRINTF 337 /* printf */
-#define REGEXP 338 /* /REG/ */
-#define RETURN 339 /* return */
-#define SHIFTL 340 /* << */
-#define SHIFTR 341 /* >> */
-#define SPRINT 342 /* sprint */
-#define SPRINTF 343 /* sprintf */
-#define STRING 344 /* ".." */
-#define SUB 345 /* - */
-#define SUBEQ 346 /* -= */
-#define SYSTEM 347 /* system */
-#define UMINUS 348 /* - */
-
-/* tokens in parser */
-
-#define VALUE 400 /* value node */
-#define INCDEC 401 /* ++, -- */
-#define PRE 402 /* pre incre/decre */
-#define POST 403 /* post incre/decre */
-
-/* redirect in print(f) statement */
-
-#define R_OUT 410 /* > */
-#define R_APD 411 /* >> */
-#define R_PIPE 412 /* | */
-#define R_IN 413 /* < */
-#define R_PIN 414 /* | getline */
-#define R_POUT 415 /* print | */
-
-/* function */
-
-#define ATAN2 500 /* atan2 */
-#define COS 501 /* cos */
-#define EXP 502 /* exp */
-#define INDEX 503 /* index */
-#define INT 504 /* int */
-#define LENGTH 505 /* length */
-#define LOG 506 /* log */
-#define RAND 507 /* rand */
-#define RGSUB 508 /* gsub */
-#define RMATCH 509 /* match */
-#define RSUB 510 /* sub */
-#define SIN 511 /* sin */
-#define SPLIT 512 /* split */
-#define SQRT 513 /* sqrt */
-#define SRAND 514 /* srand */
-#define SUBSTR 515 /* substr */
-
-/* print(f) options */
-
-#define FORMAT 1024 /* PRINTF, SPRINTF */
-#define STROUT 2048 /* SPRINTF */
-#define PRMASK 0x3ff /* ~(FORMAT|STROUT) */
-
- /* node - used in parsed tree */
-
-struct node {
- int n_type; /* node type */
- struct node *n_next; /* pointer to next node */
- struct node *n_arg[1]; /* argument (variable length) */
-};
-
-typedef struct node NODE;
-
- /* object cell */
-
-struct cell {
- int c_type; /* cell type */
- char *c_sval; /* string value */
- double c_fval; /* floating value */
-};
-
-typedef struct cell CELL;
-
- /* cell type */
-
-#define UDF 0 /* pass parameter */
-#define VAR 1 /* variable */
-#define NUM 2 /* number */
-#define ARR 4 /* array */
-#define STR 8 /* string */
-#define REC 16 /* record */
-#define FLD 32 /* filed */
-#define PAT 64 /* pattern (compiled REGEXPR) */
-#define BRK 128 /* break */
-#define CNT 256 /* continue */
-#define NXT 512 /* next */
-#define EXT 1024 /* exit */
-#define RTN 2048 /* return */
-#define TMP 4096 /* temp cell */
-#define POS 8192 /* argument position */
-#define FUN 16384 /* function */
-
- /* symbol cell - linked to symbol table */
-
-struct symbol {
- char *s_name;
- CELL *s_val;
- struct symbol *s_next;
-};
-
-typedef struct symbol SYMBOL;
+++ /dev/null
-#!/bin/sh
-make clean
-make && make install
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-#include <ctype.h>
-#include "awk.h"
-#include "regexp.h"
-
-extern char **FS, **OFS, **ORS, **OFMT;
-extern double *RSTART, *RLENGTH;
-extern char record[];
-extern CELL *field[];
-
-extern int r_start, r_length;
-
-double getfval(), atof();
-char *strsave(), *getsval(), *strcat(), *strstr();
-CELL *mkcell(), *mktmp();
-CELL *Field(), *Split(), *Forin();
-CELL *Arith(), *Assign(), *Stat(), *Mathfun(), *Strfun(), *Cond();
-CELL *Print(), *Cat(), *Array(), *Element();
-CELL *If(), *While(), *For(), *Do(), *Jump();
-CELL *P1stat(), *P2stat(), *Print0();
-CELL *Arg(), *Call(), *Ret();
-CELL *Subst(), *In(), *Getline(), *Delete(), *Close();
-CELL *Nulproc(), *Usrfun();
-CELL *_Arg();
-
-FILE *getfp(); /* r.c */
-
-CELL truecell = { NUM, NULL, 1.0 };
-CELL falsecell = { NUM, NULL, 0.0 };
-static CELL breakcell = { BRK, NULL, 0.0 };
-static CELL contcell = { CNT, NULL, 0.0 };
-static CELL nextcell = { NXT, NULL, 0.0 };
-static CELL retcell = { RTN, NULL, 0.0 };
-
-static CELL *retval; /* function return value */
-
-int pateval; /* used in P1STAT & P2STAT */
-static char *r_str; /* STR in 'str ~ STR */
-static regexp *r_pat; /* compiled pattern for STR */
-
-CELL *(*proctab[])() = {
- Arg, Arith, Array, Assign, Call, Cat, Cond, Delete, Do, Element,
- Field, For, Forin, Getline, If, In, Jump, Mathfun, Nulproc, P1stat,
- P2stat, Print, Print0, Strfun, Subst, Usrfun, While
-};
-
-CELL *
-execute(p) NODE *p;
-{
- int type, i;
- CELL *r, *(*proc)();
-
- type = p->n_type;
- if (type == VALUE) {
- if ((r = (CELL *) p->n_arg[0])->c_type & PAT && pateval) {
- i = match(r->c_sval, (char *)record) ? 1 : 0;
- r = mktmp(NUM, NULL, (double) i);
- }
- return r;
- }
- for ( ; p != NULL; p = p->n_next) {
-#if 0
- if (p->n_type == VALUE) continue; /* neglect */
-#endif
-/*
- switch ((int) p->n_type) {
- case ARRAY:
- r = Array(p);
- break;
- case ARITH:
- r = Arith(p);
- break;
- case ASSIGN:
- r = Assign(p);
- break;
- case PRINT:
- r = Print(p);
- break;
- case PRINT0:
- r = Print0(p);
- break;
- case CAT:
- r = Cat(p);
- break;
- case MATHFUN:
- r = Mathfun(p);
- break;
- case STRFUN:
- r = Strfun(p);
- break;
- case COND:
- r = Cond(p);
- break;
- case IF:
- r = If(p);
- break;
- case P1STAT:
- r = P1stat(p);
- break;
- case P2STAT:
- r = P2stat(p);
- break;
- case WHILE:
- r = While(p);
- break;
- case DO:
- r = Do(p);
- break;
- case FOR:
- r = For(p);
- break;
- case FORIN:
- r = Forin(p);
- break;
- case FIELD:
- r = Field(p);
- break;
- case JUMP:
- r = Jump(p);
- break;
- case ARG:
- r = Arg(p);
- break;
- case CALL:
- r = Call(p);
- break;
- case SUBST:
- r = Subst(p);
- break;
- case ELEMENT:
- r = Element(p);
- break;
- case IN:
- r = In(p);
- break;
- case GETLINE:
- r = Getline(p);
- break;
- case DELETE:
- r = Delete(p);
- break;
- case NULPROC:
- r = &truecell;
- break;
- default:
- printf("PROGRAM ERROR ? ILLEGAL NODE TYPE(%d)\n", type);
- exit(1);
- break;
- }
-*/
- i = (int) p->n_type;
- if (i < FIRSTP || i > LASTP)
- error("ILLEGAL PROC (%d)", i);
- proc = proctab[i - FIRSTP];
- r = (*proc)(p);
- if (r->c_type & (BRK|CNT|NXT|RTN))
- return r;
- if (p->n_next != NULL)
- c_free(r);
-#ifdef DOS
- kbhit(); /* needs in MS-DOS */
-#endif
- }
- return r;
-}
-
-static CELL *
-Arith(p) NODE *p;
-{
- int op;
- CELL *r, *u, *v, *execute();
- double x, y, fmod(), pow();
-
- op = (int) p->n_arg[0];
- if (op == UMINUS) {
- u = execute(p->n_arg[1]);
- x = - getfval(u);
- }
- else if (op == INCDEC) {
- u = execute(p->n_arg[1]);
- x = getfval(u);
- setfval(u, x + (int) p->n_arg[2]);
- if ((int) p->n_arg[3] == PRE)
- return u;
- /* return dummy */
- }
- else {
- u = execute(p->n_arg[1]);
- v = execute(p->n_arg[2]);
- x = getfval(u);
- y = getfval(v);
- if (op == DIV || op == MOD) {
- if (y == 0.0)
- fprintf(stderr, "divid by 0\n");
- }
- switch (op) {
- case SUB: x -= y;break;
- case ADD: x += y; break;
- case MULT: x *= y; break;
- case DIV:
- if (y == 0.0)
- error("division by zero in \"/\"", (char *)0);
- x /= y; break;
- case MOD:
- if (y == 0.0)
- error("division by zero in \"%%\"", (char *)0);
- x = fmod(x, y); break;
- case POWER: x = pow(x, y); break;
- default: printf("UNSUPPORTED ARITH OPERATOR !\n"); break;
- }
- c_free(v);
- }
- c_free(u);
- r = mktmp(NUM, NULL, x);
- return r;
-}
-
-static CELL *
-Assign(p) NODE *p;
-{
- CELL *u, *v, *execute();
- int op;
- double x, y, fmod(), pow();
-
- op = (int) p->n_arg[0];
- u = execute(p->n_arg[1]);
-
-#if 0
- if (u->c_type == UDF) /* fix up local var */
- u->c_type |= VAR|STR;
-#endif
- if (!(u->c_type & (VAR|FLD|REC)) && (u->c_type != UDF))
- fprintf(stderr, "ASSIGN TO NON VARIABLE (%d)\n", u->c_type);
- v = execute(p->n_arg[2]);
-
- if (u == v)
- goto rtn; /* same node */
-
- if (op == ASSIGN) {
- if (v->c_type & NUM/* || isnum(v->c_sval)*/)
- setfval(u, getfval(v));
- else
- setsval(u, getsval(v));
- }
- else {
- x = getfval(u);
- y = getfval(v);
- switch (op) {
- case ADDEQ: x += y; break;
- case SUBEQ: x -= y; break;
- case MULTEQ: x *= y; break;
- case DIVEQ:
- if (y == 0.0)
- error("division by zero in \"/=\"", (char *)0);
- x /= y; break;
- case MODEQ:
- if (y == 0.0)
- error("division by zero in \"%=\"", (char *)0);
- x = fmod(x, y); break;
- case POWEQ: x = pow(x, y); break;
- default:
- synerr("illegal assign op (%d)", op);
- break;
- }
- setfval(u, x);
- }
-rtn:
- c_free(v);
- return u;
-}
-
-static CELL *
-Cat(p) NODE *p;
-{
- CELL *u;
- char *s, *t, str[BUFSIZ];
-
- u = execute(p->n_arg[0]);
- s = getsval(u);
- for (t = str; *s; )
- *t++ = *s++;
- c_free(u);
- u = execute(p->n_arg[1]);
- s = getsval(u);
- while (*s)
- *t++ = *s++;
- c_free(u);
- *t = '\0';
- return mktmp(STR, str, 0.0);
-}
-
-static CELL *
-Print(p) NODE *p;
-{
- register int i, redir, typ;
- CELL *u;
- char *s, str[BUFSIZ];
- char *file;
- FILE *fp;
-
- redir = (int) p->n_arg[0];
- if (typ = redir & PRMASK) { /* redirect */
- u = execute(p->n_arg[1]);
- file = getsval(u);
- if (typ == R_PIPE)
- typ = R_POUT;
- fp = getfp(file, typ);
- c_free(u);
- }
- else
- fp = stdout;
- if (redir & FORMAT) /* format */
- format(str, p);
- else {
- *str = '\0';
- for (i = 2; p->n_arg[i] != NULL; i++) {
- if (i > 2)
- strcat(str, *OFS);
- u = execute(p->n_arg[i]);
- s = getsval(u);
- strcat(str, s);
- c_free(u);
- }
- strcat(str, *ORS);
- }
- if (redir & STROUT) /* sprintf */
- return mktmp(STR, str, 0.0);
- fputs(str, fp);
- fflush(fp);
- return &truecell;
-}
-
-static CELL *
-Mathfun(p) NODE *p;
-{
- CELL *u, *v;
- double x, y;
- double atan2(), cos(), exp(), log(), sin(), sqrt(), modf();
-
- if ((int) p->n_arg[1] == 0) {
- u = NULL;
- x = 0.0;
- }
- else {
- u = execute(p->n_arg[2]);
- x = getfval(u);
- }
- switch ((int) p->n_arg[0]) {
- case ATAN2:
- if ((int) p->n_arg[1] == 2) {
- v = execute(p->n_arg[3]);
- y = getfval(v);
- x = atan2(x, y);
- c_free(v);
- }
- else
- x = 0.0;
- break;
- case COS: x = cos(x); break;
- case EXP: x = exp(x); break;
- case INT: y = modf(x, &x); break;
- case LOG: x = log(x); break;
- case SIN: x = sin(x); break;
- case SQRT: x = sqrt(x); break;
- case RAND: x = (double) rand() / 32768.0; break;
- case SRAND: if (x == 0.0)
- x = (double) time(0);
- x = (double) srand((int) x);
- break;
- default:
- fprintf(stderr, "unknown math function (%d)\n", p->n_arg[2]);
- break;
- }
- if (u != NULL)
- c_free(u);
- return mktmp(NUM, NULL, x);
-}
-
-static CELL *
-Strfun(p) NODE *p;
-{
- CELL *u, *v, *r;
- char *s, *t, str[BUFSIZ];
- int i, m, n;
- double x;
- regexp *pat, *getpat();
-
- n = (int) p->n_arg[1];
- if (n > 0 && (int) p->n_arg[0] != SPLIT) {
- u = execute(p->n_arg[2]);
- s = getsval(u);
- }
- else {
- s = "";
- u = NULL;
- }
- switch ((int) p->n_arg[0]) {
- case INDEX:
- if (n > 1) {
- v = execute(p->n_arg[3]);
- t = getsval(v);
- i = Index(s, t);
- c_free(v);
- }
- else
- i = 0;
- r = mktmp(NUM, NULL, (double) i);
- break;
- case LENGTH:
- i = (n > 0) ? jstrlen(s) : jstrlen(record);
- r = mktmp(NUM, NULL, (double) i);
- break;
- case SPLIT:
- r = Split(p);
- break;
- case SUBSTR:
- if (n > 1) {
- v = execute(p->n_arg[3]);
- m = (int) getfval(v) - 1;
- c_free(v);
- }
- else
- m = 0;
- if (n > 2) {
- v = execute(p->n_arg[4]);
- n = (int) getfval(v);
- c_free(v);
- }
- else
- n = jstrlen(s) - m;
- for (t = str; *s && m-- > 0; s++)
- if (isKanji(*s))
- s++;
- while (*s && n-- > 0) {
- if (isKanji(*s))
- *t++ = *s++;
- *t++ = *s++;
- }
- *t = '\0';
- r = mktmp(STR, str, 0.0);
- break;
- case RMATCH:
- if (n > 1) {
- v = execute(p->n_arg[3]);
- pat = getpat(v);
- match(pat, s);
- c_free(v);
- if (r_start) { /* change only if match */
- *RSTART = (double) r_start;
- *RLENGTH = (double) r_length;
- }
- r = mktmp(NUM, NULL, (double) r_start);
- }
- else
- error("missing regexpr in match(str, regexpr)");
- break;
- case CLOSE:
- r = Close(s);
- break;
- case SYSTEM:
- r = mktmp(NUM, NULL, system(s) == -1 ? 0.0 : 1.0);
- break;
- default:
- fprintf(stderr, "unknown string function");
- break;
- }
- c_free(u);
- return r;
-}
-
-static regexp *
-getpat(r) CELL *r;
-{
- regexp *pat, *mkpat();
-
- if (r->c_type & PAT)
- pat = (regexp *) r->c_sval;
- else {
- if (r_str && strcmp(r_str, r->c_sval) == 0)
- pat = r_pat;
- else {
- sfree(r_str); sfree(r_pat);
- r_str = strsave(getsval(r));
- pat = r_pat = mkpat(r_str);
- }
- }
- return pat;
-}
-
-static CELL *
-Subst(p) NODE *p;
-{
- CELL *u, *v, *w;
- char *s, *t, *r, str[BUFSIZ], *strcpy();
- int i, n;
-
- n = (int) p->n_arg[1];
- if (n > 1) {
- u = execute(p->n_arg[3]); /* substitute string */
- s = getsval(u);
- v = execute(p->n_arg[2]); /* expr */
- if (n > 2) {
- w = execute(p->n_arg[4]);
- t = getsval(w);
- r = str;
- }
- else {
- t = r = record;
- w = NULL;
- }
- i = (int) p->n_arg[0] == RGSUB ? 0 : 1;
- if (v->c_type & (PAT|STR))
- i = Sub(r, v->c_sval, (v->c_type & STR), s, t, i);
- else
- error("[g]sub(PAT, .. ) must be /../ or string (%d)",
- w->c_type);
- if (n > 2) {
- if (w->c_type & REC) {
- strcpy(record, str);
- mkfld(record, *FS, field);
- }
- else
- setsval(w, str);
- }
- else
- mkfld(record, *FS, field);
- c_free(u);
- c_free(v);
- c_free(w);
- }
- else
- i = 0;
- return mktmp(NUM, NULL, (double) i);
-}
-
-static CELL *
-Cond(p) NODE *p;
-{
- CELL *u, *v;
- double x, y;
- int op, i, j;
- char *s;
- int save = pateval;
-
- op = (int) p->n_arg[0];
- u = execute(p->n_arg[1]);
- x = getfval(u);
-/*
-printf("Cond(%d)(%s)\n", u->c_type, u->c_sval);
-*/
- if (op == AND || op == OR || op == NOT) {
- if (u->c_type & NUM)
- i = (x != 0.0);
- else {
- s = getsval(u);
- i = (s != (char *)NULL) && (*s != '\0');
- }
- }
- if (op == AND && !i) {
- c_free(u);
- return &falsecell;
- }
- if (op == OR && i) {
- c_free(u);
- return &truecell;
- }
- if (op == NOT)
- i = i == 0 ? 1 : 0;
- else {
- if (op == MATCH || op == NOMATCH)
- pateval = 0;
- v = execute(p->n_arg[2]);
- y = getfval(v);
- if (op == AND || op == OR || op == BINAND || op == BINOR) {
- if (v->c_type & NUM)
- j = (y != 0.0);
- else {
- s = getsval(v);
- j = (s != (char *)NULL) && (*s != '\0');
- }
- switch (op) {
- case AND: i = i && j; break;
- case OR: i = i || j; break;
- case BINAND: i = i & j; break;
- case BINOR: i = i | j; break;
- }
- }
- else if (op == MATCH || op == NOMATCH) {
- char *s;
- regexp *pat, *getpat();
-
- s = getsval(u);
- pat = getpat(v);
- i = match(pat, s) == 0 ? 0 : 1;
- if (op == NOMATCH)
- i = i == 0 ? 1 : 0;
- }
- else { /* relative operator */
-/*
-printf("Cond(%d)(%d)(%s)(%s)\n", u->c_type, v->c_type, u->c_sval, v->c_sval);
-*/
- if ((u->c_type & NUM) && (v->c_type & NUM))
- i = x < y ? -1 : (x > y ? 1 : 0);
- else
- i = strcmp(getsval(u), getsval(v));
-/*
-printf("Cond(%d)(%d)(%g)(%g)(%d)\n", u->c_type, v->c_type, x, y, i);
-*/
-
- switch (op) {
- case LT: i = i < 0 ? 1 : 0; break;
- case LE: i = i <= 0 ? 1 : 0; break;
- case EQ: i = i == 0 ? 1 : 0; break;
- case NE: i = i != 0 ? 1 : 0; break;
- case GT: i = i > 0 ? 1 : 0; break;
- case GE: i = i >= 0 ? 1 : 0; break;
- default:
- fprintf(stderr, "unknown relative operator (%d)\n", op);
- break;
- }
- }
- c_free(v);
- }
- c_free(u);
- pateval = save;
- return mktmp(NUM, NULL, (double) i);
-}
-
-static CELL *
-If(p) NODE *p;
-{
- CELL *u;
- int i;
- char *s;
-
- u = execute(p->n_arg[0]);
- if (u->c_type & NUM)
- i = (getfval(u) != 0.0);
- else {
- s = getsval(u);
- i = (s != (char *)NULL) && (*s != '\0');
- }
- c_free(u);
- if (i)
- u = execute(p->n_arg[1]);
- else if (p->n_arg[2])
- u = execute(p->n_arg[2]);
- else
- u = &truecell;
- return u;
-}
-
-static CELL *
-While(p) NODE *p;
-{
- CELL *u;
- double x;
-
- for (;;) {
- u = execute(p->n_arg[0]);
- x = getfval(u);
- if (x == 0.0)
- break;
- c_free(u);
- u = execute(p->n_arg[1]);
- switch (u->c_type) {
- case BRK:
- goto rtn;
- case NXT: case EXT: case RTN:
- return u;
- }
- c_free(u);
- }
-rtn:
- c_free(u);
- return &truecell;
-}
-
-static CELL *
-Do(p) NODE *p;
-{
- CELL *u;
- double x;
-
- for (;;) {
- u = execute(p->n_arg[0]);
- switch (u->c_type) {
- case BRK:
- goto rtn;
- case NXT: case EXT: case RTN:
- return u;
- }
- c_free(u);
- u = execute(p->n_arg[1]);
- if(getfval(u) == 0.0)
- break;
- c_free(u);
- }
-rtn:
- c_free(u);
- return &truecell;
-}
-
-static CELL *
-For(p) NODE *p;
-{
- CELL *u;
- double x;
-
- if (p->n_arg[0] != NULL) {
- u = execute(p->n_arg[0]);
- c_free(u);
- }
- for (;;) {
- if (p->n_arg[1] != NULL) {
- u = execute(p->n_arg[1]);
- x = getfval(u);
- c_free(u);
- if (x == 0.0)
- break;
- }
- u = execute(p->n_arg[3]);
- switch (u->c_type) {
- case BRK:
- c_free(u);
- goto rtn;
- case NXT: case EXT: case RTN:
- return u;
- }
- if (p->n_arg[2] != NULL) {
- u = execute(p->n_arg[2]);
- c_free(u);
- }
- }
-rtn:
- return &truecell;
-}
-
-static CELL *
-Jump(p) NODE *p;
-{
- CELL *u;
- int i;
-
- switch ((int) p->n_arg[0]) {
- case BREAK: u = &breakcell; break;
- case CONTIN: u = &contcell; break;
- case EXIT:
- if ((int) p->n_arg[1]) {
- u = execute(p->n_arg[1]);
- i = (int) getfval(u);
- }
- else
- i = 0;
- closeall();
- exit(i);
- case RETURN:
- Return(p);
- u = &retcell;
- break;
- case NEXT: u = &nextcell; break;
- }
- return u;
-}
-
-static
-Return(p) NODE *p;
-{
- CELL *u;
- int i;
- char *s, str[BUFSIZ];
-
- c_free(retval);
- if (p->n_arg[1] != NULL) {
- if (p->n_arg[2] == NULL) {
-/*
-if (0) {
-*/
- u = execute(p->n_arg[1]);
- if (u->c_type == UDF)
- retval = mktmp(STR, "", 0.0);
- else
- retval = mktmp(u->c_type, u->c_sval, u->c_fval);
- c_free(u);
- }
- else {
- for (i = 1; p->n_arg[i] != NULL; i++) {
- if (i == 1)
- *str = '\0';
- else
- strcat(str, *OFS);
- u = execute(p->n_arg[i]);
- s = getsval(u);
- strcat(str, s);
- c_free(u);
- }
-/*
-printf("Ret(%s)(%d)\n", str, isnum(str));
-*/
- if (isnum(str))
- retval = mktmp(STR|NUM, str, atof(str));
- else
- retval = mktmp(STR, str, 0.0);
- }
- }
- else
- retval = &truecell;
-}
-
-#define MAXFRAME 100
-CELL **frame[MAXFRAME];
-static int framep;
-
-static CELL *
-Arg(p) NODE *p;
-{
- CELL *u;
- int i;
-
- u = (CELL *)p->n_arg[0];
- return _Arg((int)u->c_fval);
-}
-
-CELL *
-_Arg(i)
-{
-/*
-printf("Arg(%d)\n", i);
-*/
- return frame[framep - 1][i];
-}
-
-static CELL *
-Call(p) NODE *p;
-{
- CELL *u, *v, *r, **arg;
- NODE *q;
- int i, j, k, n;
- char *emalloc();
-
- if (framep >= MAXFRAME - 2)
- error("stack frame overflow", (char *)0);
- retval = &truecell;
- r = (CELL *) p->n_arg[0];
- if (r->c_type != FUN)
- synerr("called function is not declared", (char *)0);
- n = (int) r->c_fval; /* # of params */
- if (n > 0) {
- arg = (CELL **) emalloc(sizeof(u) * n);
- for (i = 2, j = 0, k = (int) p->n_arg[1]; j < k; i++) {
- u = execute(p->n_arg[i]);
-/*
-printf("pass, j(%d)typ(%d)\n", j, u->c_type);
-*/
- if (u->c_type & ARR)
- v = u; /* pass by reference */
- else { /* pass by value */
- v = mkcell(UDF, u->c_sval, u->c_fval);
- if (u->c_type != UDF) {
-#if 0
- v->c_type = u->c_type;
- if (v->c_type & (NUM|STR))
- v->c_type |= VAR;
- v->c_type &= ~TMP; /* dont't free */
-#else
- v->c_type |= (u->c_type & (NUM|STR))|VAR;
- /*v->c_type &= ~TMP;*/
-#endif
- /* Don't free original */
- }
-/*
-printf("pass1, j(%d)typ(%d)\n", j, v->c_type);
-*/
- }
- arg[j++] = v;
- }
- for ( ; j < n; ) /* local var */
- arg[j++] = mkcell(UDF, NULL, 0.0);
- }
- else
- arg = NULL;
-
- frame[framep] = arg;
- framep++;
-
- r = execute(r->c_sval);
- c_free(r);
- framep--;
- if (n > 0) {
- for (j = n - 1 ; j > k; j--) { /* local var */
- u = arg[j];
- if (u->c_type & ARR)
- a_free(u);
- else
- c_free(u);
- }
- for ( ; j >= 0; j--) {
- u = arg[j];
- if (!(u->c_type & ARR)) {
-/* c_free(u);*/
- sfree(u->c_sval);
- sfree(u);
- }
- else {
- v = execute(p->n_arg[j + 2]);
- if (v->c_type == UDF) { /* copy back */
-/*
-printf("copy_back_UDF(%d)(%d)\n", j, u->c_type);
-*/
- v->c_type = u->c_type;
- sfree(v->c_sval);
- v->c_sval = u->c_sval;
- v->c_fval = u->c_fval;
- sfree(u);
- }
- }
- }
- }
- sfree(arg);
-/* return retval;*/
- u = mktmp(retval->c_type, retval->c_sval, retval->c_fval);
- return u;
-}
-
-CELL *Nulproc()
-{
- return &truecell;
-}
-
-CELL *
-Usrfun(p) NODE *p;
-{
- CELL *u;
-
- u = execute(p);
- return u;
-}
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-
-isKanji(c)
-{
- c &= 0xff;
- return (c > 0x80 && c < 0xa0 || c > 0xdf && c < 0xfd);
-}
-
-jstrlen(s) char *s;
-{
- int i;
-
- for (i = 0; *s; i++, s++)
- if (isKanji(*s))
- s++;
- return i;
-}
-
-char *
-jStrchr(s, c) char *s;
-{
- for ( ; *s; s++)
- if (isKanji(*s))
- s++;
- else if (*s == c)
- return s;
- return NULL;
-}
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-#include <ctype.h>
-#include "awk.h"
-
-extern char *srcprg; /* inline program */
-extern FILE *pfp; /* program file */
-
-int sym; /* lexical token */
-int sym1; /* auxiliary lexical token */
-int regexflg; /* set by parser (y.c) to indicate parsing REGEXPR */
-int funflg; /* set by parser (y.c) to indicate parsing FUNCTION */
-int printflg; /* set by parser (y.c) to indicate parsing PRINT */
-int getlineflg; /* set by parser (y.c) to indicate parsing GETLINE */
-char text[BUFSIZ]; /* lexical word */
-char line[BUFSIZ]; /* program line for error message (ring buffer) */
-char *linep = line; /* line pointer */
-char funnam[128]; /* function name for error message */
-int lineno = 1;
-
-lex()
-{
- int c, d;
- char *s;
-
- if (regexflg)
- return sym = scanreg();
-next:
- while ((c = Getc()) == ' ' || c == '\t')
- ;
- while (c == '#')
- for (c = Getc(); c != '\n'; c = Getc())
- ;
- switch (c) {
- case '\\':
- if ((c = Getc()) == '\n') {
- lineno++;
- goto next;
- }
- break;
- case '\n':
- lineno++;
- break;
- }
- switch (c) {
- case EOF: return sym = 0;
- case '+': return sym = follow2('=', '+', ADDEQ, INC, ADD);
- case '-': return sym = follow2('=', '-', SUBEQ, DEC, SUB);
- case '*': return sym = follow('=', MULTEQ, MULT);
- case '/': return sym = follow('=', DIVEQ, DIV);
- case '%': return sym = follow('=', MODEQ, MOD);
- case '^': return sym = follow('=', POWEQ, POWER);
- case '=': return sym = follow('=', EQ, ASSIGN);
- case '!': return sym = follow2('=', '~', NE, NOMATCH, NOT);
- case '&': return sym = follow('&', AND, BINAND);
- case '|': sym = follow('|', OR, BINOR);
- if (printflg && sym == BINOR)
- sym = R_POUT;
- return sym;
- case '<': sym = follow2('=', '<', LE, SHIFTL, LT);
- if (getlineflg && sym == LT)
- sym = R_IN;
- return sym;
- case '>': sym = follow2('=', '>', GE, SHIFTR, GT);
- if (printflg) {
- switch (sym) {
- case GT: sym = R_OUT; break;
- case SHIFTR: sym = R_APD; break;
- }
- }
- return sym;
- case '~': return sym = MATCH; break;
- case ';': case '\n': return sym = EOL;
- }
- if (isalpha(c) || c == '_') {
- for (s = text; isalnum(c) || c == '_'; ) {
- *s++ = c; c = Getc();
- }
- Ungetc(c);
- *s = '\0';
- if ((d = iskeywd(text)) == 0 &&
- (d = isbuiltin(text, &sym1)) == 0) {
- if (c == '(')
- return sym = CALL;
- else if (funflg) {
- if ((sym1 = isarg(text)) != -1)
- return sym = ARG;
- }
- }
- return sym = d ? d : IDENT;
- }
- else if (c == '.' || (isdigit(c))) {
- Ungetc(c);
- return sym = scannum(text); /* NUMBER */
- }
- else if (c == '"')
- return sym = scanstr(text); /* STRING */
- return sym = c;
-}
-
-static
-follow(c1, r1, r2)
-{
- register int c;
-
- if ((c = Getc()) == c1)
- return r1;
- else {
- Ungetc(c);
- return r2;
- }
-}
-
-static
-follow2(c1, c2, r1, r2, r3)
-{
- register int c;
-
- if ((c = Getc()) == c1)
- return r1;
- else if (c == c2)
- return r2;
- else {
- Ungetc(c);
- return r3;
- }
-}
-
-static
-iskeywd(s) char *s;
-{
- static struct { char *kw; int token; } tab[] = {
- "BEGIN", BEGIN,
- "END", END,
- "break", BREAK,
- "continue", CONTIN,
- "delete", DELETE,
- "do", DO,
- "else", ELSE,
- "exit", EXIT,
- "for", FOR,
- "func", FUNC,
- "function", FUNC,
- "getline", GETLINE,
- "if", IF,
- "in", IN,
- "next", NEXT,
- "print", PRINT,
- "printf", PRINTF,
- "return", RETURN,
- "sprint", SPRINT,
- "sprintf", SPRINTF,
- "while", WHILE,
- "", 0, 0
- };
- register int i;
-
- for (i = 0; tab[i].token; i++)
- if (strcmp(tab[i].kw, s) == 0)
- break;
- return tab[i].token;
-}
-
-static
-isbuiltin(s, p) char *s; int *p;
-{
- static struct { char *kw; int type; int token; } tab[] = {
- "atan2", MATHFUN, ATAN2,
- "close", STRFUN, CLOSE,
- "cos", MATHFUN, COS,
- "exp", MATHFUN, EXP,
- "gsub", SUBST, RGSUB,
- "index", STRFUN, INDEX,
- "int", MATHFUN, INT,
- "length", STRFUN, LENGTH,
- "log", MATHFUN, LOG,
- "match", STRFUN, RMATCH,
- "sin", MATHFUN, SIN,
- "sqrt", MATHFUN, SQRT,
- "rand", MATHFUN, RAND,
- "srand", MATHFUN, SRAND,
- "split", STRFUN, SPLIT,
- "sub", SUBST, RSUB,
- "substr", STRFUN, SUBSTR,
- "system", STRFUN, SYSTEM,
- "", 0, 0
- };
- register int i;
-
- for (i = 0; tab[i].token; i++)
- if (strcmp(tab[i].kw, s) == 0)
- break;
- *p = tab[i].token;
- return tab[i].type;
-}
-
-static
-scannum(s) char *s;
-{
- register int c;
- char *strchr();
-
- if ((c = Getc()) && strchr("+-", c) != NULL) {
- *s++ = c; c = Getc();
- }
- while (isdigit(c)) {
- *s++ = c; c = Getc();
- }
- if (c == '.') {
- *s++ = c; c = Getc();
- while (isdigit(c)) {
- *s++ = c; c = Getc();
- }
- }
- if (c && strchr("eE", c) != NULL) {
- *s++ = c; c = Getc();
- if (c && strchr("+-", c) != NULL) {
- *s++ = c; c = Getc();
- }
- while (isdigit(c)) {
- *s++ = c; c = Getc();
- }
- }
- *s = '\0';
- Ungetc(c);
- return NUMBER;
-}
-
-static
-scanstr(s) char *s;
-{
- register int c, i, j;
-
- for (c = Getc(); c != EOF & c != '"'; ) {
- if (c == '\\') {
- switch (c = Getc()) {
- case 'b': c = '\b'; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- default:
- if (isdigit(c)) {
- for (i = j = 0; i < 3 && isdigit(c); c = Getc(), i++)
- j = j * 8 + c - '0';
- Ungetc(c);
- c = j;
- }
- break;
- }
- }
- *s++ = c;
- if (isKanji(c))
- *s++ = Getc();
- c = Getc();
- }
- *s = '\0';
- return STRING;
-}
-
-static
-scanreg()
-{
- register int c;
- register char *s;
-
- for (s = text; (c = Getc()) != '/'; )
- if (c == '\n')
- error("newline in regular expression");
- else {
- if (isKanji(c) || c == '\\') {
- *s++ = c; c = Getc();
- }
- *s++ = c;
- }
- *s = '\0';
- return REGEXP;
-}
-
-isarrayindex()
-{
- int c, c2;
-
-next:
- while ((c = Getc()) == ' ' || c == '\t')
- ;
- if (c == '\\') {
- if ((c2 = Getc()) == '\n') {
- lineno++;
- goto next;
- }
- Ungetc(c2);
- }
- if (c != '[') Ungetc(c);
-
- return (c == '[');
-}
-
-#define UNGET_DEPTH 2
-static int unget[UNGET_DEPTH], unget_depth;
-
-Ungetc(c)
-{
- if (unget_depth == UNGET_DEPTH) error("unget buffer overflow");
- unget[unget_depth++] = c;
-
- if (linep > line) {
- if (--linep < line)
- linep == line + BUFSIZ - 1;
- }
-}
-
-Getc()
-{
- register int c;
- char *s, *t;
-
- if (unget_depth > 0)
- c = unget[--unget_depth];
- else if (srcprg)
- c = *srcprg ? *srcprg++ : EOF;
- else
- c = fgetc(pfp);
-
-#if 0
- if (linep - line == BUFSIZ) {
-printf("!!!\n");
- for (s = line; *s != '\n' && ((s - line) <BUFSIZ); s++)
- ;
-printf("***(%d)***\n", *s);
- for (t = line; s < linep; )
- *t++ = *++s;
- }
-#endif
- *linep++ = c;
- if ((linep - line) == BUFSIZ)
- linep = line;
- return c;
-}
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <signal.h>
-#include "awk.h"
-
-extern char **FS, **FILENAME;
-extern char record[];
-extern FILE *ifp;
-
-NODE *parse();
-CELL *execute();
-FILE *efopen(), *fopen();
-char *strsave();
-
-int xargc;
-char **xargv;
-char *srcprg;
-FILE *pfp;
-char *cmd;
-#if 0
-int iflg; /* interactive mode */
-#endif
-
-main(argc, argv, envp) char **argv, *envp;
-{
- char *s, *strpbrk(), *strchr();
- void onint();
-
-#ifdef DOS
- _sharg(&argc, &argv);
-#endif
- signal(SIGINT, onint);
- signal(SIGFPE, onint);
- cmd = argv[0];
- init();
- while (--argc > 0 && (*++argv)[0] == '-')
- for (s = argv[0]+1; *s; s++)
- if (strcmp(argv[0], "-") == 0)
- break;
- else
- switch (*s) {
-#if 0
- case 'i':
- iflg++;
- pfp = stdin;
- interactive();
- /* no return */
-#endif
- case 'F':
- *FS = ++s;
- break;
- case 'f':
- if (*(s+1))
- s++;
- else {
- argc--; s = *++argv;
- }
- if (s == NULL) usage();
- pfp = efopen(s, "r");
- s += strlen(s) - 1;
- break;
- }
- xargc = argc; xargv = argv;
- if (pfp == NULL && xargc > 0) {
- srcprg = *xargv++; xargc--;
- }
-/*
- if (pfp == NULL && xargc > 0) {
- if (strpbrk(xargv[0], " !$^()={}[];<>,/~") != NULL) {
- sprintf(record, "%s\n", xargv[0]);
- srcprg = strsave(record);
- }
- else {
- sprintf(record, "%s.awk", xargv[0]);
- if ((pfp = fopen(record, "r")) == NULL)
- error("can't open %s", record);
- }
- xargc--; xargv++;
- }
-*/
-
- if (pfp == NULL && srcprg == NULL) usage();
-
- while (*xargv != NULL && strchr(*xargv, '=') != NULL) {
- setvar(*xargv++);
- xargc--;
- }
-
- initarg(cmd, xargc, xargv, envp);
- if (xargc == 0) {
- ifp = stdin; *FILENAME = "-";
- }
- parse();
- closeall();
- exit(0);
-}
-
-FILE *
-efopen(file, mode) char *file, *mode;
-{
- FILE *fp, *fopen();
-
- if ((fp = fopen(file, mode)) == NULL)
- error("cannot open %s", file);
- return fp;
-}
-
-error(s, t) char *s, *t;
-{
- extern double *NR;
-
- fprintf(stderr, "awk: ");
- fprintf(stderr, s, t);
- fprintf(stderr, "\n");
- if (NR != NULL) {
- fprintf(stderr, "record number %g\n", *NR);
- }
-#ifdef DOS
- closeall();
-#endif
- exit(1);
-}
-
-void
-onint(i)
-{
- closeall();
- exit(0x80 | i);
-}
-
-void
-usage()
-{
- fprintf(stderr,
- "usage: %s [options] [-f <rulefile> | <rules>] [inputfiles]\n", cmd);
- closeall();
- exit(1);
-}
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-#include "awk.h"
-
-NODE *
-node0(type)
-{
- NODE *p;
- char *emalloc();
-
- p = (NODE *) emalloc(sizeof(*p) - sizeof(p));
- p->n_type = type;
- p->n_next = NULL;
- return p;
-}
-
-NODE *
-node1(type, arg0) NODE *arg0;
-{
- NODE *p;
- char *emalloc();
-
- p = (NODE *) emalloc(sizeof(*p));
- p->n_type = type;
- p->n_next = NULL;
- p->n_arg[0] = (NODE *) arg0;
- return p;
-}
-
-NODE *
-node2(type, arg0, arg1) NODE *arg0, *arg1;
-{
- NODE *p;
- char *emalloc();
-
- p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * 1);
- p->n_type = type;
- p->n_next = NULL;
- p->n_arg[0] = (NODE *) arg0;
- p->n_arg[1] = (NODE *) arg1;
- return p;
-}
-
-NODE *
-node3(type, arg0, arg1, arg2) NODE *arg0, *arg1, *arg2;
-{
- NODE *p;
- char *emalloc();
-
- p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * 2);
- p->n_type = type;
- p->n_next = NULL;
- p->n_arg[0] = (NODE *) arg0;
- p->n_arg[1] = (NODE *) arg1;
- p->n_arg[2] = (NODE *) arg2;
- return p;
-}
-
-NODE *
-node4(type, arg0, arg1, arg2, arg3) NODE *arg0, *arg1, *arg2, *arg3;
-{
- NODE *p;
- char *emalloc();
-
- p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * 3);
- p->n_type = type;
- p->n_next = NULL;
- p->n_arg[0] = (NODE *) arg0;
- p->n_arg[1] = (NODE *) arg1;
- p->n_arg[2] = (NODE *) arg2;
- p->n_arg[3] = (NODE *) arg3;
- return p;
-}
-
-CELL *
-mkcell(type, sval, fval) char *sval; double fval;
-{
- CELL *p;
- char *emalloc(), *strsave();
-
- p = (CELL *) emalloc(sizeof(*p));
- p->c_type = type;
- if (sval == NULL)
- p->c_sval = NULL;
- else
- p->c_sval = strsave(sval);
- p->c_fval = fval;
- return p;
-}
-
-#ifdef TMPCELL
-#define MAXTMP 25
-
-CELL tmpcell[MAXTMP];
-#endif
-
-CELL *
-mktmp(type, sval, fval) char *sval; double fval;
-{
- register int i;
- char *strsave();
-
-#ifdef TMPCELL
- for (i = 0; i < MAXTMP; i++)
- if (tmpcell[i].c_type == 0) {
- tmpcell[i].c_type = type | TMP;
- tmpcell[i].c_sval = strsave(sval);
- tmpcell[i].c_fval = fval;
- return &tmpcell[i];
- }
- error("formula too complex", (char *) 0);
-#else
- return mkcell(type | TMP, sval, fval);
-#endif
-}
-
-c_free(p) CELL *p;
-{
- if ((p != NULL) && (p->c_type & TMP)) {
-#ifdef TMPCELL
- p->c_type = 0;
- sfree(p->c_sval);
- p->c_sval = (char *)NULL;
- p->c_fval = 0.0;
-#else
- if (p->c_sval != NULL) {
- Free(p->c_sval);
- p->c_sval = NULL;
- }
- p->c_type = 0;
- Free(p);
- p = NULL;
-#endif
- }
-}
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#ifdef DOS
-#include <process.h>
-#endif
-#include "awk.h"
-#include "regexp.h"
-
-#define MAXFLD 100
-
-extern char **FS, **RS, **OFS, **ORS, **FILENAME;
-extern double *NF, *NR;
-extern double *FNR;
-extern double *ARGC;
-extern SYMBOL *argtab[];
-extern CELL *getvar();
-
-char *strsave(), *strcpy(), *getsval(), *jStrchr(), *strchr();
-double getfval(), atof();
-CELL *mkcell(), *mktmp(), *execute(), *patexec();
-FILE *efopen();
-
-extern CELL truecell, falsecell;
-
-extern int pateval;
-
-int infileno = 1;
-FILE *ifp;
-char record[BUFSIZ];
-CELL *field[MAXFLD];
-
-char *fs_str;
-regexp *fs_pat;
-
-CELL *
-Getline(p) NODE *p;
-{
- CELL *u;
- char *fnam, *s, str[BUFSIZ];
- int i;
- FILE *fp, *getfp();
-
- if ((int) p->n_arg[0]) /* read into var */
- s = str;
- else
- s = NULL;
- if ((int) p->n_arg[1]) { /* file name */
- u = execute(p->n_arg[1]);
- fnam = getsval(u);
- fp = getfp(fnam, (int) p->n_arg[2]);
- c_free(u);
- i = get1rec(s, fp);
- }
- else
- i = Getrec(s);
- if (s == str) {
- u = execute(p->n_arg[0]);
- setsval(u, str);
- }
- return mktmp(NUM, NULL, (double) i);
-}
-
-static
-get1rec(buf, fp) char *buf; FILE *fp;
-{
- register int c;
- register char rs, *s;
- int mflg;
-
- if (buf == NULL)
- buf = record;
- if ((rs = **RS) == '\0') { /* multi line record */
- mflg = 1;
- rs = '\n';
- }
- else
- mflg = 0;
-
- if (feof(fp) || (c = getc(fp)) == EOF)
- return 0;
- for (s = buf; ; ) {
- for ( ; c != rs && c != EOF; c = getc(fp)) {
- if (isKanji(c)) {
- *s++ = c; c = getc(fp);
- }
- *s++ = c;
- }
- if (mflg) {
- if ((c = getc(fp)) == '\n' || c == EOF)
- break;
- *s++ = '\n';
- }
- else
- break;
- }
- *s = '\0';
-#if 1
- if (buf == record) {
-#else
- if (buf == record && c != EOF) {
-#endif
- mkfld(record, *FS, field);
- (*NR)++;
- (*FNR)++;
- }
- return s > buf || c != EOF ? 1 : 0;
-}
-
-Getrec(s) char *s;
-{
- CELL *u;
- char *file, str[8];
-
- while (ifp == stdin || infileno < (int)*ARGC) {
- if (ifp == NULL) {
- *FNR = 0.0;
- if (infileno == (int)*ARGC)
- break;
- sprintf(str, "%d", infileno);
- u = getvar(str, argtab);
- file = getsval(u);
- if (strchr(file, '=') != NULL) {
- setvar(file);
- infileno++;
- continue;
- }
- else if (strcmp(file, "") == 0) {
-/*
-if (infileno == (int)*ARGC - 1)
- ifp = stdin;
-*/
- infileno++;
- continue;
- }
- else {
- if (strcmp(file, "-") == 0)
- ifp = stdin;
- else
- ifp = efopen(file, "r");
- *FILENAME = file;
- }
- }
- if (get1rec(s, ifp))
- return 1;
- else {
- if (ifp != stdin)
- fclose(ifp);
- ifp = NULL;
- infileno++;
- }
- }
- ifp = stdin; /* for further "getline" */
- *FILENAME = "-";
- return 0; /* EOF */
-}
-
-mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
-{
- char *s, *t;
- char str[BUFSIZ];
- int i, j, n;
- int skip = 0;
-
- if (strlen(sep) > 1)
- return r_mkfld(rec, sep, fld);
-
- if (*sep == ' ' || *sep == '\0') {
- sep = " \t\n"; skip++;
- }
- for (i = 1, n = (int) *NF; i <= n; i++) {
- sfree(fld[i]->c_sval);
- sfree(fld[i]);
- fld[i] = NULL;
- }
- for (i = 0, s = rec; ; ) {
- t = str;
- if (skip) {
- while (*s && strchr(" \t\n", *s))
- s++;
- if (*s == '\0')
- break;
- }
- while (*s && !jStrchr(sep, *s)) {
- if (isKanji(*s))
- *t++ = *s++;
- *t++ = *s++;
- }
- *t = '\0';
- if (isnum(str))
- fld[++i] = mkcell(FLD|STR|NUM, str, atof(str));
- else
- fld[++i] = mkcell(FLD|STR, str, 0.0);
- if (*s)
- s++;
- else
- break;
- }
- *NF = (double) i;
- return i;
-}
-
-static
-r_mkfld(rec, sep, fld) char *rec, *sep; CELL *fld[];
-{
- char *s, *t;
- char str[BUFSIZ];
- int i, n;
- regexp *mkpat();
- extern int r_start, r_length;
-
- if (strcmp(*FS, fs_str) != 0) {
- sfree(fs_str); sfree(fs_pat);
- fs_str = strsave(*FS);
- fs_pat = mkpat(fs_str);
- }
- for (i = 1, n = (int) *NF; i <= n; i++) {
- sfree(fld[i]->c_sval);
- sfree(fld[i]);
- fld[i] = NULL;
- }
- for (i = 0, s = rec, t = str; *s; ) {
- if (match(fs_pat, s)) {
- for (n = r_start; --n > 0; )
- *t++ = *s++;
- }
- else {
- while (*s)
- *t++ = *s++;
- }
- *t = '\0';
- t = str;
- fld[++i] = mkcell(FLD|STR, str, 0.0);
- if (*s)
- s += r_length;
- }
- *NF = (double) i;
- return i;
-}
-
-mkrec(u) CELL *u;
-{
- register char *s, *t;
- register int i, j;
-
- for (j = (int)*NF, i = 1; i <= j; i++)
- if (field[i] == u)
- break;
- if (i > j) {
- for ( ; i < MAXFLD; i++)
- if (field[i] == u)
- break;
- if (i == MAXFLD)
- error("too many field (%d)", i);
- *NF = (double)i;
- }
- for (t = record, i = 1, j = (int) *NF; i <= j; i++) {
- if (i > 1)
- *t++ = **OFS;
- for (s = getsval(field[i]); *s; )
- *t++ = *s++;
- }
- *t++ = '\0';
-}
-
-CELL *
-Field(p) NODE *p;
-{
- CELL *u;
- int i, j;
-
- u = execute(p->n_arg[0]);
- i = (int) getfval(u);
- c_free(u);
- j = (int)*NF;
- if (i > j)
- for (++j; j <= i; j++) {
- if (field[j] == NULL)
- field[j] = mkcell(FLD|STR, "", 0.0);
- }
- return field[i];
-}
-
-CELL *
-P1stat(p) NODE *p;
-{
- CELL *u;
- double x;
-
- pateval++;
- u = execute(p->n_arg[0]);
- pateval = 0;
- x = getfval(u);
- c_free(u);
- if (x != 0.0)
- u = execute(p->n_arg[1]);
- else
- u = &truecell;
- return u;
-}
-
-CELL *
-P2stat(p) NODE *p;
-{
- static stat = 0;
- CELL *u, *v;
- double x;
-
- switch (stat) {
- case 0:
- pateval++;
- u = execute(p->n_arg[0]);
- pateval = 0;
- x = getfval(u);
- c_free(u);
- if (x == 0.0) {
- u = &truecell; break;
- }
- else
- stat++;
- /* fall through */
- case 1:
- u = execute(p->n_arg[2]);
- c_free(u);
- pateval++;
- u = execute(p->n_arg[1]);
- pateval = 0;
- x = getfval(u);
- if (x != 0.0)
- stat = 0;
- break;
- default:
- u = &truecell;
- break;
- }
- return u;
-}
-
-CELL *
-Print0()
-{
-/*
- int i, j;
- char *s, str[BUFSIZ];
-
- for (*str = '\0', i = 1, j = (int) *NF; i <= j; i++) {
- if (i > 1)
- strcat(str, *OFS);
- s = getsval(field[i]);
- strcat(str, s);
- }
- strcat(str, *ORS);
- fputs(str, stdout);
-*/
- fprintf(stdout, "%s%s", record, *ORS);
- return &truecell;
-}
-
-char *
-format(t, p) char *t; NODE *p;
-{
- CELL *u, *v;
- char *r, *s, *s0, fmt[BUFSIZ];
- double x;
- int i;
-
- u = execute(p->n_arg[2]);
- s = s0 = getsval(u);
-/*
-printf("fmt(%s)\n", s);
-*/
- for (i = 3; *s; s++) {
- if (isKanji(*s)) {
- *t++ = *s++; *t++ = *s; continue;
- }
- if (*s != '%') {
- *t++ = *s; continue;
- }
- else if (*(s + 1) == '%') {
- *t++ = *s++; continue;
- }
- for (r = fmt, *r++ = *s++; *r++ = *s; s++) {
- if (strchr("%cdefgosux", *s))
- break;
- }
- *r = '\0';
- if (p->n_arg[i] == NULL)
- error("not enough args in printf(%s)", s0);
- v = execute(p->n_arg[i++]);
- if (*s == 's')
- r = getsval(v);
- else
- x = getfval(v);
-/*
-printf("val(%d)(%s)\n", v->c_type, v->c_sval);
-*/
- switch (*s) {
- case 'c':
- sprintf(t, fmt, (int) x);
- break;
- case 'd':
- if (*(s - 1) != 'l') {
- *--r = 'l'; *++r = 'd'; *++r = '\0';
- }
- sprintf(t, fmt, (long) x);
- break;
- case 'e': case 'f': case 'g':
- sprintf(t, fmt, x);
- break;
- case 'o': case 'u': case 'x':
- if (*(s - 1) == 'l')
- sprintf(t, fmt, (long) x);
- else
- sprintf(t, fmt, (int) x);
- break;
- case 's':
- /*r = getsval(v);*/
- sprintf(t, fmt, r);
- break;
- default:
- strcpy(t, fmt);
- break;
- }
- c_free(v);
- t += strlen(t);
- }
- c_free(u);
- *t = '\0';
-}
-
-#define MAXFILE 10
-struct {
- char *f_name; /* file name */
- FILE *f_fp;
- int f_type;
-} filetab[MAXFILE];
-
-FILE *
-getfp(file, type) char *file;
-{
- register int i;
- register char *name, *mode;
- char *awktmp();
- FILE *fp, *efopen(), *epopen();
-
- for (i = 0; i < MAXFILE; i++)
- if (filetab[i].f_name && strcmp(filetab[i].f_name, file) == 0)
- return filetab[i].f_fp;
- for (i = 0; i < MAXFILE; i++)
- if (!filetab[i].f_fp)
- break;
- if (i == MAXFILE)
- error("too many files to open");
- name = file;
- switch (type) {
- case R_OUT: mode = "w"; break;
- case R_APD: mode = "a"; break;
- case R_POUT:
-#ifdef DOS
- name = awktmp(i); mode = "w"; /* MS-DOS */
-#else
- fp = epopen(file, "w");
- goto g1;
-#endif
- break;
- case R_IN: mode = "r"; break;
- case R_PIN:
-#ifdef DOS
- {
- int savefd, fd, result;
-
- name = awktmp(i);
- if ((fd = open(name,
- O_WRONLY|O_TEXT|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE)) == -1)
- error("can't open %s", name);
- savefd = dup(1); dup2(fd, 1); close(fd);
- if ((result =
- system(file)) == -1)
- error("can't exec %s", file);
- dup2(savefd, 1); close(savefd); close(fd);
- mode = "r";
- }
-#else
- fp = epopen(file,"r");
- goto g1;
-#endif
- break;
- }
- fp = efopen(name, mode);
-g1:
- filetab[i].f_name = strsave(file);
- filetab[i].f_type = type;
- filetab[i].f_fp = fp;
- return fp;
-}
-
-closeall()
-{
- register int i;
-
- for (i = 0; i < MAXFILE; i++)
- close1(i);
-}
-
-CELL *
-Close(s) char *s;
-{
- register int i;
-
- for (i = 0; i < MAXFILE; i++)
- if (strcmp(s, filetab[i].f_name) == 0) {
- close1(i);
- break;
- }
- i = (i == MAXFILE) ? 0 : 1;
- return mktmp(NUM, NULL, (double) i);
-}
-
-static
-close1(i)
-{
- int fd, result, savefd;
- char *awktmp();
-
- if (filetab[i].f_fp == NULL)
- return;
- switch (filetab[i].f_type) {
- case R_PIN:
-#ifdef DOS
- fclose(filetab[i].f_fp);
- unlink(awktmp(i));
-#else
- pclose(filetab[i].f_fp);
-#endif
- break;
- case R_IN: case R_OUT: case R_APD:
- fclose(filetab[i].f_fp);
- break;
- case R_POUT:
-#ifdef DOS
- fclose(filetab[i].f_fp);
- if ((fd = open(awktmp(i), O_RDONLY)) == NULL)
- error("can't open %s", awktmp(i));
- savefd = dup(0);
- dup2(fd, 0);
- close(fd);
- if ((result =
- system(filetab[i].f_name)) == -1)
-/*
- spawnl(P_WAIT, "/usr/bin/sh", "sh", "-c", filetab[i].f_name, (char *) 0)) == -1)
- fprintf(stderr, "can't spawn /bin/sh\n");
-*/
- error("can't exec %s", filetab[i].f_name);
- dup2(savefd, 0);
- close(savefd);
- unlink(awktmp(i));
-#else
- pclose(filetab[i].f_fp);
-#endif
- break;
- }
- sfree(filetab[i].f_name);
- filetab[i].f_type = 0;
- filetab[i].f_name = NULL;
- filetab[i].f_fp = NULL;
-}
-
-#ifndef DOS
-FILE *
-epopen(file, mod) char *file, *mod;
-{
- FILE *fp, *popen();
-
- if ((fp = popen(file, mod)) == NULL)
- error("can't poen %s", file);
- return fp;
-}
-#endif
-
-static char *
-awktmp(i)
-{
- static char str[16];
-
- sprintf(str, "awk000%02d.tmp", i);
- return str;
-}
-
-Index(s, t) char *s, *t;
-{
- register char *u, *v;
- register int i;
-
- for (i = 1; *s; s++, i++) {
- for (u = s, v = t; *v; u++, v++) {
- if (isKanji(*v)) {
- if (*u != *v)
- break;
- u++; v++;
- }
- if (*u != *v)
- break;
- }
- if (*v == '\0')
- return i;
- if (isKanji(*s))
- s++;
- }
- return 0;
-}
+++ /dev/null
-/*
- * regcomp and regexec -- regsub and regerror are elsewhere
- *
- * Copyright (c) 1986 by University of Toronto.
- * Written by Henry Spencer. Not derived from licensed software.
- *
- * Permission is granted to anyone to use this software for any
- * purpose on any computer system, and to redistribute it freely,
- * subject to the following restrictions:
- *
- * 1. The author is not responsible for the consequences of use of
- * this software, no matter how awful, even if they arise
- * from defects in it.
- *
- * 2. The origin of this software must not be misrepresented, either
- * by explicit claim or by omission.
- *
- * 3. Altered versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * Beware that some of this code is subtly aware of the way operator
- * precedence is structured in regular expressions. Serious changes in
- * regular-expression syntax might require a total rethink.
- *
- * Modified by K.Hirabayashi to accept KANJI code, memory allocation
- * and to add following functions.
- * isthere(), mkpat(), match(), regsub(), sjtok(), ktosj(),
- * Strchr(), Strncmp(), Strlen()
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include "regexp.h"
-
-#define regerror(a) error("regular expression error: %s", a)
-
-int r_start, r_length;
-
-/*
- * The first byte of the regexp internal "program" is actually this magic
- * number; the start node begins in the second byte.
- */
-#define MAGIC 0234
-
-/*
- * The "internal use only" fields in regexp.h are present to pass info from
- * compile to execute that permits the execute phase to run lots faster on
- * simple cases. They are:
- *
- * regstart char that must begin a match; '\0' if none obvious
- * reganch is the match anchored (at beginning-of-line only)?
- * regmust string (pointer into program) that match must include, or NULL
- * regmlen length of regmust string
- *
- * Regstart and reganch permit very fast decisions on suitable starting points
- * for a match, cutting down the work a lot. Regmust permits fast rejection
- * of lines that cannot possibly match. The regmust tests are costly enough
- * that regcomp() supplies a regmust only if the r.e. contains something
- * potentially expensive (at present, the only such thing detected is * or +
- * at the start of the r.e., which can involve a lot of backup). Regmlen is
- * supplied because the test in regexec() needs it and regcomp() is computing
- * it anyway.
- */
-
-/*
- * Structure for regexp "program". This is essentially a linear encoding
- * of a nondeterministic finite-state machine (aka syntax charts or
- * "railroad normal form" in parsing technology). Each node is an opcode
- * plus a "next" pointer, possibly plus an operand. "Next" pointers of
- * all nodes except BRANCH implement concatenation; a "next" pointer with
- * a BRANCH on both ends of it is connecting two alternatives. (Here we
- * have one of the subtle syntax dependencies: an individual BRANCH (as
- * opposed to a collection of them) is never concatenated with anything
- * because of operator precedence.) The operand of some types of node is
- * a literal string; for others, it is a node leading into a sub-FSM. In
- * particular, the operand of a BRANCH node is the first node of the branch.
- * (NB this is *not* a tree structure: the tail of the branch connects
- * to the thing following the set of BRANCHes.) The opcodes are:
- */
-
-/* definition number opnd? meaning */
-#define END 0 /* no End of program. */
-#define BOL 1 /* no Match "" at beginning of line. */
-#define EOL 2 /* no Match "" at end of line. */
-#define ANY 3 /* no Match any one character. */
-#define ANYOF 4 /* str Match any character in this string. */
-#define ANYBUT 5 /* str Match any character not in this string. */
-#define BRANCH 6 /* node Match this alternative, or the next... */
-#define BACK 7 /* no Match "", "next" ptr points backward. */
-#define EXACTLY 8 /* str Match this string. */
-#define NOTHING 9 /* no Match empty string. */
-#define STAR 10 /* node Match this (simple) thing 0 or more times. */
-#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
-#define OPEN 20 /* no Mark this point in input as start of #n. */
- /* OPEN+1 is number 1, etc. */
-#define CLOSE 30 /* no Analogous to OPEN. */
-
-/*
- * Opcode notes:
- *
- * BRANCH The set of branches constituting a single choice are hooked
- * together with their "next" pointers, since precedence prevents
- * anything being concatenated to any individual branch. The
- * "next" pointer of the last BRANCH in a choice points to the
- * thing following the whole choice. This is also where the
- * final "next" pointer of each individual branch points; each
- * branch starts with the operand node of a BRANCH node.
- *
- * BACK Normal "next" pointers all implicitly point forward; BACK
- * exists to make loop structures possible.
- *
- * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
- * BRANCH structures using BACK. Simple cases (one character
- * per match) are implemented with STAR and PLUS for speed
- * and to minimize recursive plunges.
- *
- * OPEN,CLOSE ...are numbered at compile time.
- */
-
-/*
- * A node is one char of opcode followed by two chars of "next" pointer.
- * "Next" pointers are stored as two 8-bit pieces, high order first. The
- * value is a positive offset from the opcode of the node containing it.
- * An operand, if any, simply follows the node. (Note that much of the
- * code generation knows about this implicit relationship.)
- *
- * Using two bytes for the "next" pointer is vast overkill for most things,
- * but allows patterns to get big without disasters.
- */
-#define OP(p) (*(p))
-#define NEXT(p) (((*((p)+1)&0377)<<8) + *((p)+2)&0377)
-#define OPERAND(p) ((p) + 3)
-
-
-
-/*
- * Utility definitions.
- */
-#ifndef CHARBITS
-#define UCHARAT(p) ((int)*(ushort *)(p))
-#else
-#define UCHARAT(p) ((int)*(p)&CHARBITS)
-#endif
-
-#define FAIL(m) { regerror(m); return(NULL); }
-#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
-#define META "^$.[()|?+*\\"
-
-/*
- * Flags to be passed up and down.
- */
-#define HASWIDTH 01 /* Known never to match null string. */
-#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
-#define SPSTART 04 /* Starts with * or +. */
-#define WORST 0 /* Worst case. */
-
-/*
- * Global work variables for regcomp().
- */
-static ushort *regparse; /* Input-scan pointer. */
-static int regnpar; /* () count. */
-static ushort regdummy;
-static ushort *regcode; /* Code-emit pointer; ®dummy = don't. */
-static long regsize; /* Code size. */
-
-/*
- * Forward declarations for regcomp()'s friends.
- */
-#ifndef STATIC
-#define STATIC static
-#endif
-STATIC ushort *reg();
-STATIC ushort *regbranch();
-STATIC ushort *regpiece();
-STATIC ushort *regatom();
-STATIC ushort *regnode();
-STATIC ushort *regnext();
-STATIC void regc();
-STATIC void reginsert();
-STATIC void regtail();
-STATIC void regoptail();
-STATIC int Strcspn();
-
-/*
- - regcomp - compile a regular expression into internal code
- *
- * We can't allocate space until we know how big the compiled form will be,
- * but we can't compile it (and thus know how big it is) until we've got a
- * place to put the code. So we cheat: we compile it twice, once with code
- * generation turned off and size counting turned on, and once "for real".
- * This also means that we don't allocate space until we are sure that the
- * thing really will compile successfully, and we never have to move the
- * code and thus invalidate pointers into it. (Note that it has to be in
- * one piece because free() must be able to free it all.)
- *
- * Beware that the optimization-preparation code in here knows about some
- * of the structure of the compiled regexp.
- */
-regexp *
-regcomp(exp)
-ushort *exp;
-{
- register regexp *r;
- register ushort *scan;
- register ushort *longest;
- register int len;
- int flags;
- extern char *emalloc();
-
- if (exp == NULL)
- FAIL("NULL argument");
-
- /* First pass: determine size, legality. */
- regparse = exp;
- regnpar = 1;
- regsize = 0L;
- regcode = ®dummy;
- regc((ushort) MAGIC);
- if (reg(0, &flags) == NULL)
- return(NULL);
-
- /* Small enough for pointer-storage convention? */
- if (regsize >= 32767L) /* Probably could be 65535L. */
- FAIL("regexp too big");
-
- /* Allocate space. */
- r = (regexp *)emalloc(sizeof(regexp) + (unsigned)regsize * sizeof(ushort));
-
- /* Second pass: emit code. */
- regparse = exp;
- regnpar = 1;
- regcode = r->program;
- regc((ushort) MAGIC);
- if (reg(0, &flags) == NULL)
- return(NULL);
-
- /* Dig out information for optimizations. */
- r->regstart = '\0'; /* Worst-case defaults. */
- r->reganch = 0;
- r->regmust = NULL;
- r->regmlen = 0;
- scan = r->program+1; /* First BRANCH. */
- if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
- scan = OPERAND(scan);
-
- /* Starting-point info. */
- if (OP(scan) == EXACTLY)
- r->regstart = *OPERAND(scan);
- else if (OP(scan) == BOL)
- r->reganch++;
-
- /*
- * If there's something expensive in the r.e., find the
- * longest literal string that must appear and make it the
- * regmust. Resolve ties in favor of later strings, since
- * the regstart check works with the beginning of the r.e.
- * and avoiding duplication strengthens checking. Not a
- * strong reason, but sufficient in the absence of others.
- */
- if (flags&SPSTART) {
- longest = NULL;
- len = 0;
- for (; scan != NULL; scan = regnext(scan))
- if (OP(scan) == EXACTLY && Strlen(OPERAND(scan)) >= len) {
- longest = OPERAND(scan);
- len = Strlen(OPERAND(scan));
- }
- r->regmust = longest;
- r->regmlen = len;
- }
- }
-
- return(r);
-}
-
-/*
- - reg - regular expression, i.e. main body or parenthesized thing
- *
- * Caller must absorb opening parenthesis.
- *
- * Combining parenthesis handling with the base level of regular expression
- * is a trifle forced, but the need to tie the tails of the branches to what
- * follows makes it hard to avoid.
- */
-static ushort *
-reg(paren, flagp)
-int paren; /* Parenthesized? */
-int *flagp;
-{
- register ushort *ret;
- register ushort *br;
- register ushort *ender;
- register int parno;
- int flags;
-
- *flagp = HASWIDTH; /* Tentatively. */
-
- /* Make an OPEN node, if parenthesized. */
- if (paren) {
- if (regnpar >= NSUBEXP)
- FAIL("too many ()");
- parno = regnpar;
- regnpar++;
- ret = regnode(OPEN+parno);
- } else
- ret = NULL;
-
- /* Pick up the branches, linking them together. */
- br = regbranch(&flags);
- if (br == NULL)
- return(NULL);
- if (ret != NULL)
- regtail(ret, br); /* OPEN -> first. */
- else
- ret = br;
- if (!(flags&HASWIDTH))
- *flagp &= ~HASWIDTH;
- *flagp |= flags&SPSTART;
- while (*regparse == '|') {
- regparse++;
- br = regbranch(&flags);
- if (br == NULL)
- return(NULL);
- regtail(ret, br); /* BRANCH -> BRANCH. */
- if (!(flags&HASWIDTH))
- *flagp &= ~HASWIDTH;
- *flagp |= flags&SPSTART;
- }
-
- /* Make a closing node, and hook it on the end. */
- ender = regnode((paren) ? CLOSE+parno : END);
- regtail(ret, ender);
-
- /* Hook the tails of the branches to the closing node. */
- for (br = ret; br != NULL; br = regnext(br))
- regoptail(br, ender);
-
- /* Check for proper termination. */
- if (paren && *regparse++ != ')') {
- FAIL("unmatched ()");
- } else if (!paren && *regparse != '\0') {
- if (*regparse == ')') {
- FAIL("unmatched ()");
- } else
- FAIL("junk on end"); /* "Can't happen". */
- /* NOTREACHED */
- }
-
- return(ret);
-}
-
-/*
- - regbranch - one alternative of an | operator
- *
- * Implements the concatenation operator.
- */
-static ushort *
-regbranch(flagp)
-int *flagp;
-{
- register ushort *ret;
- register ushort *chain;
- register ushort *latest;
- int flags;
-
- *flagp = WORST; /* Tentatively. */
-
- ret = regnode(BRANCH);
- chain = NULL;
- while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
- latest = regpiece(&flags);
- if (latest == NULL)
- return(NULL);
- *flagp |= flags&HASWIDTH;
- if (chain == NULL) /* First piece. */
- *flagp |= flags&SPSTART;
- else
- regtail(chain, latest);
- chain = latest;
- }
- if (chain == NULL) /* Loop ran zero times. */
- (void) regnode(NOTHING);
-
- return(ret);
-}
-
-/*
- - regpiece - something followed by possible [*+?]
- *
- * Note that the branching code sequences used for ? and the general cases
- * of * and + are somewhat optimized: they use the same NOTHING node as
- * both the endmarker for their branch list and the body of the last branch.
- * It might seem that this node could be dispensed with entirely, but the
- * endmarker role is not redundant.
- */
-static ushort *
-regpiece(flagp)
-int *flagp;
-{
- register ushort *ret;
- register ushort op;
- register ushort *next;
- int flags;
-
- ret = regatom(&flags);
- if (ret == NULL)
- return(NULL);
-
- op = *regparse;
- if (!ISMULT(op)) {
- *flagp = flags;
- return(ret);
- }
-
- if (!(flags&HASWIDTH) && op != '?')
- FAIL("*+ operand could be empty");
- *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
-
- if (op == '*' && (flags&SIMPLE))
- reginsert(STAR, ret);
- else if (op == '*') {
- /* Emit x* as (x&|), where & means "self". */
- reginsert(BRANCH, ret); /* Either x */
- regoptail(ret, regnode(BACK)); /* and loop */
- regoptail(ret, ret); /* back */
- regtail(ret, regnode(BRANCH)); /* or */
- regtail(ret, regnode(NOTHING)); /* null. */
- } else if (op == '+' && (flags&SIMPLE))
- reginsert(PLUS, ret);
- else if (op == '+') {
- /* Emit x+ as x(&|), where & means "self". */
- next = regnode(BRANCH); /* Either */
- regtail(ret, next);
- regtail(regnode(BACK), ret); /* loop back */
- regtail(next, regnode(BRANCH)); /* or */
- regtail(ret, regnode(NOTHING)); /* null. */
- } else if (op == '?') {
- /* Emit x? as (x|) */
- reginsert(BRANCH, ret); /* Either x */
- regtail(ret, regnode(BRANCH)); /* or */
- next = regnode(NOTHING); /* null. */
- regtail(ret, next);
- regoptail(ret, next);
- }
- regparse++;
- if (ISMULT(*regparse))
- FAIL("nested *?+");
-
- return(ret);
-}
-
-/*
- - regatom - the lowest level
- *
- * Optimization: gobbles an entire sequence of ordinary characters so that
- * it can turn them into a single node, which is smaller to store and
- * faster to run. Backslashed characters are exceptions, each becoming a
- * separate node; the code is simpler that way and it's not worth fixing.
- */
-static ushort *
-regatom(flagp)
-int *flagp;
-{
- register ushort *ret;
- int flags;
- ushort c, d;
-
- *flagp = WORST; /* Tentatively. */
-
- switch ((int) *regparse++) {
- case '^':
- ret = regnode(BOL);
- break;
- case '$':
- ret = regnode(EOL);
- break;
- case '.':
- ret = regnode(ANY);
- *flagp |= HASWIDTH|SIMPLE;
- break;
- case '[': {
- register int class;
- register int classend;
- register int c;
-
- if (*regparse == '^') { /* Complement of range. */
- ret = regnode(ANYBUT);
- regparse++;
- } else
- ret = regnode(ANYOF);
- if (*regparse == ']' || *regparse == '-')
- regc(*regparse++);
- while (*regparse != '\0' && *regparse != ']') {
- if (*regparse == '-') {
- regparse++;
- if (*regparse == ']' || *regparse == '\0')
- regc((ushort) '-');
- else {
- class = UCHARAT(regparse-2)+1;
- classend = UCHARAT(regparse);
- if (class > classend+1)
- FAIL("invalid [] range");
- regc((ushort) 0xffff);
- regc((ushort) class);
- regc((ushort) classend);
- regparse++;
- }
- } else {
- if ((c = *regparse++) == '\\') {
- if ((c = *regparse++) == 'n')
- c = '\n';
- else if (c == 't')
- c = '\t';
- }
- regc(c);
- }
- }
- regc((ushort) 0);
- if (*regparse != ']')
- FAIL("unmatched []");
- regparse++;
- *flagp |= HASWIDTH|SIMPLE;
- }
- break;
- case '(':
- ret = reg(1, &flags);
- if (ret == NULL)
- return(NULL);
- *flagp |= flags&(HASWIDTH|SPSTART);
- break;
- case '\0':
- case '|':
- case ')':
- FAIL("internal urp"); /* Supposed to be caught earlier. */
- break;
- case '?':
- case '+':
- case '*':
- FAIL("?+* follows nothing");
- break;
- case '\\':
- if (*regparse == '\0')
- FAIL("trailing \\");
- ret = regnode(EXACTLY);
-/*
- regc(*regparse++);
-*/
- c = *regparse++;
- if (c == 'n')
- c = '\n';
- else if (c == 't')
- c = '\t';
- else if (c == 'f')
- c = '\f';
- else if (c == '\r')
- c = '\r';
- else if (c == '\b')
- c = '\b';
- else if (IsDigid(c)) {
- d = c - '0';
- if (IsDigid(*regparse)) {
- d = d * 8 + *regparse++ - '0';
- if (IsDigid(*regparse))
- d = d * 8 + *regparse++ - '0';
- }
- c = d;
- }
- regc(c);
- regc((ushort) 0);
- *flagp |= HASWIDTH|SIMPLE;
- break;
- default: {
- register int len;
- register char ender;
-
- regparse--;
- len = Strcspn(regparse, META);
- if (len <= 0)
- FAIL("internal disaster");
- ender = *(regparse+len);
- if (len > 1 && ISMULT(ender))
- len--; /* Back off clear of ?+* operand. */
- *flagp |= HASWIDTH;
- if (len == 1)
- *flagp |= SIMPLE;
- ret = regnode(EXACTLY);
- while (len > 0) {
- regc(*regparse++);
- len--;
- }
- regc((ushort) 0);
- }
- break;
- }
-
- return(ret);
-}
-
-IsDigid(c) ushort c;
-{
- return '0' <= c && c <= '9';
-}
-
-/*
- - regnode - emit a node
- */
-static ushort * /* Location. */
-regnode(op)
-ushort op;
-{
- register ushort *ret;
- register ushort *ptr;
-
- ret = regcode;
- if (ret == ®dummy) {
- regsize += 3;
- return(ret);
- }
-
- ptr = ret;
- *ptr++ = op;
- *ptr++ = '\0'; /* Null "next" pointer. */
- *ptr++ = '\0';
- regcode = ptr;
-
- return(ret);
-}
-
-/*
- - regc - emit (if appropriate) a byte of code
- */
-static void
-regc(b)
-ushort b;
-{
- if (regcode != ®dummy)
- *regcode++ = b;
- else
- regsize++;
-}
-
-/*
- - reginsert - insert an operator in front of already-emitted operand
- *
- * Means relocating the operand.
- */
-static void
-reginsert(op, opnd)
-ushort op;
-ushort *opnd;
-{
- register ushort *src;
- register ushort *dst;
- register ushort *place;
-
- if (regcode == ®dummy) {
- regsize += 3;
- return;
- }
-
- src = regcode;
- regcode += 3;
- dst = regcode;
- while (src > opnd)
- *--dst = *--src;
-
- place = opnd; /* Op node, where operand used to be. */
- *place++ = op;
- *place++ = '\0';
- *place++ = '\0';
-}
-
-/*
- - regtail - set the next-pointer at the end of a node chain
- */
-static void
-regtail(p, val)
-ushort *p;
-ushort *val;
-{
- register ushort *scan;
- register ushort *temp;
- register int offset;
-
- if (p == ®dummy)
- return;
-
- /* Find last node. */
- scan = p;
- for (;;) {
- temp = regnext(scan);
- if (temp == NULL)
- break;
- scan = temp;
- }
-
- if (OP(scan) == BACK)
- offset = scan - val;
- else
- offset = val - scan;
- *(scan+1) = (offset>>8)&0377;
- *(scan+2) = offset&0377;
-}
-
-/*
- - regoptail - regtail on operand of first argument; nop if operandless
- */
-static void
-regoptail(p, val)
-ushort *p;
-ushort *val;
-{
- /* "Operandless" and "op != BRANCH" are synonymous in practice. */
- if (p == NULL || p == ®dummy || OP(p) != BRANCH)
- return;
- regtail(OPERAND(p), val);
-}
-
-/*
- * regexec and friends
- */
-
-/*
- * Global work variables for regexec().
- */
-static ushort *reginput; /* String-input pointer. */
-static ushort *regbol; /* Beginning of input, for ^ check. */
-static ushort **regstartp; /* Pointer to startp array. */
-static ushort **regendp; /* Ditto for endp. */
-
-/*
- * Forwards.
- */
-STATIC int regtry();
-STATIC int regmatch();
-STATIC int regrepeat();
-
-#ifdef DEBUG
-int regnarrate = 0;
-void regdump();
-STATIC char *regprop();
-#endif
-
-/*
- - regexec - match a regexp against a string
- */
-int
-regexec(prog, string, bolflag)
-register regexp *prog;
-register ushort *string;
-int bolflag;
-{
- register ushort *s;
- extern ushort *Strchr();
-
- /* Be paranoid... */
- if (prog == NULL || string == NULL) {
- regerror("NULL parameter");
- return(0);
- }
-
- /* Check validity of program. */
- if (prog->program[0] != MAGIC) {
- regerror("corrupted program");
- return(0);
- }
-
- /* If there is a "must appear" string, look for it. */
- if (prog->regmust != NULL) {
- s = string;
- while ((s = Strchr(s, prog->regmust[0])) != NULL) {
- if (Strncmp(s, prog->regmust, prog->regmlen) == 0)
- break; /* Found it. */
- s++;
- }
- if (s == NULL) /* Not present. */
- return(0);
- }
-
- /* Mark beginning of line for ^ . */
- if(bolflag)
- regbol = string;
- else
- regbol = NULL;
-
- /* Simplest case: anchored match need be tried only once. */
- if (prog->reganch)
- return(regtry(prog, string));
-
- /* Messy cases: unanchored match. */
- s = string;
- if (prog->regstart != '\0') {
- /* We know what char it must start with. */
- while ((s = Strchr(s, prog->regstart)) != NULL) {
- if (regtry(prog, s))
- return(1);
- s++;
- }
-}
- else
- /* We don't -- general case. */
- do {
- if (regtry(prog, s))
- return(1);
- } while (*s++ != '\0');
-
- /* Failure. */
- return(0);
-}
-
-/*
- - regtry - try match at specific point
- */
-static int /* 0 failure, 1 success */
-regtry(prog, string)
-regexp *prog;
-ushort *string;
-{
- register int i;
- register ushort **sp;
- register ushort **ep;
-
- reginput = string;
- regstartp = prog->startp;
- regendp = prog->endp;
-
- sp = prog->startp;
- ep = prog->endp;
- for (i = NSUBEXP; i > 0; i--) {
- *sp++ = NULL;
- *ep++ = NULL;
- }
- if (regmatch(prog->program + 1)) {
- prog->startp[0] = string;
- prog->endp[0] = reginput;
- return(1);
- } else
- return(0);
-}
-
-/*
- - regmatch - main matching routine
- *
- * Conceptually the strategy is simple: check to see whether the current
- * node matches, call self recursively to see whether the rest matches,
- * and then act accordingly. In practice we make some effort to avoid
- * recursion, in particular by going through "ordinary" nodes (that don't
- * need to know whether the rest of the match failed) by a loop instead of
- * by recursion.
- */
-static int /* 0 failure, 1 success */
-regmatch(prog)
-ushort *prog;
-{
- register ushort *scan; /* Current node. */
- ushort *next; /* Next node. */
- extern ushort *Strchr();
-
- scan = prog;
-#ifdef DEBUG
- if (scan != NULL && regnarrate)
- fprintf(stderr, "%s(\n", regprop(scan));
-#endif
- while (scan != NULL) {
-#ifdef DEBUG
- if (regnarrate)
- fprintf(stderr, "%s...\n", regprop(scan));
-#endif
- next = regnext(scan);
-
- switch ((int) OP(scan)) {
- case BOL:
- if (reginput != regbol)
- return(0);
- break;
- case EOL:
- if (*reginput != '\0')
- return(0);
- break;
- case ANY:
- if (*reginput == '\0')
- return(0);
- reginput++;
- break;
- case EXACTLY: {
- register int len;
- register ushort *opnd;
-
- opnd = OPERAND(scan);
- /* Inline the first character, for speed. */
- if (*opnd != *reginput)
- return(0);
- len = Strlen(opnd);
- if (len > 1 && Strncmp(opnd, reginput, len) != 0)
- return(0);
- reginput += len;
- }
- break;
- case ANYOF:
- if (*reginput == '\0' || isthere(OPERAND(scan), *reginput) == 0)
- return(0);
- reginput++;
- break;
- case ANYBUT:
- if (*reginput == '\0' || isthere(OPERAND(scan), *reginput) != 0)
- return(0);
- reginput++;
- break;
- case NOTHING:
- break;
- case BACK:
- break;
- case OPEN+1:
- case OPEN+2:
- case OPEN+3:
- case OPEN+4:
- case OPEN+5:
- case OPEN+6:
- case OPEN+7:
- case OPEN+8:
- case OPEN+9: {
- register int no;
- register ushort *save;
-
- no = OP(scan) - OPEN;
- save = reginput;
-
- if (regmatch(next)) {
- /*
- * Don't set startp if some later
- * invocation of the same parentheses
- * already has.
- */
- if (regstartp[no] == NULL)
- regstartp[no] = save;
- return(1);
- } else
- return(0);
- }
- break;
- case CLOSE+1:
- case CLOSE+2:
- case CLOSE+3:
- case CLOSE+4:
- case CLOSE+5:
- case CLOSE+6:
- case CLOSE+7:
- case CLOSE+8:
- case CLOSE+9: {
- register int no;
- register ushort *save;
-
- no = OP(scan) - CLOSE;
- save = reginput;
-
- if (regmatch(next)) {
- /*
- * Don't set endp if some later
- * invocation of the same parentheses
- * already has.
- */
- if (regendp[no] == NULL)
- regendp[no] = save;
- return(1);
- } else
- return(0);
- }
- break;
- case BRANCH: {
- register ushort *save;
-
- if (OP(next) != BRANCH) /* No choice. */
- next = OPERAND(scan); /* Avoid recursion. */
- else {
- do {
- save = reginput;
- if (regmatch(OPERAND(scan)))
- return(1);
- reginput = save;
- scan = regnext(scan);
- } while (scan != NULL && OP(scan) == BRANCH);
- return(0);
- /* NOTREACHED */
- }
- }
- break;
- case STAR:
- case PLUS: {
- register ushort nextch;
- register int no;
- register ushort *save;
- register int min;
-
- /*
- * Lookahead to avoid useless match attempts
- * when we know what character comes next.
- */
- nextch = '\0';
- if (OP(next) == EXACTLY)
- nextch = *OPERAND(next);
- min = (OP(scan) == STAR) ? 0 : 1;
- save = reginput;
- no = regrepeat(OPERAND(scan));
- while (no >= min) {
- /* If it could work, try it. */
- if (nextch == '\0' || *reginput == nextch)
- if (regmatch(next))
- return(1);
- /* Couldn't or didn't -- back up. */
- no--;
- reginput = save + no;
- }
- return(0);
- }
- break;
- case END:
- return(1); /* Success! */
- break;
- default:
- regerror("memory corruption");
- return(0);
- break;
- }
-
- scan = next;
- }
-
- /*
- * We get here only if there's trouble -- normally "case END" is
- * the terminating point.
- */
- regerror("corrupted pointers");
- return(0);
-}
-
-/*
- - regrepeat - repeatedly match something simple, report how many
- */
-static int
-regrepeat(p)
-ushort *p;
-{
- register int count = 0;
- register ushort *scan;
- register ushort *opnd;
-
- scan = reginput;
- opnd = OPERAND(p);
- switch (OP(p)) {
- case ANY:
- count = Strlen(scan);
- scan += count;
- break;
- case EXACTLY:
- while (*opnd == *scan) {
- count++;
- scan++;
- }
- break;
- case ANYOF:
- while (*scan != '\0' && isthere(opnd, *scan) != 0) {
- count++;
- scan++;
- }
- break;
- case ANYBUT:
- while (*scan != '\0' && isthere(opnd, *scan) == 0) {
- count++;
- scan++;
- }
- break;
- default: /* Oh dear. Called inappropriately. */
- regerror("internal foulup");
- count = 0; /* Best compromise. */
- break;
- }
- reginput = scan;
-
- return(count);
-}
-
-/*
- - regnext - dig the "next" pointer out of a node
- */
-static ushort *
-regnext(p)
-register ushort *p;
-{
- register int offset;
-
- if (p == ®dummy)
- return(NULL);
-
- offset = NEXT(p);
- if (offset == 0)
- return(NULL);
-
- if (OP(p) == BACK)
- return(p-offset);
- else
- return(p+offset);
-}
-
-#ifdef DEBUG
-
-STATIC char *regprop();
-
-/*
- - regdump - dump a regexp onto stdout in vaguely comprehensible form
- */
-void
-regdump(r)
-regexp *r;
-{
- register ushort *s;
- register ushort op = EXACTLY; /* Arbitrary non-END op. */
- register ushort *next;
-
-
- s = r->program + 1;
- while (op != END) { /* While that wasn't END last time... */
- op = OP(s);
- printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
- next = regnext(s);
- if (next == NULL) /* Next ptr. */
- printf("(0)");
- else
- printf("(%d)", (s-r->program)+(next-s));
- s += 3;
- if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
- /* Literal string, where present. */
- while (*s != '\0') {
- if (*s == 0xffff) { /* range */
- kputchar(*++s); putchar('-'); ++s;
- }
- kputchar(*s++);
- }
- s++;
- }
- putchar('\n');
- }
-
- /* Header fields of interest. */
- if (r->regstart != '\0') {
- fputs("start `", stdout); kputchar(r->regstart); fputs("' ", stdout);
- }
- if (r->reganch)
- printf("anchored ");
- if (r->regmust != NULL) {
- fputs("must have \"", stdout); kputs(r->regmust); putchar('"');
- }
- printf("\n");
-}
-
-kputchar(c) ushort c;
-{
- if (c & 0xff00)
- putchar(c >> 8);
- putchar(c & 0xff);
-}
-
-kputs(s) ushort *s;
-{
- while (*s)
- kputchar(*s++);
-}
-
-/*
- - regprop - printable representation of opcode
- */
-static char *
-regprop(op)
-ushort *op;
-{
- register char *p;
- static char buf[50];
-
- (void) strcpy(buf, ":");
-
- switch ((int) OP(op)) {
- case BOL:
- p = "BOL";
- break;
- case EOL:
- p = "EOL";
- break;
- case ANY:
- p = "ANY";
- break;
- case ANYOF:
- p = "ANYOF";
- break;
- case ANYBUT:
- p = "ANYBUT";
- break;
- case BRANCH:
- p = "BRANCH";
- break;
- case EXACTLY:
- p = "EXACTLY";
- break;
- case NOTHING:
- p = "NOTHING";
- break;
- case BACK:
- p = "BACK";
- break;
- case END:
- p = "END";
- break;
- case OPEN+1:
- case OPEN+2:
- case OPEN+3:
- case OPEN+4:
- case OPEN+5:
- case OPEN+6:
- case OPEN+7:
- case OPEN+8:
- case OPEN+9:
- sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
- p = NULL;
- break;
- case CLOSE+1:
- case CLOSE+2:
- case CLOSE+3:
- case CLOSE+4:
- case CLOSE+5:
- case CLOSE+6:
- case CLOSE+7:
- case CLOSE+8:
- case CLOSE+9:
- sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
- p = NULL;
- break;
- case STAR:
- p = "STAR";
- break;
- case PLUS:
- p = "PLUS";
- break;
- default:
- regerror("corrupted opcode");
- break;
- }
- if (p != NULL)
- (void) strcat(buf, p);
- return(buf);
-}
-#endif
-
-/*
- * The following is provided for those people who do not have strcspn() in
- * their C libraries. They should get off their butts and do something
- * about it; at least one public-domain implementation of those (highly
- * useful) string routines has been published on Usenet.
- */
-/*
- * strcspn - find length of initial segment of s1 consisting entirely
- * of characters not from s2
- */
-
-static int
-Strcspn(s1, s2)
-ushort *s1;
-unsigned char *s2;
-{
- register ushort *scan1;
- register unsigned char *scan2;
- register int count;
-
- count = 0;
- for (scan1 = s1; *scan1 != '\0'; scan1++) {
- for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */
- if (*scan1 == *scan2++)
- return(count);
- count++;
- }
- return(count);
-}
-
-isthere(s, c) ushort *s, c;
-{
- register unsigned int c1, c2;
-
- for ( ; *s; s++) {
- if (*s == 0xffff) { /* range */
- c1 = *++s; c2 = *++s;
- if (c1 <= c && c <= c2)
- return 1;
- }
- else if (*s == c)
- return 1;
- }
- return 0;
-}
-
-ushort *
-Strchr(s, c) ushort *s, c;
-{
- for ( ; *s; s++)
- if (*s == c)
- return s;
- return NULL;
-}
-
-Strncmp(s, t, n) ushort *s, *t;
-{
- for ( ; --n > 0 && *s == *t; s++, t++)
- ;
- return *s - *t;
-}
-
-Strlen(s) ushort *s;
-{
- int i;
-
- for (i = 0; *s; i++, s++)
- ;
- return i;
-}
-
-ushort kbuf[BUFSIZ];
-
-char *
-mkpat(s) char *s;
-{
- sjtok(kbuf, s);
- return (char *) regcomp(kbuf);
-}
-
-match(p, s) regexp *p; char *s;
-{
- register int i;
-
- sjtok(kbuf, s);
- if (i = regexec(p, kbuf, 1)) {
- r_start = p->startp[0] - kbuf + 1;
- r_length = p->endp[0] - p->startp[0];
- }
- else
- r_start = r_length = 0;
- return i;
-}
-
-sjtok(s, t) ushort *s; unsigned char *t;
-{
- register c;
-
- for ( ; *t; t++) {
- if (isKanji(c = *t))
- c = (c << 8) | (*++t & 0xff);
- *s++ = c;
- }
- *s = 0;
-}
-
-ktosj(s, t) unsigned char *s; ushort *t;
-{
- register c;
-
- while (*t) {
- if ((c = *t++) & 0xff00)
- *s++ = c >> 8;
- *s++ = c & 0xff;
- }
- *s = '\0';
-}
-
-regsub(dst, exp, src, pat, pos) ushort *dst, *src, *pat; regexp *exp;
-{ /* dst <-- s/src/pat/pos global substitution for pos == 0 */
- register int c, i;
- register ushort *loc1, *loc2, *s, *t, *u;
- register int n = 0;
-
- if (exp->program[0] != MAGIC) {
- regerror("damaged regexp fed to regsub");
- return 0;
- }
- while (*src) {
-next:
- if (regexec(exp, src, 1) == 0)
- break;
- loc1 = exp->startp[0]; loc2 = exp->endp[0];
- if (pos-- > 1) {
- while (src < loc2)
- *dst++ = *src++;
- goto next;
- }
- while (src < loc1)
- *dst++ = *src++;
- for (s = pat; c = *s++; ) {
- if (c == '&')
- i = 0;
- else if (c == '\\' && '0' <= *s && *s <= '9')
- i = *s++ - '0';
- else {
- if (c == '\\' && (*s == '\\' || *s == '&'))
- c = *s++;
- *dst++ = c;
- continue;
- }
- if ((t = exp->startp[i]) != NULL
- && (u = exp->endp[i]) != NULL) {
- while (t < u)
- *dst++ = *t++;
- }
- }
- src = loc2;
- n++;
- if (pos == 0)
- break;
- }
- while (*src)
- *dst++ = *src++;
- *dst++ = 0;
- return n;
-}
-
-static ushort kbuf1[BUFSIZ], kbuf2[BUFSIZ];
-
-Sub(u, exp, str, s, t, pos) char *exp; char *s, *t, *u;
-{
- register int i;
- regexp *r;
-
- if (str) {
- sjtok(kbuf, exp);
- r = regcomp(kbuf);
- }
- else
- r = (regexp *) exp;
- sjtok(kbuf, s);
- sjtok(kbuf1, t);
- i = regsub(kbuf2, r, kbuf1, kbuf, pos);
- ktosj(u, kbuf2);
- if (str)
- sfree(r);
-
- return i;
-}
+++ /dev/null
-/*
- * Definitions etc. for regexp(3) routines.
- *
- * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
- * not the System V one.
- */
-#define ushort unsigned short
-#define CHARBITS 0xffff
-#define NSUBEXP 10
-typedef struct regexp {
- ushort *startp[NSUBEXP];
- ushort *endp[NSUBEXP];
- ushort regstart; /* Internal use only. */
- ushort reganch; /* Internal use only. */
- ushort *regmust; /* Internal use only. */
- int regmlen; /* Internal use only. */
- ushort program[1]; /* Unwarranted chumminess with compiler. */
-} regexp;
-
-extern regexp *regcomp();
-extern int regexec();
-extern int regsub();
-extern int regerror();
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-#include <ctype.h>
-#include "awk.h"
-#include "regexp.h"
-
-#define PI 3.14159265358979323846
-
-#define HASHSIZE 50
-#define MAXFIELD 100
-
-double atof();
-char *getsval(), *jStrchar();
-extern CELL *execute(), *_Arg();
-
-extern char record[];
-extern CELL *field[];
-
-extern CELL truecell, falsecell;
-extern prmflg;
-
-SYMBOL *hashtab[HASHSIZE];
-SYMBOL *funtab[HASHSIZE];
-SYMBOL *argtab[HASHSIZE];
-SYMBOL *envtab[HASHSIZE];
-
-char *strsave(), *emalloc(), *strchr();
-CELL *lookup(), *install(), *_install(), *mkcell(), *mktmp(), *getvar();
-
-char **FS, **RS, **OFS, **ORS, **OFMT, **FILENAME;
-char **SUBSEP;
-double *NR, *NF;
-double *FNR, *ARGC, *RSTART, *RLENGTH;
-
-init()
-{
- FS = &install("FS", VAR|STR, " ", 0.0, hashtab)->c_sval;
- RS = &install("RS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
- OFS = &install("OFS", VAR|STR , " ", 0.0, hashtab)->c_sval;
- ORS = &install("ORS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
- OFMT = &install("OFMT", VAR|STR, "%.6g", 0.0, hashtab)->c_sval;
- NR = &install("NR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
- NF = &install("NF", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
- FILENAME = &install("FILENAME", VAR|STR, (char *)NULL, 0.0, hashtab)->c_sval;
- install("PI", VAR|NUM, (char *)NULL, PI, hashtab);
- field[0] = mkcell(REC|STR, (char *)NULL, 0.0); /* $0 */
- field[0]->c_sval = record;
- SUBSEP = &install("SUBSEP", VAR|STR, "\034", 0.0, hashtab)->c_sval;
- FNR = &install("FNR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
- RSTART = &install("RSTART", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
- RLENGTH = &install("RLENGTH", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
-}
-
-setvar(s) char *s;
-{
- CELL *u;
- char *t;
-
- for (t = s; *t && *t != '='; t++)
- ;
- *t++ = '\0';
- if ((u = lookup(s, hashtab)) == (CELL *)NULL) {
- if (isnum(t))
- install(s, VAR|NUM|STR, t, atof(t), hashtab);
- else
- install(s, VAR|STR, t, 0.0, hashtab);
- }
- else {
- if (isnum(t))
- setfval(u, atof(t));
- else
- setsval(u, t);
- }
-}
-
-initarg(arg0, argc, argv, envp) char *arg0, **argv, **envp;
-{
- CELL *u;
- register int i;
- register char str[4], *p;
-
- ARGC = &install("ARGC", VAR|NUM, (char *)NULL, (double)argc+1, hashtab)->c_fval;
- u = install("ARGV", ARR, (char *)NULL, 0.0, hashtab);
- u->c_sval = (char *) argtab;
- install("0", VAR|STR, arg0, 0.0, argtab);
- for (i = 0; i < argc; i++) {
- sprintf(str, "%d", i+1);
- if (isnum(argv[i]))
- install(str, VAR|STR|NUM, argv[i], atof(argv[i]), argtab);
- else
- install(str, VAR|STR, argv[i], 0.0, argtab);
- }
-
- u = install("ENVIRON", ARR, (char *)NULL, 0.0, hashtab);
- u->c_sval = (char *) envtab;
- for (i = 0; envp[i] && *envp[i]; i++) {
- if ((p = strchr(envp[i], '=')) != NULL) {
- *p = 0;
- if (isnum(p+1))
- install(envp[i], VAR|STR|NUM, p+1, atof(p+1), envtab);
- else
- install(envp[i], VAR|STR, p+1, 0.0, envtab);
- *p = '=';
- }
- }
-}
-
-static
-hash(s) unsigned char *s;
-{
- register unsigned int h;
-
- for (h = 0; *s; )
- h += *s++;
- return h % HASHSIZE;
-}
-
-CELL *
-lookup(s, h) char *s; SYMBOL *h[];
-{
- register SYMBOL *p;
-
- for (p = h[hash(s)]; p; p = p->s_next)
- if (strcmp(s, p->s_name) == 0)
- return p->s_val;
- return (CELL *)NULL;
-}
-
-static CELL *
-install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];
-{
- CELL *u;
-
- if ((u = lookup(name, h)) == (CELL *)NULL)
- u = _install(name, type, sval, fval, h);
- else
- error("%s is doubly defined", name);
- return u;
-}
-
-static CELL *
-_install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];{
- register SYMBOL *p;
- CELL *u;
- int hval;
-
- p = (SYMBOL *) emalloc(sizeof(*p));
- u = (CELL *) emalloc(sizeof(*u));
- p->s_name = strsave(name);
- p->s_val = u;
- hval = hash(name);
- p->s_next = h[hval];
- h[hval] = p;
- u->c_type = type;
- u->c_sval = strsave(sval);
-#if 0
- if (!(type & NUM) && isnum(sval)) {
- u->c_fval = atof(sval);
- u->c_type |= NUM;
- }
- else
-#endif
- u->c_fval = fval;
- return u;
-}
-
-CELL *
-getvar(s, h, typ) char *s; SYMBOL *h[];
-{
- CELL *u;
- SYMBOL *p;
- char *t;
- int i, hval;
-
- if ((u = lookup(s, h)) == (CELL *)NULL) {
- if (prmflg) {
- u = _install(s, UDF, "", 0.0, h);
- goto rtn;
- }
- else if (typ & ARR) {
- t = emalloc(sizeof(SYMBOL *) * HASHSIZE);
- for (i = 0; i < HASHSIZE; i++)
- ((SYMBOL **) t)[i] = (SYMBOL *)NULL;
- u = (CELL *) emalloc(sizeof(*u));
- u->c_type = typ;
- u->c_sval = t;
- u->c_fval = 0.0;
- p = (SYMBOL *) emalloc(sizeof(*p));
- p->s_name = strsave(s);
- p->s_val = u;
- hval = hash(s);
- p->s_next = h[hval];
- h[hval] = p;
- }
- else
- u = _install(s, typ, "", 0.0, h);
- }
- else if (!prmflg && (u->c_type == UDF) && (typ != UDF)) {
- /* fix up local_var/forward_function */
- if (typ == ARR) {
-/*
-printf("getvar_correct_to_array\n");
-*/
- u->c_type = typ;
- sfree(u->c_sval);
- u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
- for (i = 0; i < HASHSIZE; i++)
- ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
- u->c_fval = 0.0;
- }
- else if (typ != UDF) {
- u->c_type = typ;
- }
- }
-rtn:
- return u;
-}
-
-fixarray(u) CELL *u;
-{
- int i;
-
- if (u->c_type == UDF) { /* fix up local var */
-/*
-printf("fixarray\n");
-*/
- u->c_type = ARR;
- sfree(u->c_sval);
- u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
- for (i = 0; i < HASHSIZE; i++)
- ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
- u->c_fval = 0.0;
- }
-}
-
-a_free(u) CELL *u;
-{ /* free local array */
- SYMBOL **h, *q, *r;
- CELL *v;
- int i;
-
- if (!(u->c_type & ARR))
- error("try to free non array variable", (char *)0);
- h = (SYMBOL **) u->c_sval;
- for (i = 0; i < HASHSIZE; i++)
- for (q = h[i]; q; q = r) {
- r = q->s_next;
- sfree(q->s_name);
- v = q->s_val; /* CELL */
- c_free(v);
- sfree(q); /* SYMBOL */
- }
-
- sfree(u->c_sval); /* symbol table */
- c_free(u);
-}
-
-CELL *
-Array(p) NODE *p;
-{
- CELL *u;
- char str[BUFSIZ];
- int i, n;
-
- CELL *v;
-
- u = (CELL *) p->n_arg[0];
- if (u->c_type == POS) {
- i = (int)u->c_fval;
-/*
-printf("**ARG_ARRAY(%d)*\n", i);
-*/
- u = _Arg(i);
- if (u->c_type == UDF) { /* fix up local array */
-/*
-printf("local_var_to_array\n");
-*/
- fixarray(u);
- }
- }
- else if (!(u->c_type & ARR))
- error("non array refference");
- arrayelm(p, str);
- u = getvar(str, u->c_sval, VAR|NUM|STR); /* "rtsort in AWK book */
- return u;
-}
-
-static
-arrayelm(p, s) NODE *p; char *s;
-{
- CELL *u;
- int i, n;
- char *t;
-
-/*
-char *tt = s;
-*/
- n = (int) p->n_arg[1] + 2;
- for (i = 2; i < n; i++) {
- if (i > 2)
- *s++ = **SUBSEP;
- u = execute(p->n_arg[i]);
- for (t = getsval(u); *t; )
- *s++ = *t++;
- c_free(u);
- }
- *s = '\0';
-/*
-printf("array_elm(%s)\n", tt);
-*/
-}
-
-CELL *
-Element(p) NODE *p;
-{
- char str[BUFSIZ];
-
- arrayelm(p, str);
- return mktmp(STR, str, 0.0);
-}
-
-CELL *
-Delete(p) NODE *p;
-{
- CELL *u;
- char str[BUFSIZ];
- int i;
- SYMBOL *q, *r, **h;
-
- u = (CELL *) p->n_arg[0];
- if (!(u->c_type & ARR))
- error("can't delete non array variable");
- arrayelm(p, str);
- h = (SYMBOL **) u->c_sval;
- for (r = (SYMBOL *)NULL, i = hash(str), q = h[i]; q; r = q, q = q->s_next)
- if (strcmp(str, q->s_name) == 0)
- break;
- if (q) {
- sfree(q->s_val->c_sval);
- sfree(q->s_name);
- if (r)
- r->s_next = q->s_next;
- if (q == h[i])
- h[i] = (SYMBOL *)NULL;
- }
- return &truecell;
-}
-
-CELL *
-In(p) NODE *p;
-{
- SYMBOL **h, *q;
- CELL *u, *v;
- char *s;
- int i;
-
- u = (CELL *) p->n_arg[1]; /* array */
- if (!(u->c_type & ARR))
- error("%s is not an array", u->c_sval);
- h = (SYMBOL **) u->c_sval;
- if (u->c_sval != (char *)NULL) {
- v = execute(p->n_arg[0]); /* var */
- s = getsval(v);
- for (i = 0; i < HASHSIZE; i++)
- for (q = h[i]; q; q = q->s_next) {
- if (strcmp(s, q->s_name) == 0) {
- c_free(v);
- return &truecell;
- }
- }
- c_free(v);
- }
- return &falsecell;
-}
-
-CELL *
-Split(p) NODE *p;
-{
- CELL *u, *v, *w;
- char *s, *t, *h, *name, *sep;
- int i, n, skip;
- char elm[8], str[BUFSIZ];
- static char *s_str;
- static regexp *s_pat;
- regexp *mkpat();
- extern int r_start, r_length;
-
- n = (int) p->n_arg[1];
- if (n > 1) {
- u = execute(p->n_arg[2]);
- s = getsval(u); /* str */
- v = execute(p->n_arg[3]); /* array */
- if (!(v->c_type & ARR)) {
-/*
-printf("Split fix_to_array(%d)\n", v->c_type);
-*/
- if (v->c_type == UDF) /* fix up local array */
- fixarray(v);
- else
- error("split to non array variable", (char *)0);
- }
- h = v->c_sval;
- c_free(v);
- if (n > 2) {
- v = execute(p->n_arg[4]);
- sep = getsval(v);
- }
- else {
- v = (CELL *)NULL;
- sep = *FS;
- }
- if (strlen(sep) > 1) { /* reg_exp */
- if (strcmp(sep, s_str) != 0) {
- sfree(s_str); sfree(s_pat);
- s_str = strsave(sep);
- s_pat = mkpat(s_str);
- }
- for (i = 0, t = str; *s; ) {
- if (match(s_pat, s)) {
- for (n = r_start; --n > 0; )
- *t++ = *s++;
- }
- else {
- while(*s)
- *t++ = *s++;
- }
- *t = '\0';
- t = str;
- sprintf(elm, "%d", ++i);
- w = getvar(elm, h, VAR);
- if (isnum(str))
- setfval(w, atof(str));
- else
- setsval(w, str);
- if (*s)
- s += r_length;
- }
- }
- else {
- skip = *sep == ' ';
- for (i = 0; t = str, *s; ) {
- if (skip)
- while (jStrchr(" \t\n", *s))
- s++;
- if (!(*s))
- break;
- while (*s && !jStrchr(sep, *s)) {
- if (isKanji(*s))
- *t++ = *s++;
- *t++ = *s++;
- }
- *t = '\0';
- sprintf(elm, "%d", ++i);
- w = getvar(elm, h, VAR);
- if (isnum(str))
- setfval(w, atof(str));
- else
- setsval(w, str);
- if (*s && !skip)
- s++;
- }
- }
- c_free(v); /* sep */
- c_free(u); /* str may be CATed */
- }
- else
- i = 0;
- return mktmp(NUM, (char *)NULL, (double) i);
-}
-
-CELL *
-Forin(p) NODE *p;
-{
- CELL *u, *v;
- SYMBOL **h, *q;
- char *name;
- int i;
-
- u = execute(p->n_arg[1]);
- if (!(u->c_type & ARR))
- synerr(
- "non array variable is specified in 'for (. in var)'", (char *)0);
- h = (SYMBOL **) u->c_sval;
- c_free(u);
- u = execute(p->n_arg[0]);
- if (u->c_type == UDF) {
-/*
-printf("Forin_fix_to_VAR|NUM\n");
-*/
- u->c_type = VAR|NUM;
- }
- if (!(u->c_type & VAR))
- error("'for (VAR in .)' is not variable (%d)", name, u->c_type);
- for (i = 0; i < HASHSIZE; i++) {
- for (q = h[i]; q; q = q->s_next) {
- setsval(u, q->s_name);
- v = execute(p->n_arg[2]);
- c_free(v);
- }
- }
- c_free(u);
- return &truecell;
-}
-
-char *
-strsave(s) char *s;
-{
- register int n;
- char *emalloc(), *strcpy();
-
- if (s == (char *)NULL)
- return (char *)NULL;
- n = strlen(s) + 1;
- return strcpy(emalloc(n), s);
-}
-
-sfree(p) char *p;
-{
- if (p != (char *)NULL)
- Free(p);
-}
-
-isnum(s) char *s;
-{
- char *strchr();
-
- if (s == NULL || *s == '\0' || !strcmp(s, "."))
- return 0;
- if (*s && strchr("+-", *s) != (char *)NULL)
- s++;
- if (*s == '\0')
- return 0;
- while (isdigit(*s))
- s++;
- if (*s == '.') {
- s++;
- while (isdigit(*s))
- s++;
- }
- if (*s && strchr("eE", *s) != (char *)NULL) {
- s++;
- if (*s == '\0')
- return 0;
- if (*s && strchr("+-", *s) != (char *)NULL)
- s++;
- while (isdigit(*s))
- s++;
- }
- return *s == '\0';
-}
-
-setfval(u, f) CELL *u; double f;
-{
- if (u->c_type == UDF) { /* fix up local var */
-/*
-printf("setfval_fix_to_VAR\n");
-*/
- u->c_type |= VAR;
- }
- if (u->c_type & (VAR|FLD|REC|TMP)) {
- u->c_type &= ~STR;
- u->c_type |= NUM;
- sfree(u->c_sval);
- u->c_sval = (char *)NULL;
- u->c_fval = f;
- if (u->c_type & FLD)
- mkrec(u);
- }
- else
- fprintf(stderr, "assign to nonvariable (%d)\n", u->c_type);
-}
-
-setsval(u, s) CELL *u; char *s;
-{
- double atof();
-
- if (u->c_type == UDF) { /* fix up local var */
-/*
-printf("setsval_fix_to_VAR\n");
-*/
- u->c_type |= VAR;
- }
- if (u->c_type & (VAR|FLD|REC|TMP)) {
- u->c_type &= ~NUM;
- u->c_type |= STR;
- sfree(u->c_sval);
- u->c_sval = strsave(s);
-#if 0 /* "table2" in AWK book */
- if (isnum(u->c_sval)) {
- u->c_fval = atof(u->c_sval);
- u->c_type |= NUM;
- }
- else
-#endif
- u->c_fval = 0.0;
- if (u->c_type & FLD)
- mkrec(u);
- }
- else
- fprintf(stderr, "assign to constant (%d)\n", u->c_type);
-}
-
-double
-getfval(u) CELL *u;
-{
- double x, atof();
-
- if (u->c_type == UDF) { /* local var */
- u->c_type |= VAR|STR|NUM;
- u->c_sval = strsave("");
- x = u->c_fval = 0.0;
- }
- else if (u->c_type & NUM)
- x = u->c_fval;
-#if 1
- else {
- x = atof(u->c_sval);
-#else
- else {
- if (isnum(u->c_sval))
- x = atof(u->c_sval);
- else
- x = 0.0;
-#endif
- }
- return x;
-}
-
-char *
-getsval(u) CELL *u;
-{
- char *s, str[80];
-
- if (u->c_type & STR)
- s = u->c_sval;
- else if (u->c_type & NUM) {
-/* if (u->c_fval >= -2147483648.0 && u->c_fval <= 2147483647.0)*/
- if ((long)u->c_fval == u->c_fval)
- s = "%.16g";
- else
- s = *OFMT;
- sprintf(str, s, u->c_fval);
- sfree(u->c_sval);
- s = u->c_sval = strsave(str);
- }
-#if 1
- else if (u->c_type == UDF) { /* local var */
-/*
-printf("getsval_fix_to_VAR|STR\n");
-*/
- u->c_type |= VAR|STR|NUM;
- s = u->c_sval = strsave("");
- u->c_fval = 0.0;
- }
-#endif
- else
- fprintf(stderr, "abnormal value (STR|NUM == 0)(%d)\n", u->c_type);
- return s;
-}
-
-char *
-emalloc(n) unsigned n;
-{
- char *p;
-#if 0
- char far *_fmalloc();
-#else
- char *malloc();
-#endif
-
-#if 0
- if ((p = _fmalloc(n)) == (char *)NULL)
-#else
- if ((p = malloc(n)) == (char *)NULL)
-#endif
- error("memory over");
- return p;
-}
-
-Free(s) char *s;
-{
-#if DOS
- void _ffree();
-
- _ffree(s);
-#else
- free(s);
-#endif
-}
+++ /dev/null
-/*
- * a small awk clone
- *
- * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
- *
- * Absolutely no warranty. Use this software with your own risk.
- *
- * Permission to use, copy, modify and distribute this software for any
- * purpose and without fee is hereby granted, provided that the above
- * copyright and disclaimer notice.
- *
- * This program was written to fit into 64K+64K memory of the Minix 1.2.
- */
-
-
-#include <stdio.h>
-#include "awk.h"
-
-extern char *mkpat();
-
-extern char *cmd;
-extern char text[];
-extern char funnam[];
-extern int sym;
-extern int sym1;
-extern int regexflg;
-extern int funflg;
-extern int printflg;
-extern int getlineflg;
-
-extern SYMBOL *hashtab[], *funtab[];
-
-extern CELL *field[];
-
-char *emalloc(), *strsave();
-NODE *node0(), *node1(), *node2(), *node3(), *node4();
-NODE *stat(), *pastat();
-NODE *expr(), *expr1(), *expr2(), *expr3(), *expr4();
-NODE *expr5(), *expr6(), *expr7(), *expr8(), *expr9(), *expr10();
-NODE *doprint(), *dofuncn(), *doif(), *dowhile(), *dofor(), *body();
-NODE *doassign(), *dodo(), *doarray(), *doreturn(), *doelement();
-CELL *mkcell(), *getvar();
-CELL *execute(), *lookup();
-
-int forflg; /* parsing for(expr in array), inhibit 'expr in array' */
-int prmflg; /* parsing pass parameters */
-NODE *begin, *loop, *End;
-
-parse()
-{
- NODE *p, *q, *r, *stat();
- CELL *u;
-
- lex();
- skipeol();
- while (sym) {
- switch (sym) {
- case BEGIN:
- lex();
- begin = stat();
- break;
- case END:
- lex();
- if (End == NULL)
- End = stat();
- else {
- for (p = End; p; p = q) {
- if ((q = p->n_next) == NULL)
- p->n_next = stat();
- }
- }
- break;
- case FUNC:
- lex();
- dousrfun();
- break;
- default:
- q = loop = pastat();
- skipeol();
- while (sym && sym != BEGIN && sym != END && sym != FUNC) {
- r = pastat();
- q->n_next = r;
- q = r;
- skipeol();
- }
- break;
- }
- skipeol();
- }
- if (begin) {
- u = execute(begin);
- c_free(u);
- }
- if (End || loop)
- while (Getrec(NULL)) {
- if (loop) {
- u = execute(loop);
- c_free(u);
- }
- }
- if (End) {
- u = execute(End);
- c_free(u);
- }
-}
-
-#define MAXARG 100
-static char *argnam[MAXARG];
-static int narg;
-
-static
-dousrfun()
-{
- CELL *u;
-
- strcpy(funnam, text);
- u = getvar(text, funtab, FUN);
- lex();
- if (sym != '(')
- synerr("'(' expected");
- for (lex(); sym != ')'; narg++) {
- if (sym != IDENT)
- synerr("argument expected");
- argnam[narg] = strsave(text);
- lex();
- if (sym == ',')
- lex();
- }
- u->c_fval = (double) narg;
- lex();
- skipeol();
- funflg++;
- u->c_sval = (char *) stat();
- funflg--;
- if (narg > 0) {
- do {
- sfree(argnam[--narg]);
- } while (narg > 0);
- }
- skipeol();
-}
-
-isarg(s) char *s;
-{
- int i;
-
- if (narg > 0) {
- for (i = narg - 1; i >= 0; i--)
- if (strcmp(s, argnam[i]) == 0)
- break;
- }
- else
- i = -1;
- return i;
-}
-
-/*
-interactive()
-{
- NODE *p, *q;
- CELL *u;
-
- for (lex(); sym; lex()) {
- p = stat();
- if (p->n_type != PRINT && !iscntl(p->n_type)) {
- q = (NODE *) emalloc(sizeof(NODE) + sizeof(NODE *) * 4);
- q->n_type = PRINT;
- q->n_arg[0] = q->n_arg[1] = q->n_arg[3] = NULL;
- q->n_arg[2] = p;
- q->n_next = NULL;
- p = q;
- }
- u = execute(p);
- printf("[%g(%s)]\n", u->c_fval, u->c_sval);
- c_free(u);
- }
- closeall();
- exit(0);
-}
-*/
-
-static
-iscntl(t)
-{
- static int tab[] = {
- IF, DO, WHILE, FOR, JUMP, GETLINE, 0
- };
- int i;
-
- for (i = 0; tab[i]; i++)
- if (t == tab[i])
- break;
- return tab[i];
-}
-
-static NODE *
-pastat()
-{
- NODE *p, *q, *r;
-
- if (sym == '{') /* action only */
- p = stat();
- else { /* exp [, expr] [{ .. }] */
- p = expr();
- if (sym == ',') {
- lex();
- q = expr();
- }
- else
- q = NULL;
- if (sym && sym != EOL)
- r = stat();
- else
- r = node0(PRINT0);
- if (q)
- p = node3(P2STAT, p, q, r);
- else
- p = node2(P1STAT, p, r);
- }
- return p;
-}
-
-static NODE *
-stat()
-{
- NODE *p, *q, *r;
- CELL *u, *v;
- int op;
-
-/*printf("@stat(%d)(%s)\n", sym, text);*/
- while (sym == EOL)
- lex();
- switch(sym) {
- case PRINT:
- p = doprint(0);
- break;
- case PRINTF:
- p = doprint(FORMAT);
- break;
- case IF:
- p = doif();
- break;
- case WHILE:
- p = dowhile();
- break;
- case DO:
- p = dodo();
- break;
- case FOR:
- p = dofor();
- break;
- case RETURN:
- p = doreturn();
- break;
- case EXIT:
- p = node2(JUMP, (NODE *)sym, (NODE *)NULL);
- lex();
- if (sym == IDENT || sym == NUMBER || sym == ARG)
- p->n_arg[1] = expr();
- break;
- case BREAK: case CONTIN: case NEXT:
- p = node1(JUMP, (NODE *)sym);
- lex();
- break;
- case DELETE:
- lex();
- u = getvar(text, hashtab, ARR);
- if (!isarrayindex())
- synerr("'[' expected");
- p = doarray(u);
- p->n_type = DELETE;
- lex(); /* ']' */
- break;
- case '{':
- lex();
- skipeol();
- if (sym == '}')
- p = node0(NULPROC);
- else
- p = q = stat();
- skipeol();
- while (sym != '}') {
- r = stat();
- q->n_next = r;
- q = r;
- skipeol();
- }
- lex();
- break;
- default:
- p = expr();
-#if 0
- if (sym == BINOR) { /* expr | GETLINE */
- lex();
- if (sym != GETLINE)
- synerr("'GETLINE' expected");
- lex();
- if (sym == IDENT || sym == STRING || sym == ARG) {
- q = expr();
- }
- else
- q = NULL;
- p = node3(GETLINE, q, p, (NODE *)R_PIN);
- }
-#endif
- break;
- }
- if (p->n_type == VALUE)
- synerr("statement expected");
- return p;
-}
-
-static
-skipeol()
-{
- while (sym == EOL)
- lex();
-}
-
-static NODE *
-doprint(fmt)
-{
- NODE *p, *q, *r;
- CELL *u;
- int i, op;
- int n = 0;
-
- printflg++;
- lex();
- if (sym == '(')
- lex();
- if (sym != '}' && sym != ')' && sym != EOL && sym != R_OUT && sym != R_APD
- && sym != R_POUT) {
- p = q = expr(); n++;
- while (sym == ',') {
- lex();
- skipeol();
- r = expr(); n++;
- q->n_next = r;
- q = r;
- }
- }
- if (sym == ')')
- lex();
- if (sym == R_OUT || sym == R_APD || sym == R_POUT) {
- op = sym;
- lex();
-/* q = expr10();*/
- q = expr(); /* 94-04-02 */
- }
- else
- q = (NODE *) (op = 0); /* stdout */
- printflg = 0;
- r = (NODE *) emalloc(sizeof(*r) + sizeof(r) * (n + 3));
- r->n_type = PRINT; /* convert list to arg */
- r->n_next = NULL;
- r->n_arg[0] = (NODE *) (op | fmt);
- r->n_arg[1] = q;
- if (n == 0) {
- p = node1(VALUE, (NODE *)field[0]);
- }
- for (i = 2; p != NULL; i++) {
- r->n_arg[i] = p;
- q = p->n_next;
- p->n_next = NULL;
- p = q;
- }
- r->n_arg[i] = NULL;
- return r;
-}
-
-static NODE *
-doif()
-{
- NODE *p, *q, *r;
-
- lex();
- if (sym != '(')
- synerr("'(' expected");
- lex();
- p = expr();
- if (sym != ')')
- synerr("')' expected");
- lex();
- skipeol();
- q = stat();
- skipeol();
- if (sym == ELSE) {
- lex();
- skipeol();
- r = stat();
- }
- else
- r = NULL;
- return node3(IF, p, q, r);
-}
-
-static NODE *
-dowhile()
-{
- NODE *p, *q;
-
- lex();
- if (sym != '(')
- synerr("'(' expected");
- lex();
- p = stat();
- if (sym != ')')
- synerr("')' expected");
- q = body();
- return node2(WHILE, p, q);
-}
-
-static NODE *
-dofor()
-{
- NODE *p, *q, *r, *s;
- CELL *u;
- int i;
-
- lex();
- if (sym != '(')
- synerr("'(' expected");
- lex();
- if (sym != EOL) {
- forflg++; /* inhibit parsing 'expr IN array' */
- p = expr();
- forflg = 0;
- }
- else
- p = NULL;
- if (sym == IN) {
- lex();
- if (sym == ARG) {
-/*
-printf("***FOR_IN_ARG(%d)***\n", sym);
-*/
- u = mkcell(POS, NULL, (double)sym1);
- q = node1(ARG, u);
- }
- else {
- u = getvar(text, hashtab, ARR);
- q = node1(VALUE, u);
- }
- lex();
- if (sym != ')')
- synerr("')' expected");
- lex();
- skipeol();
- s = stat();
- r = node3(FORIN, p, q, s);
- }
- else {
- if (sym != EOL)
- synerr("'in' or ';' expected");
- lex();
- if (sym != EOL)
- q = expr();
- else
- q = NULL;
- if (sym != EOL)
- synerr("';' expected");
- lex();
- if (sym != ')')
- r = expr();
- else
- r = NULL;
- if (sym != ')')
- synerr("')' expected");
- s = body();
- r = node4(FOR, p, q, r, s);
- }
- return r;
-}
-
-static NODE *
-body()
-{
- NODE *r;
-
- while ((sym = Getc()) == '\n' || sym == ' ' || sym == '\t')
- ;
- if (sym == ';') {
- r = node0(NULPROC);
- lex();
- }
- else {
- Ungetc(sym);
- lex();
- r = stat();
- }
- return r;
-}
-
-static NODE *
-dodo()
-{
- NODE *p, *q;
-
- lex();
- skipeol();
- p = stat();
- skipeol();
- if (sym != WHILE)
- synerr("'while' expected");
- lex();
- if (sym != '(')
- synerr("'(' expected");
- lex();
- q = stat();
- if (sym != ')')
- synerr("')' expected");
- lex();
- return node2(DO, p, q);
-}
-
-static NODE *
-doreturn()
-{
- NODE *p, *q, *r;
- int i, n = 0;
-
- if (lex() != EOL) {
- p = q = expr(); n++;
- while (sym == ',') {
- lex(); skipeol();
- r = expr(); n++;
- q ->n_next = r;
- q = r;
- }
- }
- else
- p = (NODE *)NULL;
-
- r = (NODE *) emalloc(sizeof(*r) + sizeof (r) * (n + 1));
- r->n_type = JUMP;
- r->n_next = NULL;
- r->n_arg[0] = (NODE *) RETURN;
- for (i = 1; p != NULL; i++) {
- r->n_arg[i] = p;
- q = p->n_next;
- p->n_next = NULL;
- p = q;
- }
- r->n_arg[i] = NULL;
- return r;
-}
-
-static NODE *
-expr()
-{
- NODE *p;
-
- p = expr1();
- if (isassign(sym))
- p = doassign(sym, p);
- return p;
-}
-
-static isassign(sym)
-{
- return (sym == ASSIGN || sym == ADDEQ || sym == SUBEQ || sym == MULTEQ
- || sym == DIVEQ || sym == MODEQ || sym == POWEQ);
-}
-
-static NODE *
-doassign(op, p) NODE *p;
-{ /* evaluate right to left */
- NODE *q;
-
- lex();
- q = expr();
- if (isassign(sym))
- q = doassign(sym, q);
- return node3(ASSIGN, (NODE *)op, p, q);
-}
-
-static NODE *
-expr1()
-{
- NODE *p, *q;
-
-/*
-printf("expr1(%d)(%s)\n", sym, text);
-*/
- p = expr2();
- if (sym == '?') {
- lex();
-#if 0
- q = stat();
- if (sym != ':')
- synerr("':' expected");
- lex();
- return node3(IF, p, q, stat());
-#else
- q = expr();
- if (sym != ':')
- synerr("':' expected");
- lex();
- return node3(IF, p, q, expr());
-#endif
- }
- return p; /* 930213 */
-}
-
-static NODE *
-expr2()
-{
- NODE *p;
-
-/*
-printf("expr2(%d)(%s)\n", sym, text);
-*/
- p = expr3();
- while (sym == OR) {
- lex();
- skipeol();
- p = node3(COND, (NODE *)OR, p, expr3());
- }
- return p;
-}
-
-static NODE *
-expr3()
-{
- NODE *p;
-
-/*
-printf("expr3(%d)(%s)\n", sym, text);
-*/
- p = expr4();
- while (sym == AND) {
- lex();
- skipeol();
- p = node3(COND, (NODE *)AND, p, expr4());
- }
- return p;
-}
-
-static NODE *
-expr4()
-{
- NODE *p;
- CELL *q;
- int op;
-
-/*
-printf("expr4(%d)(%s)\n", sym, text);
-*/
- p = expr5();
- if (!forflg && sym == IN) {
- lex();
- q = getvar(text, hashtab, ARR);
- lex();
- return node2(IN, p, q);
- }
- while (sym == EQ || sym == NE || sym == LT || sym == LE || sym == GT
- || sym == GE || sym == MATCH || sym == NOMATCH) {
- op = sym;
- lex();
- p = node3(COND, (NODE *)op, p, expr5());
- }
- return p;
-}
-
-static NODE *
-expr5()
-{
- NODE *p, *q;
-
-/*
-printf("expr5(%d)(%s)\n", sym, text);
-*/
- p = expr6();
- while (iscat(sym)) {
- q = expr6();
- p = node2(CAT, p, q);
- }
- return p;
-}
-
-static iscat(sym)
-{
- static int ctab[] = {
- ADD, SUB, MULT, DIV, MOD, INC, DEC, STRING, NUMBER, IDENT, '(',
- MATHFUN, STRFUN, SPRINTF, '$', SUBST, ARG, CALL, 0
- };
- register int i, j;
-
- for (i = 0; j = ctab[i]; i++)
- if (sym == j)
- break;
- return j;
-}
-
-static NODE *
-expr6()
-{
- register int sign = sym;
- NODE *p, *q;
-
-/*
-printf("expr6(%d)(%s)\n", sym, text);
-*/
- if (sym == SUB || sym == ADD)
- lex();
- p = expr7();
- if (sign == SUB)
- p = node2(ARITH, (NODE *)UMINUS, p);
- while (sym == ADD || sym == SUB) {
- sign = sym;
- lex();
- q = expr7();
- if (sign == ADD) {
- p = node3(ARITH, (NODE *)ADD, p, q);
- }
- else if (sign == SUB) {
- p = node3(ARITH, (NODE *)SUB, p, q);
- }
- else
- synerr("'+' or '-' expected");
- }
- return p;
-}
-
-static NODE *
-expr7()
-{
- register int op;
- NODE *p, *q;
-
-/*
-printf("expr7(%d)(%s)\n", sym, text);
-*/
- p = expr8();
- while (sym == MULT || sym == DIV || sym == MOD) {
- op = sym;
- lex();
- q = expr8();
- switch (op) {
- case MULT: p = node3(ARITH, (NODE *)MULT, p, q); break;
- case DIV: p = node3(ARITH, (NODE *)DIV, p, q); break;
- case MOD: p = node3(ARITH, (NODE *)MOD, p, q); break;
- default: synerr("'*', '/' or '%' expected"); break;
- }
- }
- return p;
-}
-
-static NODE *
-expr8()
-{
- NODE *p;
- int op;
-
-/*
-printf("expr8(%d)(%s)\n", sym, text);
-*/
- if (sym == NOT) {
- lex();
- p = node2(COND, (NODE *)NOT, expr9());
- }
- else {
- p = expr9();
- if (sym == POWER) {
- lex();
- p = node3(ARITH, (NODE *)POWER, p, expr9());
- }
- }
- return p;
-}
-
-static NODE *
-expr9()
-{
- NODE *p, *q;
- int op, sym0;
-
-/*
-printf("expr9(%d)(%s)\n", sym, text);
-*/
- if (op = isincdec(sym)) {
- lex();
- if (sym != IDENT && sym != ARG)
- synerr("illegal '++/--' operator");
- p = expr10();
- p = node4(ARITH, (NODE *)INCDEC, p, (NODE *)op, (NODE *)PRE);
- }
- else {
- sym0 = sym;
- p = expr10();
- if (op = isincdec(sym)) {
-/*printf("POST(%d)(%d)(%s)\n", sym, sym0, text);*/
- if (sym0 == IDENT || sym0 == ARG) {
- p = node4(ARITH, (NODE *)INCDEC, p, (NODE *)op,
- (NODE *)POST);
- lex();
- }
- }
- if (sym == BINOR) { /* | getline */
- lex();
- if (sym != GETLINE)
- synerr("'GETLINE' expected");
- lex();
- if (sym == IDENT || sym == STRING || sym == ARG) {
- q = expr();
- }
- else
- q = NULL;
- p = node3(GETLINE, q, p, (NODE *)R_PIN);
- }
- }
- return p;
-}
-
-static isincdec(sym)
-{
- return sym == INC ? 1 : (sym == DEC ? -1 : 0);
-}
-
-static NODE *
-expr10()
-{
- NODE *p, *q;
- CELL *u, *v;
- int op;
- int c;
-int gsave, psave;
- double atof();
-
-/*
-printf("expr10(%d)(%s)\n", sym, text);
-*/
- switch (sym) {
- case STRING:
- u = mkcell(STR, text, 0.0);
- goto g1;
- case NUMBER:
- u = mkcell(NUM, NULL, atof(text));
-g1:
- p = node1(VALUE, u);
- lex();
- break;
- case IDENT: case ARG:
- if (isarrayindex()) { /* array */
- /* 940403 */
- if (sym == ARG) {
- u = (CELL *)emalloc(sizeof(CELL));
- u = mkcell(POS, NULL, (double)sym1);
- p = doarray(u);
- }
- else {
- u = getvar(text, hashtab, ARR);
- p = doarray(u);
- }
- }
- else {
- if (sym == ARG) {
- u = mkcell(POS, NULL, (double)sym1);
- p = node1(ARG, u);
- }
- else { /* symple variable */
- u = getvar(text, hashtab, VAR|STR|NUM);
- p = node1(VALUE, u);
- }
- }
- lex();
- break;
- case '(':
- /* print >(x ? y : z) needs this */
-gsave = getlineflg; psave = printflg;
-getlineflg = printflg = 0;
- lex();
- p = expr();
- if (sym == ',') /* (expr, expr, .. ) */
- p = doelement(p);
- if (sym != ')')
- synerr("')' expected");
-getlineflg = gsave; printflg = psave;
- lex();
- break;
- case CALL:
- p = dofuncn(sym, getvar(text, funtab, UDF));
- break;
- case MATHFUN: case STRFUN: case SUBST:
- p = dofuncn(sym, (CELL *)sym1);
- break;
- case SPRINTF:
- p = doprint(FORMAT|STROUT);
- break;
- case '$':
- lex();
- switch (sym) {
- case NUMBER:
- u = mkcell(NUM, NULL, atof(text));
- p = node1(VALUE, u);
- p = node1(FIELD, p);
- lex();
- break;
- case IDENT: case ARG: case '(':
- p = node1(FIELD, expr10());
- break;
- default:
- synerr("number or identifier expected after '$'", (char *)0);
- }
- break;
- case DIV:
- regexflg++;
- lex();
- regexflg = 0;
- u = mkcell(PAT, NULL, 0.0);
- u->c_sval = (char *) mkpat(text);
- p = node1(VALUE, u);
- lex();
- break;
- case GETLINE:
- getlineflg++;
- lex();
- if (sym == IDENT || sym == STRING || sym == ARG)
- q = expr10(); /* read into var */
- else
- q = NULL;
- getlineflg = 0;
- if (sym == R_IN) {
- op = R_IN;
- lex();
- p = expr10();
- }
- else
- op = (int) (p = NULL);
- p = node3(GETLINE, q, p, (NODE *)op);
- break;
- default:
- synerr(
- "identifier, number, string, argument, regexpr, call or '(' expected");
- break;
- }
- return p;
-}
-
-static NODE *
-dofuncn(fun, op) CELL *op;
-{
- NODE *p;
- int i, j;
- int n = 0;
- NODE *a[100];
-
- if (lex() == '(') {
- prmflg++;
- for (lex(); sym && (sym != ')'); n++) {
- if ((int)op == SPLIT && n == 1) {
-/*
-printf("sym(%d)sym1(%d)(%d)\n", sym, sym1, isarg(text));
-*/
- if (sym != ARG) { /*isarg(text) == -1*/
- /* make an array if not exist */
- prmflg = 0;
- getvar(text, hashtab, ARR);
- prmflg++;
- }
- }
- a[n] = expr();
- if (sym == ',')
- lex();
- else if (sym != ')')
- synerr("',' or ')' expected");
- }
- prmflg = 0;
-
- if (sym == ')')
- lex();
- else
- synerr("')' expected");
- }
- p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 2));
- p->n_type = fun;
- p->n_next = NULL;
- p->n_arg[0] = (NODE *) op;
- p->n_arg[1] = (NODE *) n;
- for (i = 0, j = 2; i < n; )
- p->n_arg[j++] = a[i++];
- p->n_arg[j] = NULL;
- return p;
-}
-
-static NODE *
-doarray(u) CELL *u;
-{
- NODE *p;
- int i, j;
- int n;
- NODE *a[20];
-
- for (lex(), n = 0; sym && sym != ']'; n++) {
- a[n] = expr();
- if (sym == ',')
- lex();
- }
- if (sym != ']')
- synerr("']' expected");
- /* left ']' for expr10() */
- p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 1));
- p->n_type = ARRAY;
- p->n_next = NULL;
- p->n_arg[0] = (NODE *)u;
- p->n_arg[1] = (NODE *) n;
- for (i = 0, j = 2; i < n; )
- p->n_arg[j++] = a[i++];
- return p;
-}
-
-static NODE *
-doelement(q) NODE *q;
-{
- NODE *p;
- int i, j;
- int n;
- NODE *a[20];
-
- a[0] = q;
- for (lex(), n = 1; sym && sym != ')'; n++) {
- a[n] = expr();
- if (sym == ',')
- lex();
- else if (sym != ')')
- synerr("',' or ')' expected");
- }
- /* left ')' for expr10() */
- p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 1));
- p->n_type = ELEMENT;
- p->n_next = NULL;
- p->n_arg[0] = NULL;
- p->n_arg[1] = (NODE *) n;
- for (i = 0, j = 2; i < n; )
- p->n_arg[j++] = a[i++];
- return p;
-}
-
-synerr(s, t) char *s, *t;
-{
- extern int lineno;
- extern char line[], *linep;
- int c, i;
- char *u, *v;
-
- fprintf(stderr, "%s: Syntax error at line %d", cmd, lineno);
- if (funflg)
- fprintf(stderr, " in function %s", funnam);
- fprintf(stderr, ":\n");
- if ((v = linep - 1) < line)
- v = line + BUFSIZ - 1;
- for (i = 0, u = v - 1; ; --u) {
- if (u < line) {
- if (line[BUFSIZ - 1] == '\0')
- break;
- u = line + BUFSIZ - 1;
- }
- if (*u == '\n' && ++i == 2)
- break;
- }
- if (u != v) {
- while (u != v) {
- fputc(*u, stderr);
- if ((++u - line) == BUFSIZ)
- u = line;
- }
- if (*u != '\n')
- fputc(*u, stderr);
- fprintf(stderr, " <--\n\n");
-/*
- fprintf(stderr, " <-- ");
- while ((c = Getc()) != EOF && c != '\n')
- fputc(c, stderr);
- fprintf(stderr, "\n");
- if (c == EOF);
- fprintf(stderr, "\n");
-*/
- }
- fprintf(stderr, s, t);
- fprintf(stderr, "\n");
-#ifdef DOS
- closeall();
-#endif
- exit(1);
-}