Source code upload

This commit is contained in:
calmsacibis995
2022-09-29 17:59:04 +03:00
parent 72fa9da3d7
commit 8fc8fa8089
33399 changed files with 11964078 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
#ident "@(#)awk:EXPLAIN 1.2"
Nov 30, 1979:
Awk has been modified yet again, in an attempt to make
its behavior more rational and predictable in the areas
of initialization, comparison, and type coercion.
Herewith what we believe the current truth to be:
1. Each variable and field can potentially be a string
or a number or both at any time.
When a variable is set by the assignment
v = expr
its type is set to that of expr. (This includes +=, ++, etc.)
An arithmetic expression is of type number, a
concatenation is of type string, and so on.
If the assignment is a simple copy, as in
v1 = v2
then the type of v1 becomes that of v2.
2. In comparisons, if both operands are numeric,
the comparison is made numerically. Otherwise,
operands are coerced to string if necessary, and
the comparison is made on strings.
3. The type of any expression can be coerced to
numeric by subterfuges (kludges?) such as
expr + 0
and to string by
expr ""
(i.e., concatenation with a null string).
4. Uninitialized variables have the numeric value
0 and the string value "". Accordingly, if x is
uninitialized,
if (x) ...
is false, and
if (!x) ...
if (x == 0) ...
if (x == "") ...
are all true. But note that
if (x == "0") ...
is false.
5. The type of a field is determined by context
when possible; for example,
$1++
clearly implies that $1 is to be numeric, and
$1 = $1 "," $2
implies that $1 and $2 are both to be strings.
Coercion will be done as needed.
In contexts where types cannot be reliably determined, e.g.,
if ($1 == $2) ...
the type of each field is determined on input by
inspection. All fields are strings; in addition,
each field that contains only a number (in the
sense of Fortran, say) is also considered numeric.
This ensures (for better or worse) that the test
if ($1 == $2) ...
will succeed on the inputs
0 0.0
100 1e2
+100 100
1e-3 1e-3
and fail on the inputs
(null) 0
(null) 0.0
2E-518 6E-427
as we believe it should.
Fields which are explicitly null have the string
value ""; they are not numeric.
Non-existent fields (i.e., fields past NF) are
treated this way too.
As it is for fields, so it is for array elements
created by split(...).
6. There is no warranty of merchantability nor any warranty
of fitness for a particular purpose nor any other warranty,
either express or implied, as to the accuracy of the
enclosed materials or as to their suitability for any
particular purpose. Accordingly, the AWK Development
Task Force assumes no responsibility for their use by the
recipient. Further, the Task Force assumes no obligation
to furnish any assistance of any kind whatsoever, or to
furnish any additional information or documentation.
+50
View File
@@ -0,0 +1,50 @@
#!smake
#
# Makefile for nawk(1).
#
#ident "$Revision: 1.18 $"
BASEVERSION=n32bit
ALTVERSIONS=troot
WANTPARALLEL=yes-please
include $(ROOT)/usr/include/make/cmdcommondefs
LFILES= awk.lx.l
YFILES= awk.g.y
CFILES= b.c lib.c main.c parse.c run.c tran.c
COMMANDS=nawk
LLDLIBS=-lw -lm
GLDOPTS=
LDIRT= maketab awk.g.c y.tab.h proctab.[co]
default: y.tab.h $(TARGETS)
include $(CMDCOMMONRULES)
TLINKXARGS+=-x maketab -x awk.g.c -x proctab.c
n32bitinstall: default
$(INSTALL) -F /usr/bin $(COMMANDS)
$(INSTALL) -ln $(COMMANDS) -F /usr/bin awk
trootinstall: default
$(INSTALL) -F /usr/bin $(COMMANDS)
$(OBJECTS): y.tab.h
y.tab.h: awk.g.y
$(YACCF) -d awk.g.y
mv y.tab.c awk.g.c
awk.g.c: y.tab.h
proctab.c: maketab
./maketab > $@
# Maketab should be built using native tools, since it's an intermediate
# tool that doesn't ship.
maketab: $$@.c y.tab.h
${HOST_CC} $@.c -o $@
CVERSION= -cckr
nawk: $(OBJECTS) proctab.o
$(CC) $(CFLAGS) $(OBJECTS) proctab.o $(LDFLAGS) -o $@
+100
View File
@@ -0,0 +1,100 @@
#ident "@(#)awk:README 1.2"
CHANGES as of July 12:
1. \ddd allowed in regular expressions.
2. exit <expression> causes the expression to
to be the status return upon completion.
3. a new builtin called "getline" causes the next
input line to be read immediately. Fields, NR, etc.,
are all set, but you are left at exactly the same place
in the awk program. Getline returns 0 for end of file;
1 for a normal record.
CHANGES SINCE MEMO:
Update to TM of Sept 1, 1978:
1. A new form of for loop
for (i in array)
statement
is now available. It provides a way to walk
along the members of an array, most usefully
for associative arrays with non-numeric subscripts.
Elements are accessed in an unpredictable order,
so don't count on anything.
Futhermore, havoc ensues if elements are created
during this operation, or if the index variable
is fiddled.
2. index(s1, s2) returns the position in s1
where s2 first occurs, or 0 if it doesn't.
3. Multi-line records are now supported more
conveniently. If the record separator is null
RS = ""
then a blank line terminates a record, and newline
is a default field separator, along with
blank and tab.
4. The syntax of split has been changed.
n = split(str, arrayname, sep)
splits the string str into the array using
the separator sep (a single character).
If no sep field is given, FS is used instead.
The elements are array[1] ... array[n]; n
is the function value.
5. some minor bugs have been fixed.
IMPLEMENTATION NOTES:
Things to watch out for when trying to make awk:
1. The yacc -d business creates a new file y.tab.h
with the yacc #defines in it. this is compared to
awk.h on each successive compile, and major recompilation
is done only if the files differ. (This permits editing
the grammar file without causing everything in sight
to be recompiled, so long as the definitions don't
change.)
2. The program proc.c is compiled into proc, which
is used to create proctab.c. proctab.c is the
table of function pointers used by run to actually
execute things. Don't try to load proc.c with the
other .c files; it also contains a "main()".
3. Awk uses structure assignment. Be sure your
version of the C compiler has it.
4. The loader flag -lm is used to fetch the standard
math library on the Research system. It is more likely
that you will want to use -lS on yours.
run.c also includes "math.h", which contains sensible
definitions for log(), sqrt(), etc. If you don't have this
include file, comment the line out, and all will be well
anyway.
5. The basic sequence of events (in case make doesn't
seem to do the job) is
yacc -d awk.g.y
cc -O -c y.tab.c
mv y.tab.o awk.g.o
lex awk.lx.l
cc -O -c lex.yy.c
mv lex.yy.o awk.lx.o
cc -O -c b.c
cc -O -c main.c
e - <tokenscript
cc -O -c token.c
cc -O -c tran.c
cc -O -c lib.c
cc -O -c run.c
cc -O -c parse.c
cc -O -c proc.c
cc -o proc proc.c token.o
proc >proctab.c
cc -O -c proctab.c
cc -i -O awk.g.o awk.lx.o b.o main.o token.o tran.o lib.o run.o parse.o proctab.o -lm
+128
View File
@@ -0,0 +1,128 @@
/* #ident "@(#)awk:awk.def 1.3" */
#ident "$Header: /proj/irix6.5.7m/isms/eoe/cmd/awk/RCS/awk.def,v 1.5 1987/01/24 17:26:17 bruce Exp $"
#define xfree(a) { if(a!=NULL) { yfree(a); a=NULL;} }
#define yfree free
#ifdef DEBUG
# define dprintf if(dbg)printf
#else
# define dprintf(x1, x2, x3, x4)
#endif
typedef double awkfloat;
extern char **FS;
extern char **RS;
extern char **ORS;
extern char **OFS;
extern char **OFMT;
extern awkfloat *NR;
extern awkfloat *NF;
extern char **FILENAME;
extern char *record;
extern int dbg;
extern int lineno;
extern int errorflag;
extern int donefld; /* 1 if record broken into fields */
extern int donerec; /* 1 if record is valid (no fld has changed */
/* CELL: all information about a variable or constant */
typedef struct val {
char ctype; /* CELL, BOOL, JUMP, etc. */
char csub; /* subtype of ctype */
char *nval; /* name, for variables only */
char *sval; /* string value */
awkfloat fval; /* value as number */
unsigned tval; /* type info */
struct val *nextval; /* ptr to next if chained */
} CELL;
extern CELL *symtab[];
extern CELL *setsymtab(), *lookup(), **makesymtab();
extern CELL *recloc; /* location of input record */
extern CELL *nrloc; /* NR */
extern CELL *nfloc; /* NF */
/* CELL.tval values: */
#define STR 01 /* string value is valid */
#define NUM 02 /* number value is valid */
#define FLD 04 /* FLD means don't free string space */
#define CON 010 /* this is a constant */
#define ARR 020 /* this is an array */
awkfloat setfval(), getfval();
char *setsval(), *getsval();
char *tostring(), *tokname(), *malloc();
double log(), sqrt(), exp(), atof();
/* function types */
#define FLENGTH 1
#define FSQRT 2
#define FEXP 3
#define FLOG 4
#define FINT 5
#define BOTCH 1
typedef struct nd {
char ntype;
char subtype;
struct nd *nnext;
int nobj;
struct nd *narg[BOTCH]; /* C won't take a zero length array */
} NODE;
extern NODE *winner;
extern NODE *nullstat;
/* ctypes */
#define OCELL 1
#define OBOOL 2
#define OJUMP 3
/* CELL subtypes */
#define CCON 5
#define CTEMP 4
#define CNAME 3
#define CVAR 2
#define CFLD 1
/* bool subtypes */
#define BTRUE 1
#define BFALSE 2
/* jump subtypes */
#define JEXIT 1
#define JNEXT 2
#define JBREAK 3
#define JCONT 4
/* node types */
#define NVALUE 1
#define NSTAT 2
#define NEXPR 3
extern CELL *(*proctab[])();
extern int pairstack[], paircnt;
#define cantexec(n) (n->ntype == NVALUE)
#define notlegal(n) (n <= FIRSTTOKEN || n >= LASTTOKEN || proctab[n-FIRSTTOKEN]== nullproc)
#define isexpr(n) (n->ntype == NEXPR)
#define isjump(n) (n->ctype == OJUMP)
#define isexit(n) (n->ctype == OJUMP && n->csub == JEXIT)
#define isbreak(n) (n->ctype == OJUMP && n->csub == JBREAK)
#define iscont(n) (n->ctype == OJUMP && n->csub == JCONT)
#define isnext(n) (n->ctype == OJUMP && n->csub == JNEXT)
#define isstr(n) (n->tval & STR)
#define isnum(n) (n->tval & NUM)
#define istrue(n) (n->ctype == OBOOL && n->csub == BTRUE)
#define istemp(n) (n->ctype == OCELL && n->csub == CTEMP)
#define isfld(n) (!donefld && n->csub==CFLD && n->ctype==OCELL && n->nval==0)
#define isrec(n) (donefld && n->csub==CFLD && n->ctype==OCELL && n->nval!=0)
extern CELL *nullproc();
extern CELL *relop();
#define MAXSYM 50
#define HAT 0177 /* matches ^ in regular expr */
/* watch out for mach dep */
#define MAKE_SVAL(s) ((s) ? (s) : tostring("")) /* Prevent NULL sval */
+452
View File
@@ -0,0 +1,452 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
%{
#ident "@(#)awk:awk.g.y 2.12"
%}
%{
#include "awk.h"
#include <pfmt.h>
yywrap() { return(1); }
#ifndef DEBUG
# define PUTS(x)
#endif
Node *beginloc = 0, *endloc = 0;
int infunc = 0; /* = 1 if in arglist or body of func */
uchar *curfname = 0;
Node *arglist = 0; /* list of args for current function */
uchar *strnode();
Node *notnull();
extern const char illstat[];
void setfname();
%}
%union {
Node *p;
Cell *cp;
int i;
uchar *s;
}
%token <i> FIRSTTOKEN /* must be first */
%token <p> PROGRAM PASTAT PASTAT2 XBEGIN XEND
%token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
%token <i> ARRAY
%token <i> MATCH NOTMATCH MATCHOP
%token <i> FINAL DOT ALL CCL NCCL CHAR MCHAR OR STAR QUEST PLUS
%token <i> AND BOR APPEND EQ GE GT LE LT NE IN
%token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
%token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT
%token <i> ADD MINUS MULT DIVIDE MOD
%token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
%token <i> PRINT PRINTF SPRINTF
%token <p> ELSE INTEST CONDEXPR
%token <i> POSTINCR PREINCR POSTDECR PREDECR
%token <cp> VAR IVAR VARNF CALL NUMBER STRING FIELD
%token <s> REGEXPR
%type <p> pas pattern ppattern plist pplist patlist prarg term
%type <p> pa_pat pa_stat pa_stats
%type <s> reg_expr
%type <p> simple_stmt opt_simple_stmt stmt stmtlist
%type <p> var varname funcname varlist
%type <p> for if while
%type <i> pst opt_pst lbrace rparen comma nl opt_nl and bor
%type <i> subop print
%right ASGNOP
%right '?'
%right ':'
%left BOR
%left AND
%left GETLINE
%nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
%left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FIELD FUNC
%left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
%left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
%left REGEXPR VAR VARNF IVAR WHILE '('
%left CAT
%left '+' '-'
%left '*' '/' '%'
%left NOT UMINUS
%right POWER
%right DECR INCR
%left INDIRECT
%token LASTTOKEN /* must be last */
%%
program:
pas { if (errorflag==0)
winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
| error { yyclearin; bracecheck(); vyyerror(":95:Bailing out"); }
;
and:
AND | and NL
;
bor:
BOR | bor NL
;
comma:
',' | comma NL
;
do:
DO | do NL
;
else:
ELSE | else NL
;
for:
FOR '(' opt_simple_stmt ';' pattern ';' opt_simple_stmt rparen stmt
{ $$ = stat4(FOR, $3, notnull($5), $7, $9); }
| FOR '(' opt_simple_stmt ';' ';' opt_simple_stmt rparen stmt
{ $$ = stat4(FOR, $3, NIL, $6, $8); }
| FOR '(' varname IN varname rparen stmt
{ $$ = stat3(IN, $3, makearr($5), $7); }
;
funcname:
VAR { setfname($1); }
| CALL { setfname($1); }
;
if:
IF '(' pattern rparen { $$ = notnull($3); }
;
lbrace:
'{' | lbrace NL
;
nl:
NL | nl NL
;
opt_nl:
/* empty */ { $$ = 0; }
| nl
;
opt_pst:
/* empty */ { $$ = 0; }
| pst
;
opt_simple_stmt:
/* empty */ { $$ = 0; }
| simple_stmt
;
pas:
opt_pst { $$ = 0; }
| opt_pst pa_stats opt_pst { $$ = $2; }
;
pa_pat:
pattern { $$ = notnull($1); }
;
pa_stat:
pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
| pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); }
| pa_pat ',' pa_pat { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
| pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); }
| lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); }
| XBEGIN lbrace stmtlist '}'
{ beginloc = linkum(beginloc, $3); $$ = 0; }
| XEND lbrace stmtlist '}'
{ endloc = linkum(endloc, $3); $$ = 0; }
| FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}'
{ infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; }
;
pa_stats:
pa_stat
| pa_stats opt_pst pa_stat { $$ = linkum($1, $3); }
;
patlist:
pattern
| patlist comma pattern { $$ = linkum($1, $3); }
;
ppattern:
var ASGNOP ppattern { $$ = op2($2, $1, $3); }
| ppattern '?' ppattern ':' ppattern %prec '?'
{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
| ppattern bor ppattern %prec BOR
{ $$ = op2(BOR, notnull($1), notnull($3)); }
| ppattern and ppattern %prec AND
{ $$ = op2(AND, notnull($1), notnull($3)); }
| NOT ppattern
{ $$ = op1(NOT, notnull($2)); }
| ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
| ppattern MATCHOP ppattern
{ if (constnode($3))
$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
else
$$ = op3($2, (Node *)1, $1, $3); }
| ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
| '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
| ppattern term %prec CAT { $$ = op2(CAT, $1, $2); }
| reg_expr
{ $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
| term
;
pattern:
var ASGNOP pattern { $$ = op2($2, $1, $3); }
| pattern '?' pattern ':' pattern %prec '?'
{ $$ = op3(CONDEXPR, notnull($1), $3, $5); }
| pattern bor pattern %prec BOR
{ $$ = op2(BOR, notnull($1), notnull($3)); }
| pattern and pattern %prec AND
{ $$ = op2(AND, notnull($1), notnull($3)); }
| NOT pattern
{ $$ = op1(NOT, op2(NE,$2,valtonode(lookup("$zero&null",symtab),CCON))); }
| pattern EQ pattern { $$ = op2($2, $1, $3); }
| pattern GE pattern { $$ = op2($2, $1, $3); }
| pattern GT pattern { $$ = op2($2, $1, $3); }
| pattern LE pattern { $$ = op2($2, $1, $3); }
| pattern LT pattern { $$ = op2($2, $1, $3); }
| pattern NE pattern { $$ = op2($2, $1, $3); }
| pattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
| pattern MATCHOP pattern
{ if (constnode($3))
$$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
else
$$ = op3($2, (Node *)1, $1, $3); }
| pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
| '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
| pattern '|' GETLINE var { $$ = op3(GETLINE, $4, (Node*)$2, $1); }
| pattern '|' GETLINE { $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); }
| pattern term %prec CAT { $$ = op2(CAT, $1, $2); }
| reg_expr
{ $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
| term
;
plist:
pattern comma pattern { $$ = linkum($1, $3); }
| plist comma pattern { $$ = linkum($1, $3); }
;
pplist:
ppattern
| pplist comma ppattern { $$ = linkum($1, $3); }
;
prarg:
/* empty */ { $$ = rectonode(); }
| pplist
| '(' plist ')' { $$ = $2; }
;
print:
PRINT | PRINTF
;
pst:
NL | ';' | pst NL | pst ';'
;
rbrace:
'}' | rbrace NL
;
reg_expr:
'/' {startreg();} REGEXPR '/' { $$ = $3; }
;
rparen:
')' | rparen NL
;
simple_stmt:
print prarg '|' term { $$ = stat3($1, $2, (Node *) $3, $4); }
| print prarg APPEND term { $$ = stat3($1, $2, (Node *) $3, $4); }
| print prarg GT term { $$ = stat3($1, $2, (Node *) $3, $4); }
| print prarg GT pattern { $$ = stat3($1, $2, (Node *) $3, $4); }
| print prarg { $$ = stat3($1, $2, NIL, NIL); }
| DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
| DELETE varname { yyclearin; vyyerror(":96:You can only delete array[element]"); $$ = stat1(DELETE, $2); }
| pattern { $$ = exptostat($1); }
| error { yyclearin; vyyerror(illstat); }
;
st:
nl | ';' opt_nl
;
stmt:
BREAK st { $$ = stat1(BREAK, NIL); }
| CLOSE pattern st { $$ = stat1(CLOSE, $2); }
| CONTINUE st { $$ = stat1(CONTINUE, NIL); }
| do stmt WHILE '(' pattern ')' st
{ $$ = stat2(DO, $2, notnull($5)); }
| EXIT pattern st { $$ = stat1(EXIT, $2); }
| EXIT st { $$ = stat1(EXIT, NIL); }
| for
| if stmt else stmt { $$ = stat3(IF, $1, $2, $4); }
| if stmt { $$ = stat3(IF, $1, $2, NIL); }
| lbrace stmtlist rbrace { $$ = $2; }
| NEXT st { if (infunc)
vyyerror(":97:Next is illegal inside a function");
$$ = stat1(NEXT, NIL); }
| RETURN pattern st { $$ = stat1(RETURN, $2); }
| RETURN st { $$ = stat1(RETURN, NIL); }
| simple_stmt st
| while stmt { $$ = stat2(WHILE, $1, $2); }
| ';' opt_nl { $$ = 0; }
;
stmtlist:
stmt
| stmtlist stmt { $$ = linkum($1, $2); }
;
subop:
SUB | GSUB
;
term:
term '+' term { $$ = op2(ADD, $1, $3); }
| term '-' term { $$ = op2(MINUS, $1, $3); }
| term '*' term { $$ = op2(MULT, $1, $3); }
| term '/' term { $$ = op2(DIVIDE, $1, $3); }
| term '%' term { $$ = op2(MOD, $1, $3); }
| term POWER term { $$ = op2(POWER, $1, $3); }
| '-' term %prec UMINUS { $$ = op1(UMINUS, $2); }
| '+' term %prec UMINUS { $$ = $2; }
| BLTIN '(' ')' { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
| BLTIN '(' patlist ')' { $$ = op2(BLTIN, (Node *) $1, $3); }
| BLTIN { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
| CALL '(' ')' { $$ = op2(CALL, valtonode($1,CVAR), NIL); }
| CALL '(' patlist ')' { $$ = op2(CALL, valtonode($1,CVAR), $3); }
| DECR var { $$ = op1(PREDECR, $2); }
| INCR var { $$ = op1(PREINCR, $2); }
| var DECR { $$ = op1(POSTDECR, $1); }
| var INCR { $$ = op1(POSTINCR, $1); }
| GETLINE var LT term { $$ = op3(GETLINE, $2, (Node *)$3, $4); }
| GETLINE LT term { $$ = op3(GETLINE, NIL, (Node *)$2, $3); }
| GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); }
| GETLINE { $$ = op3(GETLINE, NIL, NIL, NIL); }
| INDEX '(' pattern comma pattern ')'
{ $$ = op2(INDEX, $3, $5); }
| INDEX '(' pattern comma reg_expr ')'
{ vyyerror(":98:Index() doesn't permit regular expressions");
$$ = op2(INDEX, $3, (Node*)$5); }
| '(' pattern ')' { $$ = $2; }
| MATCHFCN '(' pattern comma reg_expr ')'
{ $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); }
| MATCHFCN '(' pattern comma pattern ')'
{ if (constnode($5))
$$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
else
$$ = op3(MATCHFCN, (Node *)1, $3, $5); }
| NUMBER { $$ = valtonode($1, CCON); }
| SPLIT '(' pattern comma varname comma pattern ')' /* string */
{ $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
| SPLIT '(' pattern comma varname comma reg_expr ')' /* const /regexp/ */
{ $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); }
| SPLIT '(' pattern comma varname ')'
{ $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); } /* default */
| SPRINTF '(' patlist ')' { $$ = op1($1, $3); }
| STRING { $$ = valtonode($1, CCON); }
| subop '(' reg_expr comma pattern ')'
{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); }
| subop '(' pattern comma pattern ')'
{ if (constnode($3))
$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode());
else
$$ = op4($1, (Node *)1, $3, $5, rectonode()); }
| subop '(' reg_expr comma pattern comma var ')'
{ $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); }
| subop '(' pattern comma pattern comma var ')'
{ if (constnode($3))
$$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7);
else
$$ = op4($1, (Node *)1, $3, $5, $7); }
| SUBSTR '(' pattern comma pattern comma pattern ')'
{ $$ = op3(SUBSTR, $3, $5, $7); }
| SUBSTR '(' pattern comma pattern ')'
{ $$ = op3(SUBSTR, $3, $5, NIL); }
| var
;
var:
varname
| varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); }
| FIELD { $$ = valtonode($1, CFLD); }
| IVAR { $$ = op1(INDIRECT, valtonode($1, CVAR)); }
| INDIRECT term { $$ = op1(INDIRECT, $2); }
;
varlist:
/* nothing */ { arglist = $$ = 0; }
| VAR { arglist = $$ = valtonode($1,CVAR); }
| varlist comma VAR { arglist = $$ = linkum($1,valtonode($3,CVAR)); }
;
varname:
VAR { $$ = valtonode($1, CVAR); }
| ARG { $$ = op1(ARG, (Node *) $1); }
| VARNF { $$ = op1(VARNF, (Node *) $1); }
;
while:
WHILE '(' pattern rparen { $$ = notnull($3); }
;
%%
void
setfname(p)
Cell *p;
{
if (isarr(p))
vyyerror(":99:%s is an array, not a function", p->nval);
else if (isfunc(p))
vyyerror(":100:You cannot define function %s more than once", p->nval);
curfname = p->nval;
}
constnode(p)
Node *p;
{
return p->ntype == NVALUE && ((Cell *) (p->narg[0]))->csub == CCON;
}
uchar *strnode(p)
Node *p;
{
return ((Cell *)(p->narg[0]))->sval;
}
Node *notnull(n)
Node *n;
{
switch (n->nobj) {
case LE: case LT: case EQ: case NE: case GT: case GE:
case BOR: case AND: case NOT:
return n;
default:
return op2(NE, n, nullnode);
}
}
+221
View File
@@ -0,0 +1,221 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)awk:awk.h 2.13"
typedef double Awkfloat;
typedef unsigned char uchar;
#define xfree(a) { if ((a) != NULL) { free(a); a = NULL; } }
#define DEBUG
#ifdef DEBUG
/* uses have to be doubly parenthesized */
# define dprintf(x) if (dbg) printf x
#else
# define dprintf(x)
#endif
extern char errbuf[200];
#define ERROR sprintf(errbuf,
#define FATAL ), error(1, errbuf)
#define WARNING ), error(0, errbuf)
#define SYNTAX ), yyerror(errbuf)
extern int compile_time; /* 1 if compiling, 0 if running */
#define RECSIZE (3 * 1024) /* sets limit on records, fields, etc., etc. */
extern uchar **FS;
extern uchar **RS;
extern uchar **ORS;
extern uchar **OFS;
extern uchar **OFMT;
extern Awkfloat *NR;
extern Awkfloat *FNR;
extern Awkfloat *NF;
extern uchar **FILENAME;
extern uchar **SUBSEP;
extern Awkfloat *RSTART;
extern Awkfloat *RLENGTH;
extern uchar *record;
extern int dbg;
extern int lineno;
extern int errorflag;
extern int donefld; /* 1 if record broken into fields */
extern int donerec; /* 1 if record is valid (no fld has changed */
#define CBUFLEN 400
extern uchar cbuf[CBUFLEN]; /* miscellaneous character collection */
extern uchar *patbeg; /* beginning of pattern matched */
extern int patlen; /* length. set in b.c */
/* Cell: all information about a variable or constant */
typedef struct Cell {
uchar ctype; /* OCELL, OBOOL, OJUMP, etc. */
uchar csub; /* CCON, CTEMP, CFLD, etc. */
uchar *nval; /* name, for variables only */
uchar *sval; /* string value */
Awkfloat fval; /* value as number */
unsigned tval; /* type info: STR|NUM|ARR|FCN|FLD|CON|DONTFREE */
struct Cell *cnext; /* ptr to next if chained */
} Cell;
typedef struct { /* symbol table array */
int nelem; /* elements in table right now */
int size; /* size of tab */
Cell **tab; /* hash table pointers */
} Array;
#define NSYMTAB 50 /* initial size of a symbol table */
extern Array *symtab, *makesymtab();
extern Cell *setsymtab(), *lookup();
extern Cell *recloc; /* location of input record */
extern Cell *nrloc; /* NR */
extern Cell *fnrloc; /* FNR */
extern Cell *nfloc; /* NF */
extern Cell *rstartloc; /* RSTART */
extern Cell *rlengthloc; /* RLENGTH */
/* Cell.tval values: */
#define NUM 01 /* number value is valid */
#define STR 02 /* string value is valid */
#define DONTFREE 04 /* string space is not freeable */
#define CON 010 /* this is a constant */
#define ARR 020 /* this is an array */
#define FCN 040 /* this is a function name */
#define FLD 0100 /* this is a field $1, $2, ... */
#define REC 0200 /* this is $0 */
#define freeable(p) (!((p)->tval & DONTFREE))
Awkfloat setfval(), getfval();
uchar *setsval(), *getsval();
uchar *tostring(), *tokname(), *qstring();
#include <malloc.h>
double log(), sqrt(), exp(), atof();
/* function types */
#define FLENGTH 1
#define FSQRT 2
#define FEXP 3
#define FLOG 4
#define FINT 5
#define FSYSTEM 6
#define FRAND 7
#define FSRAND 8
#define FSIN 9
#define FCOS 10
#define FATAN 11
#define FTOUPPER 12
#define FTOLOWER 13
/* Node: parse tree is made of nodes, with Cell's at bottom */
typedef struct Node {
int ntype;
struct Node *nnext;
int lineno;
int nobj;
struct Node *narg[1]; /* variable: actual size set by calling malloc */
} Node;
#define NIL ((Node *) 0)
extern Node *winner;
extern Node *nullstat;
extern Node *nullnode;
/* ctypes */
#define OCELL 1
#define OBOOL 2
#define OJUMP 3
/* Cell subtypes: csub */
#define CFREE 7
#define CCOPY 6
#define CCON 5
#define CTEMP 4
#define CNAME 3
#define CVAR 2
#define CFLD 1
/* bool subtypes */
#define BTRUE 11
#define BFALSE 12
/* jump subtypes */
#define JEXIT 21
#define JNEXT 22
#define JBREAK 23
#define JCONT 24
#define JRET 25
/* node types */
#define NVALUE 1
#define NSTAT 2
#define NEXPR 3
#define NFIELD 4
extern Cell *(*proctab[])();
extern Cell *nullproc();
extern int pairstack[], paircnt;
extern Cell *fieldadr();
extern Node *stat1(), *stat2(), *stat3(), *stat4(), *pa2stat();
extern Node *op1(), *op2(), *op3(), *op4();
extern Node *linkum(), *valtonode(), *rectonode(), *exptostat();
extern Node *makearr();
#define notlegal(n) (n <= FIRSTTOKEN || n >= LASTTOKEN || proctab[n-FIRSTTOKEN] == nullproc)
#define isvalue(n) ((n)->ntype == NVALUE)
#define isexpr(n) ((n)->ntype == NEXPR)
#define isjump(n) ((n)->ctype == OJUMP)
#define isexit(n) ((n)->csub == JEXIT)
#define isbreak(n) ((n)->csub == JBREAK)
#define iscont(n) ((n)->csub == JCONT)
#define isnext(n) ((n)->csub == JNEXT)
#define isret(n) ((n)->csub == JRET)
#define isstr(n) ((n)->tval & STR)
#define isnum(n) ((n)->tval & NUM)
#define isarr(n) ((n)->tval & ARR)
#define isfunc(n) ((n)->tval & FCN)
#define istrue(n) ((n)->csub == BTRUE)
#define istemp(n) ((n)->csub == CTEMP)
#define NCHARS (257) /* Regular 256 characters + HAT */
#define NSTATES 32
typedef struct rrow {
int ltype;
int lval;
int *lfollow;
} rrow;
typedef struct fa {
uchar *restr;
int anchor;
int use;
uchar gototab[NSTATES][NCHARS];
int *posns[NSTATES];
uchar out[NSTATES];
int initstat;
int curstat;
int accept;
int reset;
struct rrow re[1];
} fa;
extern fa *makedfa();
+291
View File
@@ -0,0 +1,291 @@
%{
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
%}
%{
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
%}
%{
/* All Rights Reserved */
%}
%{
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
%}
%{
/* UNIX System Laboratories, Inc. */
%}
%{
/* The copyright notice above does not evidence any */
%}
%{
/* actual or intended publication of such source code. */
%}
%{
#ident "@(#)awk:awk.lx.l 2.11"
%}
%Start A str sc reg comment
%{
#include "awk.h"
#include "y.tab.h"
#include <pfmt.h>
#undef input /* defeat lex */
#undef unput
extern YYSTYPE yylval;
extern int infunc;
void startreg(),unput(),unputstr();
int lineno = 1;
int bracecnt = 0;
int brackcnt = 0;
int parencnt = 0;
#define DEBUG
#ifdef DEBUG
# define RET(x) {dprintf(("lex %s [%s]\n", tokname(x), yytext)); return(x); }
#else
# define RET(x) return(x)
#endif
#define CADD cbuf[clen++] = yytext[0]; \
if (clen >= CBUFLEN-1) { \
vyyerror(":90:String/reg expr %.10s ... too long", cbuf); \
BEGIN A; \
}
static const char extra[] = ":91:Extra %c";
extern const char nlstring[];
uchar cbuf[CBUFLEN];
uchar *s;
int clen, cflag;
%}
A [a-zA-Z_]
B [a-zA-Z0-9_]
D [0-9]
O [0-7]
H [0-9a-fA-F]
WS [ \t]
%%
switch (yybgin-yysvec-1) { /* witchcraft */
case 0:
BEGIN A;
break;
case sc:
BEGIN A;
RET('}');
}
<A>\n { lineno++; RET(NL); }
<A>#.* { ; } /* strip comments */
<A>{WS}+ { ; }
<A>; { RET(';'); }
<A>"\\"\n { lineno++; }
<A>BEGIN { RET(XBEGIN); }
<A>END { RET(XEND); }
<A>func(tion)? { if (infunc) vyyerror(":92:Illegal nested function"); RET(FUNC); }
<A>return { if (!infunc) vyyerror(":93:Return not in function"); RET(RETURN); }
<A>"&&" { RET(AND); }
<A>"||" { RET(BOR); }
<A>"!" { RET(NOT); }
<A>"!=" { yylval.i = NE; RET(NE); }
<A>"~" { yylval.i = MATCH; RET(MATCHOP); }
<A>"!~" { yylval.i = NOTMATCH; RET(MATCHOP); }
<A>"<" { yylval.i = LT; RET(LT); }
<A>"<=" { yylval.i = LE; RET(LE); }
<A>"==" { yylval.i = EQ; RET(EQ); }
<A>">=" { yylval.i = GE; RET(GE); }
<A>">" { yylval.i = GT; RET(GT); }
<A>">>" { yylval.i = APPEND; RET(APPEND); }
<A>"++" { yylval.i = INCR; RET(INCR); }
<A>"--" { yylval.i = DECR; RET(DECR); }
<A>"+=" { yylval.i = ADDEQ; RET(ASGNOP); }
<A>"-=" { yylval.i = SUBEQ; RET(ASGNOP); }
<A>"*=" { yylval.i = MULTEQ; RET(ASGNOP); }
<A>"/=" { yylval.i = DIVEQ; RET(ASGNOP); }
<A>"%=" { yylval.i = MODEQ; RET(ASGNOP); }
<A>"^=" { yylval.i = POWEQ; RET(ASGNOP); }
<A>"**=" { yylval.i = POWEQ; RET(ASGNOP); }
<A>"=" { yylval.i = ASSIGN; RET(ASGNOP); }
<A>"**" { RET(POWER); }
<A>"^" { RET(POWER); }
<A>"$"{D}+ { yylval.cp = fieldadr(atoi(yytext+1)); RET(FIELD); }
<A>"$NF" { unputstr("(NF)"); return(INDIRECT); }
<A>"$"{A}{B}* { int c, n;
c = input(); unput(c);
if (c == '(' || c == '[' || infunc && (n=isarg(yytext+1)) >= 0) {
unputstr(yytext+1);
return(INDIRECT);
} else {
yylval.cp = setsymtab(yytext+1,"",0.0,STR|NUM,symtab);
RET(IVAR);
}
}
<A>"$" { RET(INDIRECT); }
<A>NF { yylval.cp = setsymtab(yytext, "", 0.0, NUM, symtab); RET(VARNF); }
<A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? {
yylval.cp = setsymtab(yytext, tostring(yytext), atof(yytext), CON|NUM, symtab);
RET(NUMBER); }
<A>while { RET(WHILE); }
<A>for { RET(FOR); }
<A>do { RET(DO); }
<A>if { RET(IF); }
<A>else { RET(ELSE); }
<A>next { RET(NEXT); }
<A>exit { RET(EXIT); }
<A>break { RET(BREAK); }
<A>continue { RET(CONTINUE); }
<A>print { yylval.i = PRINT; RET(PRINT); }
<A>printf { yylval.i = PRINTF; RET(PRINTF); }
<A>sprintf { yylval.i = SPRINTF; RET(SPRINTF); }
<A>split { yylval.i = SPLIT; RET(SPLIT); }
<A>substr { RET(SUBSTR); }
<A>sub { yylval.i = SUB; RET(SUB); }
<A>gsub { yylval.i = GSUB; RET(GSUB); }
<A>index { RET(INDEX); }
<A>match { RET(MATCHFCN); }
<A>in { RET(IN); }
<A>getline { RET(GETLINE); }
<A>close { RET(CLOSE); }
<A>delete { RET(DELETE); }
<A>length { yylval.i = FLENGTH; RET(BLTIN); }
<A>log { yylval.i = FLOG; RET(BLTIN); }
<A>int { yylval.i = FINT; RET(BLTIN); }
<A>exp { yylval.i = FEXP; RET(BLTIN); }
<A>sqrt { yylval.i = FSQRT; RET(BLTIN); }
<A>sin { yylval.i = FSIN; RET(BLTIN); }
<A>cos { yylval.i = FCOS; RET(BLTIN); }
<A>atan2 { yylval.i = FATAN; RET(BLTIN); }
<A>system { yylval.i = FSYSTEM; RET(BLTIN); }
<A>rand { yylval.i = FRAND; RET(BLTIN); }
<A>srand { yylval.i = FSRAND; RET(BLTIN); }
<A>toupper { yylval.i = FTOUPPER; RET(BLTIN); }
<A>tolower { yylval.i = FTOLOWER; RET(BLTIN); }
<A>{A}{B}* { int n, c;
c = input(); unput(c); /* look for '(' */
if (c != '(' && infunc && (n=isarg(yytext)) >= 0) {
yylval.i = n;
RET(ARG);
} else {
yylval.cp = setsymtab(yytext,"",0.0,STR|NUM,symtab);
if (c == '(') {
RET(CALL);
} else {
RET(VAR);
}
}
}
<A>\" { BEGIN str; clen = 0; }
<A>"}" { if (--bracecnt < 0) vyyerror(extra, '}'); BEGIN sc; RET(';'); }
<A>"]" { if (--brackcnt < 0) vyyerror(extra, ']'); RET(']'); }
<A>")" { if (--parencnt < 0) vyyerror(extra, ')'); RET(')'); }
<A>. { if (yytext[0] == '{') bracecnt++;
else if (yytext[0] == '[') brackcnt++;
else if (yytext[0] == '(') parencnt++;
RET(yylval.i = yytext[0]); /* everything else */ }
<reg>\\. { cbuf[clen++] = '\\'; cbuf[clen++] = yytext[1]; }
<reg>\n { vyyerror(":94:Newline in regular expression %.10s ...", cbuf); lineno++; BEGIN A; }
<reg>"/" { BEGIN A;
cbuf[clen] = 0;
yylval.s = tostring(cbuf);
unput('/');
RET(REGEXPR); }
<reg>. { CADD; }
<str>\" { BEGIN A;
cbuf[clen] = 0; s = tostring(cbuf);
cbuf[clen] = ' '; cbuf[++clen] = 0;
yylval.cp = setsymtab(cbuf, s, 0.0, CON|STR, symtab);
RET(STRING); }
<str>\n { vyyerror(nlstring, cbuf); lineno++; BEGIN A; }
<str>"\\\"" { cbuf[clen++] = '"'; }
<str>"\\"n { cbuf[clen++] = '\n'; }
<str>"\\"t { cbuf[clen++] = '\t'; }
<str>"\\"f { cbuf[clen++] = '\f'; }
<str>"\\"r { cbuf[clen++] = '\r'; }
<str>"\\"b { cbuf[clen++] = '\b'; }
<str>"\\"v { cbuf[clen++] = '\v'; } /* these ANSIisms may not be known by */
<str>"\\"a { cbuf[clen++] = '\007'; } /* your compiler. hence 007 for bell */
<str>"\\\\" { cbuf[clen++] = '\\'; }
<str>"\\"({O}{O}{O}|{O}{O}|{O}) { int n;
sscanf(yytext+1, "%o", &n); cbuf[clen++] = n; }
<str>"\\"x({H}+) { int n; /* ANSI permits any number! */
sscanf(yytext+2, "%x", &n); cbuf[clen++] = n; }
<str>"\\". { cbuf[clen++] = yytext[1]; }
<str>. { CADD; }
%%
void
startreg()
{
BEGIN reg;
clen = 0;
}
/* input() and unput() are transcriptions of the standard lex
macros for input and output with additions for error message
printing. God help us all if someone changes how lex works.
*/
uchar ebuf[300];
uchar *ep = ebuf;
input()
{
register int c;
extern uchar *lexprog;
if (yysptr > yysbuf)
c = U(*--yysptr);
else if (lexprog != NULL) { /* awk '...' */
if (c = *lexprog)
lexprog++;
} else /* awk -f ... */
c = pgetc();
if (c == '\n')
yylineno++;
else if (c == EOF)
c = 0;
if (ep >= ebuf + sizeof ebuf)
ep = ebuf;
return *ep++ = c;
}
void
unput(c)
{
yytchar = c;
if (yytchar == '\n')
yylineno--;
*yysptr++ = yytchar;
if (--ep < ebuf)
ep = ebuf + sizeof(ebuf) - 1;
}
void
unputstr(s)
char *s;
{
int i;
for (i = strlen(s)-1; i >= 0; i--)
unput(s[i]);
}
+892
View File
@@ -0,0 +1,892 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)awk:b.c 2.12"
#define DEBUG
#include "awk.h"
#include <ctype.h>
#include <stdio.h>
#include "y.tab.h"
#include <pfmt.h>
/* SGI NOTE: I believe that the following is safe, since comparisons of
* HAT are almost always made against an integer rather than a character.
* However, we must insure that the HAT character is not stored in any
* char tables, since it exceeds the maximum size of a char. Also,
* be aware that NCHARS is now 257.
* -jfk, 2-May-1995
*/
#define HAT (NCHARS-1) /* matches ^ in regular expr */
#define MAXLIN 256
#define type(v) (v)->nobj
#define left(v) (v)->narg[0]
#define right(v) (v)->narg[1]
#define parent(v) (v)->nnext
#define LEAF case CCL: case NCCL: case CHAR: case MCHAR: case DOT: case FINAL: case ALL:
#define UNARY case STAR: case PLUS: case QUEST:
/* encoding in tree Nodes:
leaf (CCL, NCCL, CHAR, MCHAR, DOT, FINAL, ALL): left is index, right contains value or pointer to value
unary (STAR, PLUS, QUEST): left is child, right is null
binary (CAT, OR): left and right are children
parent contains pointer to parent
*/
uchar chars[MAXLIN];
int setvec[MAXLIN];
int tmpset[MAXLIN];
Node *point[MAXLIN];
int rtok; /* next token in current re */
int rlxval;
uchar *rlxstr;
uchar *prestr; /* current position in current re */
uchar *lastre; /* origin of last re */
static int setcnt;
static int poscnt;
uchar *patbeg;
int patlen;
#include <sys/euc.h>
extern eucwidth_t WW;
#define WIDTH1 WW._eucw1
#define WIDTH2 WW._eucw2
#define WIDTH3 WW._eucw3
#define WIDTH(c) (ISASCII(c) ? 1 : \
(ISSET2(c) ? WIDTH2 : (ISSET3(c) ? WIDTH3 : WIDTH1)))
#define CODESET(c) (ISASCII(c) ? 0 :( ISSET2(c) ? 2 :( ISSET3(c) ? 3 : 1)))
#define CURRENTC(p) (ISASCII(*p) ? (*p++) : \
(ISSET2(*p) ? (p += WIDTH2, p[-WIDTH2]) : \
(ISSET3(*p) ? (p += WIDTH3, p[-WIDTH3]) : \
(p += WIDTH1, p[-WIDTH1]) )))
#define NFA 20 /* cache this many dynamic fa's */
fa *fatab[NFA];
int nfatab = 0; /* entries in fatab */
fa *mkdfa();
const char
badtype[] = ":1:Unknown type %d in %s";
static const char
bigcharclas[] = "Character class too big",
bigcharclasid[] = ":2",
badre[] = ":3:Syntax error in regular expression %s at %s",
nontermcharclas[] = ":4:Nonterminated character class %s";
void penter(),freetr(),nospace(),overflo(),cfoll(),follow(),freefa();
fa *makedfa(s, anchor) /* returns dfa for reg expr s */
uchar *s;
int anchor;
{
int i, use, nuse;
fa *pfa;
if (compile_time) /* a constant for sure */
return mkdfa(s, anchor);
for (i = 0; i < nfatab; i++) /* is it there already? */
if (fatab[i]->anchor == anchor && strcmp(fatab[i]->restr,s) == 0) {
fatab[i]->use++;
return fatab[i];
}
pfa = mkdfa(s, anchor);
if (nfatab < NFA) { /* room for another */
fatab[nfatab] = pfa;
fatab[nfatab]->use = 1;
nfatab++;
return pfa;
}
use = fatab[0]->use; /* replace least-recently used */
nuse = 0;
for (i = 1; i < nfatab; i++)
if (fatab[i]->use < use) {
use = fatab[i]->use;
nuse = i;
}
freefa(fatab[nuse]);
fatab[nuse] = pfa;
pfa->use = 1;
return pfa;
}
fa *mkdfa(s, anchor) /* does the real work of making a dfa */
uchar *s;
int anchor; /* anchor = 1 for anchored matches, else 0 */
{
Node *p, *p1, *reparse();
fa *f;
p = reparse(s);
p1 = op2(CAT, op2(STAR, op2(ALL, NIL, NIL), NIL), p);
/* put ALL STAR in front of reg. exp. */
p1 = op2(CAT, p1, op2(FINAL, NIL, NIL));
/* put FINAL after reg. exp. */
poscnt = 0;
penter(p1); /* enter parent pointers and leaf indices */
if ((f = (fa *) calloc(1, sizeof(fa) + poscnt*sizeof(rrow))) == NULL)
nospace("makedfa");
f->accept = poscnt-1; /* penter has computed number of positions in re */
cfoll(f, p1); /* set up follow sets */
freetr(p1);
if ((f->posns[0] = (int *) calloc(1, *(f->re[0].lfollow)*sizeof(int))) == NULL)
nospace("makedfa");
if ((f->posns[1] = (int *) calloc(1, sizeof(int))) == NULL)
nospace("makedfa");
*f->posns[1] = 0;
f->initstat = makeinit(f, anchor);
f->anchor = anchor;
f->restr = tostring(s);
return f;
}
int makeinit(f, anchor)
fa *f;
int anchor;
{
register int i, k;
f->curstat = 2;
f->out[2] = 0;
f->reset = 0;
k = *(f->re[0].lfollow);
xfree(f->posns[2]);
if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
nospace("makeinit");
for (i=0; i<=k; i++) {
(f->posns[2])[i] = (f->re[0].lfollow)[i];
}
if ((f->posns[2])[1] == f->accept)
f->out[2] = 1;
for (i=0; i<NCHARS; i++)
f->gototab[2][i] = 0;
f->curstat = cgoto(f, 2, HAT, (uchar *)0);
if (anchor) {
*f->posns[2] = k-1; /* leave out position 0 */
for (i=0; i<k; i++) {
(f->posns[0])[i] = (f->posns[2])[i];
}
f->out[0] = f->out[2];
if (f->curstat != 2)
--(*f->posns[f->curstat]);
}
return f->curstat;
}
void
penter(p) /* set up parent pointers and leaf indices */
Node *p;
{
switch(type(p)) {
LEAF
left(p) = (Node *) poscnt;
point[poscnt++] = p;
break;
UNARY
penter(left(p));
parent(left(p)) = p;
break;
case CAT:
case OR:
penter(left(p));
penter(right(p));
parent(left(p)) = p;
parent(right(p)) = p;
break;
default:
error(MM_ERROR, badtype, type(p), "penter");
break;
}
}
void
freetr(p) /* free parse tree */
Node *p;
{
switch (type(p)) {
LEAF
xfree(p);
break;
UNARY
freetr(left(p));
xfree(p);
break;
case CAT:
case OR:
freetr(left(p));
freetr(right(p));
xfree(p);
break;
default:
error(MM_ERROR, badtype, type(p), "freetr");
break;
}
}
uchar *cclenter(p)
register uchar *p;
{
register int i, c;
uchar *op;
uchar *q;
register int w, j;
#define LEFTEDGEP(p) (ISASCII(p[-1]) ? p-1 : \
(ISSET2(p[-WIDTH2]) ? p-WIDTH2 : \
(ISSET3(p[-WIDTH3]) ? p-WIDTH3 : p-WIDTH1 )))
op = p;
i = 0;
while ((c = *p++) != 0) {
if (c == '\\') {
if ((c = *p++) == 't')
c = '\t';
else if (c == 'n')
c = '\n';
else if (c == 'f')
c = '\f';
else if (c == 'r')
c = '\r';
else if (c == 'b')
c = '\b';
else if (c == '\\')
c = '\\';
else if (isdigit(c)) {
int n = c - '0';
if (isdigit(*p)) {
n = 8 * n + *p++ - '0';
if (isdigit(*p))
n = 8 * n + *p++ - '0';
}
c = n;
} /* else */
/* c = c; */
} else if (c == '-' && i > 0 && chars[i-1] != 0) {
if (*p != 0) {
q = p-1;
q = LEFTEDGEP(q);
if (CODESET(*q) != CODESET(*p))
; /* '-' is discarded */
else if((w = WIDTH(*p)) <= 1) {
c = chars[i-1];
while (++c < (int)*p) {
if (i >= MAXLIN)
overflo(gettxt(bigcharclasid, bigcharclas));
chars[i++] = c;
}
}else {
for(j=0; j<w && q[j] == p[j]; j++);
if(j >= w || q[j] < p[j]) {
/* store '-' only if left < right */
if (i >= MAXLIN)
overflo(gettxt(bigcharclasid, bigcharclas));
chars[i++] = '-';
}
}
c = *p++;
}
}
if (i >= MAXLIN-1)
overflo(gettxt(bigcharclasid, bigcharclas));
chars[i++] = c;
}
chars[i++] = '\0';
dprintf( ("cclenter: in = |%s|, out = |%s|\n", op, chars) );
xfree(op);
return(tostring(chars));
}
void
nospace(s)
uchar *s;
{
error(MM_ERROR, ":5:Regular expression too big: out of space in %s", s);
}
void
overflo(s)
uchar *s;
{
error(MM_ERROR, ":6:Regular expression too big: %s", s);
}
void
cfoll(f, v) /* enter follow set of each leaf of vertex v into lfollow[leaf] */
fa *f;
register Node *v;
{
register int i;
register int *p;
switch(type(v)) {
LEAF
f->re[(int) left(v)].ltype = type(v);
f->re[(int) left(v)].lval = (int) right(v);
for (i=0; i<=f->accept; i++)
setvec[i] = 0;
setcnt = 0;
follow(v); /* computes setvec and setcnt */
if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
overflo(gettxt(":7", "Follow set overflow"));
f->re[(int) left(v)].lfollow = p;
*p = setcnt;
for (i = f->accept; i >= 0; i--)
if (setvec[i] == 1) *++p = i;
break;
UNARY
cfoll(f,left(v));
break;
case CAT:
case OR:
cfoll(f,left(v));
cfoll(f,right(v));
break;
default:
error(MM_ERROR, badtype, type(v), "cfoll");
}
}
first(p) /* collects initially active leaves of p into setvec */
register Node *p; /* returns 0 or 1 depending on whether p matches empty string */
{
register int b;
switch(type(p)) {
LEAF
if (setvec[(int) left(p)] != 1) {
setvec[(int) left(p)] = 1;
setcnt++;
}
if (type(p) == CCL && (*(uchar *) right(p)) == '\0')
return(0); /* empty CCL */
else return(1);
case PLUS:
if (first(left(p)) == 0) return(0);
return(1);
case STAR:
case QUEST:
first(left(p));
return(0);
case CAT:
if (first(left(p)) == 0 && first(right(p)) == 0) return(0);
return(1);
case OR:
b = first(right(p));
if (first(left(p)) == 0 || b == 0) return(0);
return(1);
}
error(MM_ERROR, badtype, type(p), "first");
return(-1);
}
void
follow(v)
Node *v; /* collects leaves that can follow v into setvec */
{
Node *p;
if (type(v) == FINAL)
return;
p = parent(v);
switch (type(p)) {
case STAR:
case PLUS:
first(v);
follow(p);
return;
case OR:
case QUEST:
follow(p);
return;
case CAT:
if (v == left(p)) { /* v is left child of p */
if (first(right(p)) == 0) {
follow(p);
return;
}
}
else /* v is right child */
follow(p);
return;
}
}
member(c, s) /* is c in s? */
register uchar c, *s;
{
while (*s)
if (c == *s++)
return(1);
return(0);
}
memberw(p, s)
register uchar *s, *p;
{
register int i, w;
/* SGI BUG FIX: cgoto is called with a null when a HAT is found */
if (p == NULL) return 0;
for( ; *s != 0; s += w) {
w = WIDTH(*s);
for(i=0; i < w && p[i] == s[i]; i++);
if(i >= w) return(1);
if(s[w] == '-' && s[w+1] != 0) {
if (*p == '-')
s += (w+1);
else if(CODESET(*p) == CODESET(*s) && p[i] > s[i]) {
s += (w+1);
for(i=0; i < w && p[i] == s[i]; i++);
if(i >= w || p[i] < s[i]) return(1);
}
}
}
return(0);
}
match(f, p)
register fa *f;
register uchar *p;
{
register int s, ns;
s = f->reset?makeinit(f,0):f->initstat;
if (f->out[s])
return(1);
do {
if ((ns=f->gototab[s][*p]) && WIDTH(*p) == 1)
s=ns;
else
s=cgoto(f,s,*p,p);
if (f->out[s])
return(1);
} while (CURRENTC(p) != 0);
return(0);
}
pmatch(f, p)
register fa *f;
register uchar *p;
{
register int s, ns;
register uchar *q;
int i, k;
s = f->reset?makeinit(f,1):f->initstat;
patbeg = p;
patlen = -1;
do {
q = p;
do {
if (f->out[s]) /* final state */
patlen = q-p;
if ((ns=f->gototab[s][*q]) && WIDTH(*q) == 1)
s=ns;
else
s=cgoto(f,s,*q,q);
if (s==1) /* no transition */
if (patlen >= 0) {
patbeg = p;
return(1);
}
else
goto nextin; /* no match */
} while (CURRENTC(q) != 0);
if (f->out[s])
patlen = q-p-1; /* don't count $ */
if (patlen >= 0) {
patbeg = p;
return(1);
}
nextin:
s = 2;
if (f->reset) {
for (i=2; i<=f->curstat; i++)
xfree(f->posns[i]);
k = *f->posns[0];
if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
nospace("pmatch");
for (i=0; i<=k; i++)
(f->posns[2])[i] = (f->posns[0])[i];
f->initstat = f->curstat = 2;
f->out[2] = f->out[0];
for (i=0; i<NCHARS; i++)
f->gototab[2][i] = 0;
}
} while (CURRENTC(p) != 0);
return (0);
}
nematch(f, p)
register fa *f;
register uchar *p;
{
register int s, ns;
register uchar *q;
int i, k;
s = f->reset?makeinit(f,1):f->initstat;
patlen = -1;
while (*p) {
q = p;
do {
if (f->out[s]) /* final state */
patlen = q-p;
if ((ns=f->gototab[s][*q]) && WIDTH(*q) == 1)
s=ns;
else
s=cgoto(f,s,*q,q);
if (s==1) /* no transition */
if (patlen > 0) {
patbeg = p;
return(1);
}
else
goto nnextin; /* no nonempty match */
} while (CURRENTC(q) != 0);
if (f->out[s])
patlen = q-p-1; /* don't count $ */
if (patlen > 0 ) {
patbeg = p;
return(1);
}
nnextin:
s = 2;
if (f->reset) {
for (i=2; i<=f->curstat; i++)
xfree(f->posns[i]);
k = *f->posns[0];
if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
nospace("nematch");
for (i=0; i<=k; i++)
(f->posns[2])[i] = (f->posns[0])[i];
f->initstat = f->curstat = 2;
f->out[2] = f->out[0];
for (i=0; i<NCHARS; i++)
f->gototab[2][i] = 0;
}
CURRENTC(p);
}
return (0);
}
Node *regexp(), *primary(), *concat(), *alt(), *unary();
Node *reparse(p)
uchar *p;
{
/* parses regular expression pointed to by p */
/* uses relex() to scan regular expression */
Node *np;
dprintf( ("Reparse <%s>\n", p) );
lastre = prestr = p; /* prestr points to string to be parsed */
rtok = relex();
if (rtok == '\0')
error(MM_ERROR, ":8:Empty regular expression");
np = regexp();
if (rtok == '\0')
return(np);
else
error(MM_ERROR, badre, lastre, prestr);
/*NOTREACHED*/
}
Node *regexp()
{
return (alt(concat(primary())));
}
Node *primary()
{
Node *np;
switch (rtok) {
case CHAR:
np = op2(CHAR, NIL, (Node *) rlxval);
rtok = relex();
return (unary(np));
case MCHAR:
np = op2(MCHAR, (Node *) 0, rlxval);
rtok = relex();
return (unary(np));
case ALL:
rtok = relex();
return (unary(op2(ALL, NIL, NIL)));
case DOT:
rtok = relex();
return (unary(op2(DOT, NIL, NIL)));
case CCL:
np = op2(CCL, NIL, (Node*) cclenter(rlxstr));
rtok = relex();
return (unary(np));
case NCCL:
np = op2(NCCL, NIL, (Node *) cclenter(rlxstr));
rtok = relex();
return (unary(np));
case '^':
rtok = relex();
return (unary(op2(CHAR, NIL, (Node *) HAT)));
case '$':
rtok = relex();
return (unary(op2(CHAR, NIL, NIL)));
case '(':
rtok = relex();
if (rtok == ')') { /* special pleading for () */
rtok = relex();
return unary(op2(CCL, NIL, (Node *) tostring("")));
}
np = regexp();
if (rtok == ')') {
rtok = relex();
return (unary(np));
}
else
error(MM_ERROR, badre, lastre, prestr);
default:
error(MM_ERROR, ":9:Illegal primary in regular expression %s at %s",
lastre, prestr);
}
/*NOTREACHED*/
}
Node *concat(np)
Node *np;
{
switch (rtok) {
case CHAR: case MCHAR: case DOT: case ALL: case CCL: case NCCL: case '$': case '(':
return (concat(op2(CAT, np, primary())));
default:
return (np);
}
}
Node *alt(np)
Node *np;
{
if (rtok == OR) {
rtok = relex();
return (alt(op2(OR, np, concat(primary()))));
}
return (np);
}
Node *unary(np)
Node *np;
{
switch (rtok) {
case STAR:
rtok = relex();
return (unary(op2(STAR, np, NIL)));
case PLUS:
rtok = relex();
return (unary(op2(PLUS, np, NIL)));
case QUEST:
rtok = relex();
return (unary(op2(QUEST, np, NIL)));
default:
return (np);
}
}
relex() /* lexical analyzer for reparse */
{
register int c;
uchar cbuf[150];
int clen, cflag;
switch (c = *prestr++) {
case '|': return OR;
case '*': return STAR;
case '+': return PLUS;
case '?': return QUEST;
case '.': return DOT;
case '\0': prestr--; return '\0';
case '^':
case '$':
case '(':
case ')':
return c;
case '\\':
if ((c = *prestr++) == 't')
c = '\t';
else if (c == 'n')
c = '\n';
else if (c == 'f')
c = '\f';
else if (c == 'r')
c = '\r';
else if (c == 'b')
c = '\b';
else if (c == '\\')
c = '\\';
else if (isdigit(c)) {
int n = c - '0';
if (isdigit(*prestr)) {
n = 8 * n + *prestr++ - '0';
if (isdigit(*prestr))
n = 8 * n + *prestr++ - '0';
}
c = n;
} /* else it's now in c */
rlxval = c;
return CHAR;
default:
if((cflag = WIDTH(c)) > 1) {
clen = 0;
cbuf[clen++] = c;
while(--cflag) cbuf[clen++] = *prestr++;
cbuf[clen] = 0;
rlxval = (int) tostring(cbuf);
return MCHAR;
}
rlxval = c;
return CHAR;
case '[':
clen = 0;
if (*prestr == '^') {
cflag = 1;
prestr++;
}
else
cflag = 0;
for (;;) {
if ((c = *prestr++) == '\\') {
cbuf[clen++] = '\\';
if ((c = *prestr++) == '\0')
error(MM_ERROR, nontermcharclas, lastre);
cbuf[clen++] = c;
} else if (c == ']') {
cbuf[clen] = 0;
rlxstr = tostring(cbuf);
if (cflag == 0)
return CCL;
else
return NCCL;
} else if (c == '\n') {
error(MM_ERROR,
":10:Newline in character class %s...",
lastre);
} else if (c == '\0') {
error(MM_ERROR, nontermcharclas, lastre);
} else
cbuf[clen++] = c;
}
}
}
int cgoto(f, s, c, cp)
fa *f;
int s, c; /* Be careful here; we actually do pass ints
* for c to denote metasyntactic characters */
uchar *cp;
{
register int i, j, k;
register int *p, *q;
for (i=0; i<=f->accept; i++)
setvec[i] = 0;
setcnt = 0;
/* compute positions of gototab[s,c] into setvec */
p = f->posns[s];
for (i=1; i<=*p; i++) {
if ((k = f->re[p[i]].ltype) != FINAL) {
if (k == CHAR && c == f->re[p[i]].lval
|| k == DOT && c != 0 && c != HAT
|| k == ALL && c != 0
|| k == MCHAR && !strncmp(cp, (uchar *) f->re[p[i]].lval, WIDTH(c))
|| k == CCL && memberw(cp, (uchar *) f->re[p[i]].lval)
|| k == NCCL && !memberw(cp, (uchar *) f->re[p[i]].lval) && c != 0 && c != HAT
) {
q = f->re[p[i]].lfollow;
for (j=1; j<=*q; j++) {
if (setvec[q[j]] == 0) {
setcnt++;
setvec[q[j]] = 1;
}
}
}
}
}
/* determine if setvec is a previous state */
tmpset[0] = setcnt;
j = 1;
for (i = f->accept; i >= 0; i--)
if (setvec[i]) {
tmpset[j++] = i;
}
/* tmpset == previous state? */
for (i=1; i<= f->curstat; i++) {
p = f->posns[i];
if ((k = tmpset[0]) != p[0])
goto different;
for (j = 1; j <= k; j++)
if (tmpset[j] != p[j])
goto different;
/* setvec is state i */
f->gototab[s][c] = i;
return i;
different:;
}
/* add tmpset to current set of states */
if (f->curstat >= NSTATES-1) {
f->curstat = 2;
f->reset = 1;
for (i=2; i<NSTATES; i++)
xfree(f->posns[i]);
}
else
++(f->curstat);
for (i=0; i<NCHARS; i++)
f->gototab[f->curstat][i] = 0;
xfree(f->posns[f->curstat]);
if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
nospace("cgoto");
f->posns[f->curstat] = p;
f->gototab[s][c] = f->curstat;
for (i = 0; i <= setcnt; i++)
p[i] = tmpset[i];
if (setvec[f->accept])
f->out[f->curstat] = 1;
else
f->out[f->curstat] = 0;
return f->curstat;
}
void
freefa(f)
struct fa *f;
{
register int i;
if (f == NULL)
return;
for (i=0; i<=f->curstat; i++)
xfree(f->posns[i]);
for (i=0; i<=f->accept; i++)
xfree(f->re[i].lfollow);
xfree(f->restr);
xfree(f);
}
+664
View File
@@ -0,0 +1,664 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)awk:lib.c 2.14"
#define DEBUG
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include "awk.h"
#include "y.tab.h"
#include <pfmt.h>
#define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
#define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
extern Awkfloat r_getfval();
extern uchar *r_getsval();
FILE *infile = NULL;
uchar *file = (uchar*) "";
uchar recdata[RECSIZE];
uchar *record = recdata;
uchar fields[RECSIZE];
#define MAXFLD 200
int donefld; /* 1 = implies rec broken into fields */
int donerec; /* 1 = record is valid (no flds have changed) */
#define FINIT { OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE }
Cell fldtab[MAXFLD] = { /* room for fields */
{ OCELL, CFLD, (uchar*) "$0", recdata, 0.0, REC|STR|DONTFREE},
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
};
int maxfld = 0; /* last used field */
int argno = 1; /* current input argument number */
extern Awkfloat *ARGC;
extern uchar *getargv();
const char badopen[] = ":11:Cannot open %s: %s";
void initgetrec(),setclvar(),fldbld(),cleanfld(),newfld(),recbld(),fpecatch();
void bracecheck(),bcheck2(),error(),eprint(),bclass(),PUTS();
void
initgetrec()
{
int i;
uchar *p;
for (i = 1; i < *ARGC; i++) {
if (!isclvar(p = getargv(i))) /* find 1st real filename */
return;
setclvar(p); /* a commandline assignment before filename */
argno++;
}
infile = stdin; /* no filenames, so use stdin */
/* *FILENAME = file = (uchar*) "-"; */
}
getrec(buf)
uchar *buf;
{
int c;
static int firsttime = 1;
if (firsttime) {
firsttime = 0;
initgetrec();
}
/* SGI BUG FIX: FILENAME may not be initialized yet, so we can't
* print it. Trying to do so causes seg faults.
*/
dprintf( ("RS=<%s>, FS=<%s>, ARGC=%d\n",
*RS, *FS, (int)*ARGC) );
donefld = 0;
donerec = 1;
buf[0] = 0;
while (argno < *ARGC || infile == stdin) {
dprintf( ("argno=%d, file=|%s|\n", argno, file) )
;
if (infile == NULL) { /* have to open a new file */
file = getargv(argno);
if (*file == '\0') { /* it's been zapped */
argno++;
continue;
}
if (isclvar(file)) { /* a var=value arg */
setclvar(file);
argno++;
continue;
}
*FILENAME = file;
dprintf( ("opening file %s\n", file) );
if (*file == '-' && *(file+1) == '\0')
infile = stdin;
else if ((infile = fopen((char *)file, "r")) == NULL)
error(MM_ERROR, badopen, file, strerror(errno));
setfval(fnrloc, 0.0);
}
c = readrec(buf, RECSIZE, infile);
if (c != 0 || buf[0] != '\0') { /* normal record */
if (buf == record) {
if (!(recloc->tval & DONTFREE))
xfree(recloc->sval);
recloc->sval = record;
recloc->tval = REC | STR | DONTFREE;
if (isnumber(recloc->sval)) {
recloc->fval = atof(recloc->sval);
recloc->tval |= NUM;
}
}
setfval(nrloc, nrloc->fval+1);
setfval(fnrloc, fnrloc->fval+1);
return 1;
}
/* EOF arrived on this file; set up next */
if (infile != stdin)
fclose(infile);
infile = NULL;
argno++;
}
return 0; /* true end of file */
}
readrec(buf, bufsize, inf) /* read one record into buf */
uchar *buf;
int bufsize;
FILE *inf;
{
register int sep, c;
register uchar *rr;
if ((sep = **RS) == 0) {
sep = '\n';
while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
;
if (c != EOF)
ungetc(c, inf);
}
for (rr = buf; ; ) {
/* SGI BUG FIX: Do bounds checking on buffer */
for (; (c=getc(inf)) != sep && c != EOF && rr < buf+bufsize;
*rr++ = c) ;
/* SGI BUG FIX: Exit loop if exceeded buffer */
if (**RS == sep || c == EOF || rr >= buf+bufsize)
break;
if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
break;
*rr++ = '\n';
*rr++ = c;
}
/* SGI BUG FIX: check for >= rather than > */
if (rr >= buf + bufsize)
error(MM_ERROR, ":12:Input record `%.20s...' too long", buf);
*rr = 0;
dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF
&& rr == buf ? 0 : 1) );
return c == EOF && rr == buf ? 0 : 1;
}
uchar *getargv(n) /* get ARGV[n] */
int n;
{
Cell *x;
uchar *s, temp[10];
extern Array *ARGVtab;
sprintf((char *)temp, "%d", n);
x = setsymtab(temp, "", 0.0, STR, ARGVtab);
s = getsval(x);
dprintf( ("getargv(%d) returns |%s|\n", n, s) );
return s;
}
void
setclvar(s) /* set var=value from s */
uchar *s;
{
uchar *p;
Cell *q;
for (p=s; *p != '='; p++)
;
*p++ = 0;
p = qstring(p, '\0');
q = setsymtab(s, p, 0.0, STR, symtab);
setsval(q, p);
if (isnumber(q->sval)) {
q->fval = atof(q->sval);
q->tval |= NUM;
}
dprintf( ("command line set %s to |%s|\n", s, p) );
}
void
fldbld()
{
register uchar *r, *fr, sep;
Cell *p;
int i;
if (donefld)
return;
if (!(recloc->tval & STR))
getsval(recloc);
r = recloc->sval; /* was record! */
fr = fields;
i = 0; /* number of fields accumulated here */
if ((int) strlen((char*) *FS) > 1) { /* it's a regular expression */
i = refldbld(r, *FS);
} else if ((sep = **FS) == ' ') {
for (i = 0; ; ) {
while (*r == ' ' || *r == '\t' || *r == '\n')
r++;
if (*r == 0)
break;
i++;
if (i >= MAXFLD)
break;
if (!(fldtab[i].tval & DONTFREE))
xfree(fldtab[i].sval);
/* SGI BUG FIX: If fr is NULL, make the symbol "" */
fldtab[i].sval = ((fr) ? (fr) : tostring(""));
fldtab[i].tval = FLD | STR | DONTFREE;
do
*fr++ = *r++;
while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
*fr++ = 0;
}
*fr = 0;
} else if (*r != 0) { /* if 0, it's a null field */
for (;;) {
i++;
if (i >= MAXFLD)
break;
if (!(fldtab[i].tval & DONTFREE))
xfree(fldtab[i].sval);
/* SGI BUG FIX */
fldtab[i].sval = ((fr) ? (fr) : tostring(""));
fldtab[i].tval = FLD | STR | DONTFREE;
while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */
*fr++ = *r++;
*fr++ = 0;
if (*r++ == 0)
break;
}
*fr = 0;
}
if (i >= MAXFLD)
error(MM_ERROR, ":13:Record `%.20s...' has too many fields",
record);
/* clean out junk from previous record */
cleanfld(i, maxfld);
maxfld = i;
donefld = 1;
for (p = fldtab+1; p <= fldtab+maxfld; p++) {
if(isnumber(p->sval)) {
p->fval = atof(p->sval);
p->tval |= NUM;
}
}
setfval(nfloc, (Awkfloat) maxfld);
if (dbg)
for (p = fldtab; p <= fldtab+maxfld; p++)
pfmt(stdout, MM_INFO, ":14:field %d: |%s|\n", p-fldtab,
p->sval);
}
void
cleanfld(n1, n2) /* clean out fields n1..n2 inclusive */
{
static uchar *nullstat = (uchar *) "";
register Cell *p, *q;
for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) {
if (!(p->tval & DONTFREE))
xfree(p->sval);
p->tval = FLD | STR | DONTFREE;
p->sval = nullstat;
}
}
void
newfld(n) /* add field n (after end) */
{
if (n >= MAXFLD)
error(MM_ERROR, ":15:Creating too many fields", record);
cleanfld(maxfld, n);
maxfld = n;
setfval(nfloc, (Awkfloat) n);
}
refldbld(rec, fs) /* build fields from reg expr in FS */
uchar *rec, *fs;
{
fa *makedfa();
uchar *fr;
int i, tempstat;
fa *pfa;
fr = fields;
*fr = '\0';
if (*rec == '\0')
return 0;
pfa = makedfa(fs, 1);
dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec,
fs) );
tempstat = pfa->initstat;
for (i = 1; i < MAXFLD; i++) {
if (!(fldtab[i].tval & DONTFREE))
xfree(fldtab[i].sval);
fldtab[i].tval = FLD | STR | DONTFREE;
fldtab[i].sval = fr;
dprintf( ("refldbld: i=%d\n", i) );
if (nematch(pfa, rec)) {
pfa->initstat = 2;
dprintf( ("match %s (%d chars\n",
patbeg, patlen) );
strncpy((char*) fr, (char*) rec, patbeg-rec);
fr += patbeg - rec + 1;
*(fr-1) = '\0';
rec = patbeg + patlen;
} else {
dprintf( ("no match %s\n", rec) );
strcpy((char*) fr, (char*) rec);
pfa->initstat = tempstat;
break;
}
}
return i;
}
void
recbld()
{
int i;
register uchar *r, *p;
static uchar rec[RECSIZE];
if (donerec == 1)
return;
r = rec;
for (i = 1; i <= *NF; i++) {
p = getsval(&fldtab[i]);
while (*r = *p++)
r++;
if (i < *NF)
for (p = *OFS; *r = *p++; )
r++;
}
*r = '\0';
dprintf( ("in recbld FS=%o, recloc=%o\n", **FS,
recloc) );
recloc->tval = REC | STR | DONTFREE;
recloc->sval = record = rec;
dprintf( ("in recbld FS=%o, recloc=%o\n", **FS,
recloc) );
if (r > record + RECSIZE)
error(MM_ERROR, ":16:Built giant record `%.20s...'",
record);
dprintf( ("recbld = |%s|\n", record) );
donerec = 1;
}
Cell *fieldadr(n)
{
if (n < 0 || n >= MAXFLD)
error(MM_ERROR, ":17:Trying to access field %d", n);
return(&fldtab[n]);
}
int errorflag = 0;
char errbuf[200];
static int been_here = 0;
static const char
atline[] = ":18: at source line %d",
infunc[] = ":19: in function %s";
void
vyyerror(msg, a1, a2, a3, a4, a5)
char *msg, *a1, *a2, *a3, *a4, *a5;
{
extern uchar *cmdname, *curfname;
if (been_here++ > 2)
return;
pfmt(stderr, MM_ERROR, msg, a1, a2, a3, a4, a5);
pfmt(stderr, MM_NOSTD, atline, lineno);
if (curfname != NULL)
pfmt(stderr, MM_NOSTD, infunc, curfname);
fprintf(stderr, "\n");
errorflag = 2;
eprint();
}
void
yyerror(s)
uchar *s;
{
extern uchar *cmdname, *curfname;
static int been_here = 0;
if (been_here++ > 2)
return;
pfmt(stderr, (MM_ERROR | MM_NOGET), "%s", s);
pfmt(stderr, MM_NOSTD, atline, lineno);
if (curfname != NULL)
pfmt(stderr, MM_NOSTD, infunc, curfname);
fprintf(stderr, "\n");
errorflag = 2;
eprint();
}
void
fpecatch()
{
error(MM_ERROR, ":20:Floating point exception");
}
extern int bracecnt, brackcnt, parencnt;
void
bracecheck()
{
int c;
static int beenhere = 0;
if (beenhere++)
return;
while ((c = input()) != EOF && c != '\0')
bclass(c);
bcheck2(bracecnt, '{', '}');
bcheck2(brackcnt, '[', ']');
bcheck2(parencnt, '(', ')');
}
void
bcheck2(n, c1, c2)
{
if (n == 1)
pfmt(stderr, MM_ERROR, ":21:Missing %c\n", c2);
else if (n > 1)
pfmt(stderr, MM_ERROR, ":22:%d missing %c's\n", n, c2);
else if (n == -1)
pfmt(stderr, MM_ERROR, ":23:Extra %c\n", c2);
else if (n < -1)
pfmt(stderr, MM_ERROR, ":24:%d extra %c's\n", -n, c2);
}
void
error(flag, msg, a1, a2, a3, a4, a5)
int flag;
char *msg, *a1, *a2, *a3, *a4, *a5;
{
int errline;
extern Node *curnode;
extern uchar *cmdname;
fflush(stdout);
pfmt(stderr, flag, msg, a1, a2, a3, a4, a5);
putc('\n', stderr);
if (compile_time != 2 && NR && *NR > 0) {
pfmt(stderr, MM_INFO,
":25:Input record number %g", *FNR);
if (strcmp((char*) *FILENAME, "-") != 0)
pfmt(stderr, MM_NOSTD,
":26:, file %s", *FILENAME);
fprintf(stderr, "\n");
}
errline = 0;
if (compile_time != 2 && curnode)
errline = curnode->lineno;
else if (compile_time != 2 && lineno)
errline = lineno;
if (errline)
pfmt(stderr, MM_INFO, ":27:Source line number %d\n", errline);
eprint();
if (flag == MM_ERROR) {
if (dbg)
abort();
exit(2);
}
}
void
eprint() /* try to print context around error */
{
uchar *p, *q;
int c;
static int been_here = 0;
extern uchar ebuf[300], *ep;
if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
return;
p = ep - 1;
if (p > ebuf && *p == '\n')
p--;
for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
;
while (*p == '\n')
p++;
pfmt(stderr, MM_INFO, ":28:Context is\n\t");
for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
;
for ( ; p < q; p++)
if (*p)
putc(*p, stderr);
fprintf(stderr, " >>> ");
for ( ; p < ep; p++)
if (*p)
putc(*p, stderr);
fprintf(stderr, " <<< ");
if (*ep)
while ((c = input()) != '\n' && c != '\0' && c != EOF) {
putc(c, stderr);
bclass(c);
}
putc('\n', stderr);
ep = ebuf;
}
void
bclass(c)
{
switch (c) {
case '{': bracecnt++; break;
case '}': bracecnt--; break;
case '[': brackcnt++; break;
case ']': brackcnt--; break;
case '(': parencnt++; break;
case ')': parencnt--; break;
}
}
double errcheck(x, s)
double x;
uchar *s;
{
extern int errno;
if (errno == EDOM) {
errno = 0;
error(MM_WARNING, ":29:%s argument out of domain", s);
x = 1;
} else if (errno == ERANGE) {
errno = 0;
error(MM_WARNING, ":30:%s result out of range", s);
x = 1;
}
return x;
}
void
PUTS(s) uchar *s; {
dprintf( ("%s\n", s) );
}
isclvar(s) /* is s of form var=something? */
char *s;
{
char *os = s;
for ( ; *s; s++)
if (!(isalnum(*s) || *s == '_'))
break;
return *s == '=' && s > os && *(s+1) != '=';
}
#define MAXEXPON 38 /* maximum exponent for fp number */
isnumber(s)
register uchar *s;
{
register int d1, d2;
int point;
uchar *es;
d1 = d2 = point = 0;
while (*s == ' ' || *s == '\t' || *s == '\n')
s++;
if (*s == '\0')
return(0); /* empty stuff isn't number */
if (*s == '+' || *s == '-')
s++;
if (!isdigit(*s) && *s != '.')
return(0);
if (isdigit(*s)) {
do {
d1++;
s++;
} while (isdigit(*s));
}
if(d1 >= MAXEXPON)
return(0); /* too many digits to convert */
if (*s == '.') {
point++;
s++;
}
if (isdigit(*s)) {
d2++;
do {
s++;
} while (isdigit(*s));
}
if (!(d1 || point && d2))
return(0);
if (*s == 'e' || *s == 'E') {
s++;
if (*s == '+' || *s == '-')
s++;
if (!isdigit(*s))
return(0);
es = s;
do {
s++;
} while (isdigit(*s));
if (s - es > 2)
return(0);
else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON)
return(0);
}
while (*s == ' ' || *s == '\t' || *s == '\n')
s++;
if (*s == '\0')
return(1);
else
return(0);
}
+192
View File
@@ -0,0 +1,192 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)awk:main.c 2.15"
#define DEBUG
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <pfmt.h>
#include <errno.h>
#include <string.h>
#include <locale.h>
#include <sys/euc.h>
#include <getwidth.h>
eucwidth_t WW;
#define CMDCLASS "UX:" /* Command classification */
/* SGI CHANGE: I presume we want the locale stuff */
#include <locale.h>
#include "awk.h"
#include "y.tab.h"
char *version;
int dbg = 0;
uchar *cmdname; /* gets argv[0] for error messages */
extern FILE *yyin; /* lex input file */
uchar *lexprog; /* points to program argument if it exists */
extern int errorflag; /* non-zero if any syntax errors; set by yyerror */
int compile_time = 2; /* for error printing: */
/* 2 = cmdline, 1 = compile, 0 = running */
uchar *pfile[20]; /* program filenames from -f's */
int npfile = 0; /* number of filenames */
int curpfile = 0; /* current filename */
extern const char badopen[];
char *getenv(), *xpg;
main(argc, argv, envp)
int argc;
uchar *argv[], *envp[];
{
uchar *fs = NULL;
char label[MAXLABEL+1]; /* Space for the catalogue label */
extern void fpecatch();
if( (xpg = getenv("_XPG")) != NULL && atoi(xpg) > 0) {
execve("/usr/bin/pawk", argv, envp);
fprintf(stderr,"awk: Cannot exec /usr/bin/pawk\n");
exit(1);
}
(void)setlocale(LC_ALL, "");
{getwidth(&WW); WW._eucw2++; WW._eucw3++;}
cmdname = ((cmdname = (uchar*) strrchr ((char*) argv[0], '/')) ?
++cmdname : argv[0]);
(void)strcpy(label, CMDCLASS);
(void)strncat(label, (char*) cmdname, (MAXLABEL - sizeof(CMDCLASS) - 1));
(void)setcat("uxawk");
(void)setlabel(label);
version = (char*) gettxt(":31", "version Oct 11, 1989");
if (argc == 1) {
pfmt(stderr, MM_ERROR, ":32:Incorrect usage\n");
pfmt(stderr, MM_ACTION,
":33:Usage: %s [-f programfile | 'program'] [-Ffieldsep] [-v var=value] [files]\n",
cmdname);
exit(1);
}
signal(SIGFPE, fpecatch);
yyin = NULL;
syminit();
while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
if (strcmp((char*) argv[1], "--") == 0) { /* explicit end of args */
argc--;
argv++;
break;
}
switch (argv[1][1]) {
case 'f': /* next argument is program filename */
argc--;
argv++;
if (argc <= 1)
error(MM_ERROR, ":34:No program filename");
pfile[npfile++] = argv[1];
break;
case 'F': /* set field separator */
if (argv[1][2] != 0) { /* arg is -Fsomething */
if (argv[1][2] == 't' && argv[1][3] == 0) /* wart: t=>\t */
fs = (uchar *) "\t";
else if (argv[1][2] != 0)
fs = &argv[1][2];
} else { /* arg is -F something */
argc--; argv++;
if (argc > 1 && argv[1][0] == 't' && argv[1][1] == 0) /* wart: t=>\t */
fs = (uchar *) "\t";
else if (argc > 1 && argv[1][0] != 0)
fs = &argv[1][0];
}
if (fs == NULL || *fs == '\0')
error(MM_WARNING, ":35:Field separator FS is empty");
break;
case 'v': /* -v a=1 to be done NOW. one -v for each */
if (argv[1][2] == '\0' && --argc > 1 && isclvar((++argv)[1]))
setclvar(argv[1]);
break;
case 'd':
dbg = atoi(&argv[1][2]);
if (dbg == 0)
dbg = 1;
pfmt(stdout, (MM_INFO | MM_NOGET), "%s %s\n",
cmdname, version);
break;
default:
pfmt(stderr, MM_WARNING,
":36:Unknown option %s ignored\n", argv[1]);
break;
}
argc--;
argv++;
}
/* argv[1] is now the first argument */
if (npfile == 0) { /* no -f; first argument is program */
if (argc <= 1)
error(MM_ERROR, ":37:No program given");
dprintf( ("program = |%s|\n", argv[1]) );
lexprog = argv[1];
argc--;
argv++;
}
compile_time = 1;
argv[0] = cmdname; /* put prog name at front of arglist */
dprintf( ("argc=%d, argv[0]=%s\n", argc, argv[0]) );
/* SGI HACK: Lots of programs assume that nawk performs the
* leading set of variable initializations before it starts
* parsing the program (probably because the old nawk did this).
* The Awk book implies this behavior is wrong, but the book
* is kind of ambiguous about exactly when the first file is
* opened, and a number of our scripts assume that the initialization
* has occurred before the BEGIN clause is executed.
*/
while (argc > 1) {
if (!isclvar(argv[1]))
break;
setclvar(argv[1]);
argc--;
argv++;
}
argv[0] = cmdname;
arginit(argc, argv);
envinit(envp);
yyparse();
if (fs)
*FS = tostring(qstring(fs, '\0'));
dprintf( ("errorflag=%d\n", errorflag) );
if (errorflag == 0) {
compile_time = 0;
run(winner);
} else
bracecheck();
exit(errorflag);
}
pgetc() /* get program character */
{
int c;
for (;;) {
if (yyin == NULL) {
if (curpfile >= npfile)
return EOF;
if ((yyin = fopen((char *) pfile[curpfile], "r")) == NULL)
error(MM_ERROR, badopen,
pfile[curpfile], strerror(errno));
}
if ((c = getc(yyin)) != EOF)
return c;
yyin = NULL;
curpfile++;
}
}
+150
View File
@@ -0,0 +1,150 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)awk:maketab.c 2.5"
#include <stdio.h>
#include <string.h>
#include "awk.h"
#include "y.tab.h"
struct xx
{ int token;
char *name;
char *pname;
} proc[] = {
{ PROGRAM, "program", NULL },
{ BOR, "boolop", " || " },
{ AND, "boolop", " && " },
{ NOT, "boolop", " !" },
{ NE, "relop", " != " },
{ EQ, "relop", " == " },
{ LE, "relop", " <= " },
{ LT, "relop", " < " },
{ GE, "relop", " >= " },
{ GT, "relop", " > " },
{ ARRAY, "array", NULL },
{ INDIRECT, "indirect", "$(" },
{ SUBSTR, "substr", "substr" },
{ SUB, "sub", "sub" },
{ GSUB, "gsub", "gsub" },
{ INDEX, "sindex", "sindex" },
{ SPRINTF, "asprintf", "sprintf " },
{ ADD, "arith", " + " },
{ MINUS, "arith", " - " },
{ MULT, "arith", " * " },
{ DIVIDE, "arith", " / " },
{ MOD, "arith", " % " },
{ UMINUS, "arith", " -" },
{ POWER, "arith", " **" },
{ PREINCR, "incrdecr", "++" },
{ POSTINCR, "incrdecr", "++" },
{ PREDECR, "incrdecr", "--" },
{ POSTDECR, "incrdecr", "--" },
{ CAT, "cat", " " },
{ PASTAT, "pastat", NULL },
{ PASTAT2, "dopa2", NULL },
{ MATCH, "matchop", " ~ " },
{ NOTMATCH, "matchop", " !~ " },
{ MATCHFCN, "matchop", "matchop" },
{ INTEST, "intest", "intest" },
{ PRINTF, "aprintf", "printf" },
{ PRINT, "print", "print" },
{ CLOSE, "closefile", "closefile" },
{ DELETE, "delete", "delete" },
{ SPLIT, "split", "split" },
{ ASSIGN, "assign", " = " },
{ ADDEQ, "assign", " += " },
{ SUBEQ, "assign", " -= " },
{ MULTEQ, "assign", " *= " },
{ DIVEQ, "assign", " /= " },
{ MODEQ, "assign", " %= " },
{ POWEQ, "assign", " ^= " },
{ CONDEXPR, "condexpr", " ?: " },
{ IF, "ifstat", "if(" },
{ WHILE, "whilestat", "while(" },
{ FOR, "forstat", "for(" },
{ DO, "dostat", "do" },
{ IN, "instat", "instat" },
{ NEXT, "jump", "next" },
{ EXIT, "jump", "exit" },
{ BREAK, "jump", "break" },
{ CONTINUE, "jump", "continue" },
{ RETURN, "jump", "ret" },
{ BLTIN, "bltin", "bltin" },
{ CALL, "call", "call" },
{ ARG, "arg", "arg" },
{ VARNF, "getnf", "NF" },
{ GETLINE, "getline", "getline" },
{ 0, "", "" },
};
#define SIZE LASTTOKEN - FIRSTTOKEN + 1
char *table[SIZE];
char *names[SIZE];
main()
{
struct xx *p;
int i, n, tok;
char c;
FILE *fp;
char buf[100], name[100], def[100];
printf("#include \"awk.h\"\n");
printf("#include \"y.tab.h\"\n\n");
printf("Cell *nullproc();\n");
for (i = SIZE; --i >= 0; )
names[i] = "";
for (p=proc; p->token!=0; p++)
if (p == proc || strcmp(p->name, (p-1)->name))
printf("extern Cell *%s();\n", p->name);
if ((fp = fopen("y.tab.h", "r")) == NULL) {
fprintf(stderr, "maketab can't open y.tab.h!\n");
exit(1);
}
printf("static uchar *printname[%d] = {\n", SIZE);
i = 0;
while (fgets(buf, sizeof buf, fp) != NULL) {
n = sscanf(buf, "%1c %s %s %d", &c, def, name, &tok);
if (c != '#' || n != 4 && strcmp(def,"define") != 0) /* not a valid #define */
continue;
if (tok < FIRSTTOKEN || tok > LASTTOKEN) {
fprintf(stderr, "maketab funny token %d %s\n", tok, buf);
exit(1);
}
names[tok-FIRSTTOKEN] = (char *) malloc(strlen(name)+1);
strcpy(names[tok-FIRSTTOKEN], name);
printf("\t(uchar *) \"%s\",\t/* %d */\n", name, tok);
i++;
}
printf("};\n\n");
for (p=proc; p->token!=0; p++)
table[p->token-FIRSTTOKEN] = p->name;
printf("\nCell *(*proctab[%d])() = {\n", SIZE);
for (i=0; i<SIZE; i++)
if (table[i]==0)
printf("\tnullproc,\t/* %s */\n", names[i]);
else
printf("\t%s,\t/* %s */\n", table[i], names[i]);
printf("};\n\n");
printf("uchar *tokname(n)\n"); /* print a tokname() function */
printf("{\n");
printf(" static uchar buf[100];\n\n");
printf(" if (n < FIRSTTOKEN || n > LASTTOKEN) {\n");
printf(" sprintf(buf, \"token %%d\", n);\n");
printf(" return buf;\n");
printf(" }\n");
printf(" return printname[n-257];\n");
printf("}\n");
exit(0);
}
+234
View File
@@ -0,0 +1,234 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)awk:parse.c 2.9"
#define DEBUG
#include <stdio.h>
#include <pfmt.h>
#include "awk.h"
#include "y.tab.h"
extern const char outofspace[];
Node *nodealloc(n)
{
register Node *x;
x = (Node *) malloc(sizeof(Node) + (n-1)*sizeof(Node *));
if (x == NULL)
error(MM_ERROR, outofspace, "nodealloc");
x->nnext = NULL;
x->lineno = lineno;
return(x);
}
Node *exptostat(a) Node *a;
{
a->ntype = NSTAT;
return(a);
}
Node *node1(a,b) Node *b;
{
register Node *x;
x = nodealloc(1);
x->nobj = a;
x->narg[0]=b;
return(x);
}
Node *node2(a,b,c) Node *b, *c;
{
register Node *x;
x = nodealloc(2);
x->nobj = a;
x->narg[0] = b;
x->narg[1] = c;
return(x);
}
Node *node3(a,b,c,d) Node *b, *c, *d;
{
register Node *x;
x = nodealloc(3);
x->nobj = a;
x->narg[0] = b;
x->narg[1] = c;
x->narg[2] = d;
return(x);
}
Node *node4(a,b,c,d,e) Node *b, *c, *d, *e;
{
register Node *x;
x = nodealloc(4);
x->nobj = a;
x->narg[0] = b;
x->narg[1] = c;
x->narg[2] = d;
x->narg[3] = e;
return(x);
}
Node *stat3(a,b,c,d) Node *b, *c, *d;
{
register Node *x;
x = node3(a,b,c,d);
x->ntype = NSTAT;
return(x);
}
Node *op2(a,b,c) Node *b, *c;
{
register Node *x;
x = node2(a,b,c);
x->ntype = NEXPR;
return(x);
}
Node *op1(a,b) Node *b;
{
register Node *x;
x = node1(a,b);
x->ntype = NEXPR;
return(x);
}
Node *stat1(a,b) Node *b;
{
register Node *x;
x = node1(a,b);
x->ntype = NSTAT;
return(x);
}
Node *op3(a,b,c,d) Node *b, *c, *d;
{
register Node *x;
x = node3(a,b,c,d);
x->ntype = NEXPR;
return(x);
}
Node *op4(a,b,c,d,e) Node *b, *c, *d, *e;
{
register Node *x;
x = node4(a,b,c,d,e);
x->ntype = NEXPR;
return(x);
}
Node *stat2(a,b,c) Node *b, *c;
{
register Node *x;
x = node2(a,b,c);
x->ntype = NSTAT;
return(x);
}
Node *stat4(a,b,c,d,e) Node *b, *c, *d, *e;
{
register Node *x;
x = node4(a,b,c,d,e);
x->ntype = NSTAT;
return(x);
}
Node *valtonode(a, b) Cell *a;
{
register Node *x;
a->ctype = OCELL;
a->csub = b;
x = node1(0, (Node *) a);
x->ntype = NVALUE;
return(x);
}
Node *rectonode()
{
/* return valtonode(lookup("$0", symtab), CFLD); */
return valtonode(recloc, CFLD);
}
Node *makearr(p) Node *p;
{
Cell *cp;
if (isvalue(p)) {
cp = (Cell *) (p->narg[0]);
if (isfunc(cp))
vyyerror(":38:%s is a function, not an array",
cp->nval);
else if (!isarr(cp)) {
xfree(cp->sval);
cp->sval = (uchar *) makesymtab(NSYMTAB);
cp->tval = ARR;
}
}
return p;
}
Node *pa2stat(a,b,c) Node *a, *b, *c;
{
register Node *x;
x = node4(PASTAT2, a, b, c, (Node *) paircnt);
paircnt++;
x->ntype = NSTAT;
return(x);
}
Node *linkum(a,b) Node *a, *b;
{
register Node *c;
if (errorflag) /* don't link things that are wrong */
return a;
if (a == NULL) return(b);
else if (b == NULL) return(a);
for (c = a; c->nnext != NULL; c = c->nnext)
;
c->nnext = b;
return(a);
}
void
defn(v, vl, st) /* turn on FCN bit in definition */
Cell *v;
Node *st, *vl; /* body of function, arglist */
{
Node *p;
int n;
if (isarr(v)) {
vyyerror(":39:`%s' is an array name and a function name",
v->nval);
return;
}
v->tval = FCN;
v->sval = (uchar *) st;
n = 0; /* count arguments */
for (p = vl; p; p = p->nnext)
n++;
v->fval = n;
dprintf( ("defining func %s (%d args)\n", v->nval, n) );
}
isarg(s) /* is s in argument list for current function? */
uchar *s;
{
extern Node *arglist;
Node *p = arglist;
int n;
for (n = 0; p != 0; p = p->nnext, n++)
if (strcmp(((Cell *)(p->narg[0]))->nval, s) == 0)
return n;
return -1;
}
+226
View File
@@ -0,0 +1,226 @@
/*
* regex.c -- Support code for the POSIX extended regular expression
* handling in awk. We've completely rewritten portions of the
* awk code to simplify regular expression handling; the old,
* obsolete code lives in b.c and run.c
*/
#if !defined(OLD_REGEXP)
#include <stdio.h>
#include <regex.h>
#include <malloc.h>
#include <pfmt.h>
#include "awk.h"
#define NFA 20
/* Global variables */
fa *fatab[NFA];
int nfatab = 0;
extern void nospace(char *);
/* Forward declarations */
fa *mkdfa(uchar *s, int anchor);
void freefa(fa*);
void nospace(char *);
/*
* makedfa -- Front-end function for mkdfa. Maintains a cache of
* fa's and attempts to satisfy the request for an fa from the
* the cache first.
*/
fa *makedfa(s, anchor) /* returns dfa for reg expr s */
uchar *s;
int anchor;
{
int i, use, nuse;
fa *fa;
if (compile_time) { /* a constant for sure */
if ((fa = malloc(sizeof(fa))) == NULL)
nospace("makedfa");
return mkdfa(s, anchor);
}
for (i = 0; i < nfatab; i++) { /* is it there already? */
if (fatab[i]->anchor == anchor &&
strcmp(fatab[i]->restr,s) == 0) {
fatab[i]->use++;
return fatab[i];
}
}
fa = mkdfa(s, anchor);
if (nfatab < NFA) { /* room for another */
fatab[nfatab] = fa;
fatab[nfatab]->use = 1;
nfatab++;
return fa;
}
use = fatab[0]->use; /* replace least-recently used */
nuse = 0;
for (i = 1; i < nfatab; i++)
if (fatab[i]->use < use) {
use = fatab[i]->use;
nuse = i;
}
freefa(fatab[nuse]);
fatab[nuse] = fa;
fa->use = 1;
return fa;
}
/*
* mkdfa -- Actually generate the deterministic finite automaton for
* the regular expression parsing. This actually does all the
* work.
*/
fa *mkdfa(s, anchor)
uchar *s; /* The regular expression string */
int anchor; /* A no-op for backward compatibility ? */
{
fa *pfa;
if ((pfa = malloc(sizeof(struct fa))) == NULL)
nospace("mkdfa");
if (regcomp(&pfa->regex, s, REG_EXTENDED) != 0) {
fprintf(stderr,"Regular expression compiler failed\n");
exit(1);
}
pfa->anchor = anchor;
pfa->restr = tostring(s);
return pfa;
}
/*
* freefa -- Free an fa structure allocated by mkdfa.
*/
void freefa(fa *fa)
{
xfree(fa->restr);
xfree(fa);
}
/*
* match -- Return a 1 if the given regexpr matches something in the
* string, 0 otherwise.
*/
int
match(f, p)
fa *f;
char *p;
{
int result;
result = regexec(&f->regex, p, 0, NULL, 0);
if (result == 0)
return 1;
else
return 0;
}
char *patbeg;
char *patend;
int patlen;
/*
* pmatch -- If the regular expression matches in the given string,
* pmatch sets the patbeg, patend, and patlen variables and returns
* a 1. patbeg points to the first character in the matched substring.
* patend points to the first character after the end of the matched
* substring, and patlen is the total number of character in the
* matched substring. It is possible to match an empty substring
* (this often occurs when the '*' character is used), so patlen
* can be equal to zero.
* If no match is found, pmatch returns 0.
*/
int
pmatch(f, p, beginning)
fa *f;
char *p;
int beginning; /* Indicates that we're at the beginning of
* of the string, so '^' should match */
{
regmatch_t pmatch;
int result;
result = regexec(&f->regex, p, 1, &pmatch,
beginning ? 0 : REG_NOTBOL);
if (result == 0) {
patbeg = p + pmatch.rm_so;
patlen = pmatch.rm_eo - pmatch.rm_so;
patend = p + pmatch.rm_eo;
return 1;
} else {
patbeg = NULL;
patend = NULL;
patlen = -1;
return 0;
}
}
/*
* nematch -- scans the given string for the first match. Unlike
* pmatch, nematch only succeeds if the number of characters
* matched (patlen) is greater than 0. This makes it useful
* for situations like decomposing a line into a set of records
* based on a regular expression (see recfldbld in lib.c).
* This routine returns a 1 if a match is found, and 0 if no
* match is found. Since it calls pmatch, it also sets the
* global variables patbeg, patlen, and patend.
*/
int
nematch(f, p, beginning)
fa *f; /* The regular expression to use in matching */
char *p; /* The string to match against */
int beginning; /* A flag indicating whether the beginning of the
* string is also the beginning of the logical
* line. */
{
do {
int result = pmatch(f, p, beginning);
if (result == 1) {
if (patlen > 0) {
return 1;
} else {
p = patbeg + 1;
beginning = 0;
}
} else {
return 0;
}
} while (*p);
return 0;
}
void
nospace(s)
char *s;
{
error(MM_ERROR, ":5:Regular expression too big: out of space in %s", s);
}
#endif /* !defined(OLD_REGEXP) */
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh -v
cat /etc/hosts | ./nawk '/^[0-9]*/ { for (i=2;i<=NF;++i) {print $1}}'
+49
View File
@@ -0,0 +1,49 @@
#!/bin/csh -f
############################################################################
# File: run_regress
#
# This file runs the simple regression tests using the version
# of nawk in the parent directory. Don't assume that nawk
# works just because it passes the tests in this directory. These
# tests check a couple really simple cases. Hopefully, as time
# progresses they will get better, but don't count on it.
#
############################################################################
set NAWK = ../nawk # Version of nawk to use
if (`$NAWK -f test1 smallfile` != 4) then
echo "nawk failed test 1"
set failed
endif
if (`$NAWK -f test2 smallfile` != 5) then
echo "nawk failed test 2"
set failed
endif
if (`$NAWK -f test3 < /dev/null` != "ok") then
echo "nawk failed test 3"
set failed
endif
if (`/bin/echo "B\0346che" | $NAWK '{gsub(/\346/, "ae") ; print}'` != "Baeche") then
echo "nawk failed test 4"
set failed
endif
if (`/bin/echo '\011' | $NAWK '/^[ \t]*$/ { print "okay" }'` != "okay") then
echo "nawk failed test 5"
set failed
endif
if (`/bin/echo| $NAWK '/^[ \t]*$/ { print "okay" }'` != "okay") then
echo "nawk failed test 6"
set failed
endif
#
# If we get to this point, all the regression tests passed.
#
if ( ! $?failed) echo "Regression test passed."
+4
View File
@@ -0,0 +1,4 @@
HELLO
Line 2
Line 3
Line 4
+3
View File
@@ -0,0 +1,3 @@
END {
print NR
}
+7
View File
@@ -0,0 +1,7 @@
BEGIN {
x = 5
}
END {
print x
}
+7
View File
@@ -0,0 +1,7 @@
BEGIN {
foo()
print "ok"
}
function foo() {
}
+1808
View File
File diff suppressed because it is too large Load Diff
+468
View File
@@ -0,0 +1,468 @@
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
/* UNIX System Laboratories, Inc. */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)awk:tran.c 2.15"
#define DEBUG
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "awk.h"
#include "y.tab.h"
#include <pfmt.h>
#define FULLTAB 2 /* rehash when table gets this x full */
#define GROWTAB 4 /* grow table by this factor */
Array *symtab; /* main symbol table */
uchar **FS; /* initial field sep */
uchar **RS; /* initial record sep */
uchar **OFS; /* output field sep */
uchar **ORS; /* output record sep */
uchar **OFMT; /* output format for numbers*/
Awkfloat *NF; /* number of fields in current record */
Awkfloat *NR; /* number of current record */
Awkfloat *FNR; /* number of current record in current file */
uchar **FILENAME; /* current filename argument */
Awkfloat *ARGC; /* number of arguments from command line */
uchar **SUBSEP; /* subscript separator for a[i,j,k]; default \034 */
Awkfloat *RSTART; /* start of re matched with ~; origin 1 (!) */
Awkfloat *RLENGTH; /* length of same */
Cell *recloc; /* location of record */
Cell *nrloc; /* NR */
Cell *nfloc; /* NF */
Cell *fnrloc; /* FNR */
Array *ARGVtab; /* symbol table containing ARGV[...] */
Array *ENVtab; /* symbol table containing ENVIRON[...] */
Cell *rstartloc; /* RSTART */
Cell *rlengthloc; /* RLENGTH */
Cell *symtabloc; /* SYMTAB */
Cell *nullloc;
Node *nullnode; /* zero&null, converted into a node for comparisons */
extern Node *valtonode();
extern Cell fldtab[];
static const char
assigntovid[] = ":80",
assigntov[] = "assign to";
const char
readvofid[] = ":81",
readvof[] = "read value of",
outofspace[] = ":82:Out of space in %s",
nlstring[] = ":83:Newline in string %.10s ...";
void rehash(), funnyvar();
void
syminit()
{
symtab = makesymtab(NSYMTAB);
setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
/* this is used for if(x)... tests: */
nullloc = setsymtab("$zero&null", "", 0.0, NUM|STR|CON|DONTFREE, symtab);
nullnode = valtonode(nullloc, CCON);
/* recloc = setsymtab("$0", record, 0.0, REC|STR|DONTFREE, symtab); */
recloc = &fldtab[0];
FS = &setsymtab("FS", " ", 0.0, STR|DONTFREE, symtab)->sval;
RS = &setsymtab("RS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
OFS = &setsymtab("OFS", " ", 0.0, STR|DONTFREE, symtab)->sval;
ORS = &setsymtab("ORS", "\n", 0.0, STR|DONTFREE, symtab)->sval;
OFMT = &setsymtab("OFMT", "%.6g", 0.0, STR|DONTFREE, symtab)->sval;
FILENAME = &setsymtab("FILENAME", "-", 0.0, STR|DONTFREE, symtab)->sval;
nfloc = setsymtab("NF", "", 0.0, NUM, symtab);
NF = &nfloc->fval;
nrloc = setsymtab("NR", "", 0.0, NUM, symtab);
NR = &nrloc->fval;
fnrloc = setsymtab("FNR", "", 0.0, NUM, symtab);
FNR = &fnrloc->fval;
SUBSEP = &setsymtab("SUBSEP", "\034", 0.0, STR|DONTFREE, symtab)->sval;
rstartloc = setsymtab("RSTART", "", 0.0, NUM, symtab);
RSTART = &rstartloc->fval;
rlengthloc = setsymtab("RLENGTH", "", 0.0, NUM, symtab);
RLENGTH = &rlengthloc->fval;
symtabloc = setsymtab("SYMTAB", "", 0.0, ARR, symtab);
symtabloc->sval = (uchar *) symtab;
}
void
arginit(ac, av)
int ac;
uchar *av[];
{
Cell *cp;
Array *makesymtab();
int i;
uchar temp[5];
for (i = 1; i < ac; i++) /* first make FILENAME first real argument */
if (!isclvar(av[i])) {
setsval(lookup("FILENAME", symtab), av[i]);
break;
}
ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
cp->sval = (uchar *) ARGVtab;
for (i = 0; i < ac; i++) {
sprintf((char *)temp, "%d", i);
if (isnumber(*av))
setsymtab(temp, *av, atof(*av), STR|NUM, ARGVtab);
else
setsymtab(temp, *av, 0.0, STR, ARGVtab);
av++;
}
}
void
envinit(envp)
uchar *envp[];
{
Cell *cp;
Array *makesymtab();
uchar *p;
cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
ENVtab = makesymtab(NSYMTAB);
cp->sval = (uchar *) ENVtab;
for ( ; *envp; envp++) {
if ((p = (uchar *) strchr((char *) *envp, '=')) == NULL) /* index() on bsd */
continue;
*p++ = 0; /* split into two strings at = */
if (isnumber(p))
setsymtab(*envp, p, atof(p), STR|NUM, ENVtab);
else
setsymtab(*envp, p, 0.0, STR, ENVtab);
p[-1] = '='; /* restore in case env is passed down to a shell */
}
}
Array *makesymtab(n)
int n;
{
Array *ap;
Cell **tp;
ap = (Array *) malloc(sizeof(Array));
tp = (Cell **) calloc(n, sizeof(Cell *));
if (ap == NULL || tp == NULL)
error(MM_ERROR, outofspace, "makesymtab");
ap->nelem = 0;
ap->size = n;
ap->tab = tp;
return(ap);
}
void
freesymtab(ap) /* free symbol table */
Cell *ap;
{
Cell *cp, *temp;
Array *tp;
int i;
if (!isarr(ap))
return;
tp = (Array *) ap->sval;
if (tp == NULL)
return;
for (i = 0; i < tp->size; i++) {
for (cp = tp->tab[i]; cp != NULL; cp = temp) {
xfree(cp->nval);
if (freeable(cp))
xfree(cp->sval);
temp = cp->cnext; /* avoids freeing then using */
free(cp);
}
}
free(tp->tab);
free(tp);
}
void
freeelem(ap, s) /* free elem s from ap (i.e., ap["s"] */
Cell *ap;
uchar *s;
{
Array *tp;
Cell *p, *prev = NULL;
int h;
tp = (Array *) ap->sval;
h = hash(s, tp->size);
for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
if (strcmp((char *) s, (char *) p->nval) == 0) {
if (prev == NULL) /* 1st one */
tp->tab[h] = p->cnext;
else /* middle somewhere */
prev->cnext = p->cnext;
if (freeable(p))
xfree(p->sval);
free(p->nval);
free(p);
tp->nelem--;
return;
}
}
Cell *setsymtab(n, s, f, t, tp)
uchar *n, *s;
Awkfloat f;
unsigned t;
Array *tp;
{
register int h;
register Cell *p;
Cell *lookup();
if (n != NULL && (p = lookup(n, tp)) != NULL) {
dprintf( ("setsymtab found %o: n=%s", p, p->nval) );
dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) );
return(p);
}
p = (Cell *) malloc(sizeof(Cell));
if (p == NULL)
error(MM_ERROR, ":84:Symbol table overflow at %s", n);
p->nval = tostring(n);
p->sval = s ? tostring(s) : tostring("");
p->fval = f;
p->tval = t;
#ifdef sgi
p->csub = CVAR;
#endif
tp->nelem++;
if (tp->nelem > FULLTAB * tp->size)
rehash(tp);
h = hash(n, tp->size);
p->cnext = tp->tab[h];
tp->tab[h] = p;
dprintf( ("setsymtab set %o: n=%s", p, p->nval) );
dprintf( (" s=\"%s\" f=%g t=%o\n", p->sval, p->fval, p->tval) );
return(p);
}
hash(s, n) /* form hash value for string s */
register uchar *s;
int n;
{
register unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = (*s + 31 * hashval);
return hashval % n;
}
void
rehash(tp) /* rehash items in small table into big one */
Array *tp;
{
int i, nh, nsz;
Cell *cp, *op, **np;
nsz = GROWTAB * tp->size;
np = (Cell **) calloc(nsz, sizeof(Cell *));
if (np == NULL)
error(MM_ERROR, outofspace, "rehash");
for (i = 0; i < tp->size; i++) {
for (cp = tp->tab[i]; cp; cp = op) {
op = cp->cnext;
nh = hash(cp->nval, nsz);
cp->cnext = np[nh];
np[nh] = cp;
}
}
free(tp->tab);
tp->tab = np;
tp->size = nsz;
}
Cell *lookup(s, tp) /* look for s in tp */
register uchar *s;
Array *tp;
{
register Cell *p, *prev = NULL;
int h;
h = hash(s, tp->size);
for (p = tp->tab[h]; p != NULL; prev = p, p = p->cnext)
if (strcmp((char *) s, (char *) p->nval) == 0)
return(p); /* found it */
return(NULL); /* not found */
}
Awkfloat setfval(vp, f)
register Cell *vp;
Awkfloat f;
{
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, gettxt(assigntovid, assigntov));
if (vp->tval & FLD) {
donerec = 0; /* mark $0 invalid */
if (vp-fldtab > *NF)
newfld(vp-fldtab);
dprintf( ("setting field %d to %g\n", vp-fldtab, f) );
} else if (vp->tval & REC) {
donefld = 0; /* mark $1... invalid */
donerec = 1;
}
vp->tval &= ~STR; /* mark string invalid */
vp->tval |= NUM; /* mark number ok */
dprintf( ("setfval %o: %s = %g, t=%o\n", vp, vp->nval, f, vp->tval) );
return vp->fval = f;
}
void
funnyvar(vp, rw)
Cell *vp;
char *rw;
{
if (vp->tval & ARR)
error(MM_ERROR, ":85:Cannot %s %s; it's an array name.",
rw, vp->nval);
if (vp->tval & FCN)
error(MM_ERROR, ":86:Cannot %s %s; it's a function.",
rw, vp->nval);
error(MM_ERROR, ":87:Funny variable %o: n=%s s=\"%s\" f=%g t=%o",
vp, vp->nval, vp->sval, vp->fval, vp->tval);
}
uchar *setsval(vp, s)
register Cell *vp;
uchar *s;
{
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, gettxt(assigntovid, assigntov));
if (vp->tval & FLD) {
donerec = 0; /* mark $0 invalid */
if (vp-fldtab > *NF)
newfld(vp-fldtab);
dprintf( ("setting field %d to %s\n", vp-fldtab, s) );
} else if (vp->tval & REC) {
donefld = 0; /* mark $1... invalid */
donerec = 1;
}
vp->tval &= ~NUM;
vp->tval |= STR;
if (freeable(vp))
xfree(vp->sval);
vp->tval &= ~DONTFREE;
dprintf( ("setsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, s, vp->tval) );
return(vp->sval = tostring(s));
}
Awkfloat r_getfval(vp)
register Cell *vp;
{
/* if (vp->tval & ARR)
ERROR "Illegal reference to array %s", vp->nval FATAL;
return 0.0; */
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, gettxt(readvofid, readvof));
if ((vp->tval & FLD) && donefld == 0)
fldbld();
else if ((vp->tval & REC) && donerec == 0)
recbld();
if (!isnum(vp)) { /* not a number */
vp->fval = atof(vp->sval); /* best guess */
if (isnumber(vp->sval) && !(vp->tval&CON))
vp->tval |= NUM; /* make NUM only sparingly */
}
dprintf( ("getfval %o: %s = %g, t=%o\n", vp, vp->nval, vp->fval, vp->tval) );
return(vp->fval);
}
uchar *r_getsval(vp)
register Cell *vp;
{
uchar s[100];
/* if (vp->tval & ARR)
ERROR "Illegal reference to array %s",
vp->nval FATAL;
return ""; */
if ((vp->tval & (NUM | STR)) == 0)
funnyvar(vp, gettxt(readvofid, readvof));
if ((vp->tval & FLD) && donefld == 0)
fldbld();
else if ((vp->tval & REC) && donerec == 0)
recbld();
if ((vp->tval & STR) == 0) {
if (!(vp->tval&DONTFREE))
xfree(vp->sval);
if ((long)vp->fval == vp->fval)
sprintf((char *)s, "%.20g", vp->fval);
else
sprintf((char *)s, (char *)*OFMT, vp->fval);
vp->sval = tostring(s);
vp->tval &= ~DONTFREE;
vp->tval |= STR;
}
dprintf( ("getsval %o: %s = \"%s\", t=%o\n", vp, vp->nval, vp->sval, vp->tval) );
/* SGI BUG FIX: Some places assume this returns an actual string */
return((vp->sval) ? (vp->sval) : tostring(""));
}
uchar *tostring(s)
register uchar *s;
{
register uchar *p;
p = malloc(strlen((char *) s)+1);
if (p == NULL)
error(MM_ERROR, ":88:Out of space in tostring on %s", s);
strcpy((char *) p, (char *) s);
return(p);
}
uchar *qstring(s, delim) /* collect string up to delim */
uchar *s;
int delim;
{
uchar *q;
int c, n;
for (q = cbuf; (c = *s) != delim; s++) {
if (q >= cbuf + CBUFLEN - 1)
vyyerror(":89:String %.10s ... too long", cbuf);
else if (c == '\n')
vyyerror(nlstring, cbuf);
else if (c != '\\')
*q++ = c;
else /* \something */
switch (c = *++s) {
case '\\': *q++ = '\\'; break;
case 'n': *q++ = '\n'; break;
case 't': *q++ = '\t'; break;
case 'b': *q++ = '\b'; break;
case 'f': *q++ = '\f'; break;
case 'r': *q++ = '\r'; break;
default:
if (!isdigit(c)) {
*q++ = c;
break;
}
n = c - '0';
if (isdigit(s[1])) {
n = 8 * n + *++s - '0';
if (isdigit(s[1]))
n = 8 * n + *++s - '0';
}
*q++ = n;
break;
}
}
*q = '\0';
return cbuf;
}
+4
View File
@@ -0,0 +1,4 @@
VERSION=troot
OBJECT_STYLE=N32
VCOPTS=-non_shared
VLDOPTS=-nostdlib -L$(ROOT)/usr/lib32/nonshared -L$(ROOT)/usr/lib32/mips3/nonshared
+3
View File
@@ -0,0 +1,3 @@
VERSION=n32bit
OBJECT_STYLE=N32
VLDOPTS=-nostdlib -L$(ROOT)/usr/lib32 -L$(ROOT)/usr/lib32/mips3