1*48236Sbostic /*- 2*48236Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*48236Sbostic * All rights reserved. 4*48236Sbostic * 5*48236Sbostic * %sccs.include.proprietary.c% 6*48236Sbostic */ 7*48236Sbostic 814475Ssam #ifndef lint 9*48236Sbostic static char sccsid[] = "@(#)tran.c 4.6 (Berkeley) 04/17/91"; 10*48236Sbostic #endif /* not lint */ 116678Smckusick 126678Smckusick #include "stdio.h" 136678Smckusick #include "awk.def" 146678Smckusick #include "awk.h" 156678Smckusick 166678Smckusick cell *symtab[MAXSYM]; /* symbol table pointers */ 176678Smckusick 186678Smckusick char **FS; /* initial field sep */ 196678Smckusick char **RS; /* initial record sep */ 206678Smckusick char **OFS; /* output field sep */ 216678Smckusick char **ORS; /* output record sep */ 226678Smckusick char **OFMT; /*output format for numbers*/ 236678Smckusick awkfloat *NF; /* number of fields in current record */ 246678Smckusick awkfloat *NR; /* number of current record */ 256678Smckusick char **FILENAME; /* current filename argument */ 266678Smckusick 276678Smckusick cell *recloc; /* location of record */ 286678Smckusick cell *nrloc; /* NR */ 296678Smckusick cell *nfloc; /* NF */ 306678Smckusick 316678Smckusick syminit() 326678Smckusick { 336678Smckusick setsymtab("0", tostring("0"), 0.0, NUM|STR|CON|FLD, symtab); 346678Smckusick /* this one is used for if(x)... tests: */ 356678Smckusick setsymtab("$zero&null", tostring(""), 0.0, NUM|STR|CON|FLD, symtab); 366678Smckusick recloc = setsymtab("$record", record, 0.0, STR|FLD, symtab); 376678Smckusick dprintf("recloc %o lookup %o\n", recloc, lookup("$record", symtab, 0), NULL); 386678Smckusick FS = &setsymtab("FS", tostring(" "), 0.0, STR|FLD, symtab)->sval; 396678Smckusick RS = &setsymtab("RS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; 406678Smckusick OFS = &setsymtab("OFS", tostring(" "), 0.0, STR|FLD, symtab)->sval; 416678Smckusick ORS = &setsymtab("ORS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; 426678Smckusick OFMT = &setsymtab("OFMT", tostring("%.6g"), 0.0, STR|FLD, symtab)->sval; 4310795Ssam FILENAME = &setsymtab("FILENAME", EMPTY, 0.0, STR|FLD, symtab)->sval; 4410795Ssam nfloc = setsymtab("NF", EMPTY, 0.0, NUM, symtab); 456678Smckusick NF = &nfloc->fval; 4610795Ssam nrloc = setsymtab("NR", EMPTY, 0.0, NUM, symtab); 476678Smckusick NR = &nrloc->fval; 486678Smckusick } 496678Smckusick 506678Smckusick cell **makesymtab() 516678Smckusick { 526678Smckusick int i; 536678Smckusick cell **cp; 546678Smckusick 556678Smckusick cp = (cell **) malloc(MAXSYM * sizeof(cell *)); 566678Smckusick if (cp == NULL) 576678Smckusick error(FATAL, "out of space in makesymtab"); 586678Smckusick for (i = 0; i < MAXSYM; i++) 596678Smckusick cp[i] = 0; 606678Smckusick return(cp); 616678Smckusick } 626678Smckusick 636678Smckusick freesymtab(ap) /* free symbol table */ 646678Smckusick cell *ap; 656678Smckusick { 666678Smckusick cell *cp, **tp; 676678Smckusick int i; 686678Smckusick 696678Smckusick if (!(ap->tval & ARR)) 706678Smckusick return; 716678Smckusick tp = (cell **) ap->sval; 726678Smckusick for (i = 0; i < MAXSYM; i++) { 736678Smckusick for (cp = tp[i]; cp != NULL; cp = cp->nextval) { 7410795Ssam strfree(cp->nval); 7510795Ssam strfree(cp->sval); 766678Smckusick free(cp); 776678Smckusick } 786678Smckusick } 796678Smckusick xfree(tp); 806678Smckusick } 816678Smckusick 826678Smckusick cell *setsymtab(n, s, f, t, tab) 836678Smckusick char *n, *s; 846678Smckusick awkfloat f; 856678Smckusick unsigned t; 866678Smckusick cell **tab; 876678Smckusick { 886678Smckusick register h; 896678Smckusick register cell *p; 906678Smckusick cell *lookup(); 916678Smckusick 926678Smckusick if (n != NULL && (p = lookup(n, tab, 0)) != NULL) { 9310795Ssam if (s != EMPTY ) xfree(s); /* careful here */ 946678Smckusick dprintf("setsymtab found %o: %s", p, p->nval, NULL); 956678Smckusick dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); 966678Smckusick return(p); 976678Smckusick } 986678Smckusick p = (cell *) malloc(sizeof(cell)); 996678Smckusick if (p == NULL) 1006678Smckusick error(FATAL, "symbol table overflow at %s", n); 1016678Smckusick p->nval = tostring(n); 1026678Smckusick p->sval = s; 1036678Smckusick p->fval = f; 1046678Smckusick p->tval = t; 1056678Smckusick h = hash(n); 1066678Smckusick p->nextval = tab[h]; 1076678Smckusick tab[h] = p; 1086678Smckusick dprintf("setsymtab set %o: %s", p, p->nval, NULL); 1096678Smckusick dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); 1106678Smckusick return(p); 1116678Smckusick } 1126678Smckusick 1136678Smckusick hash(s) /* form hash value for string s */ 1146678Smckusick register unsigned char *s; 1156678Smckusick { 1166678Smckusick register int hashval; 1176678Smckusick 1186678Smckusick for (hashval = 0; *s != '\0'; ) 1196678Smckusick hashval += *s++; 1206678Smckusick return(hashval % MAXSYM); 1216678Smckusick } 1226678Smckusick 1236678Smckusick cell *lookup(s, tab, flag) /* look for s in tab, flag must match*/ 1246678Smckusick register char *s; 1256678Smckusick cell **tab; 1266678Smckusick { 1276678Smckusick register cell *p; 1286678Smckusick 1296678Smckusick for (p = tab[hash(s)]; p != NULL; p = p->nextval) 1306678Smckusick if (strcmp(s, p->nval) == 0 && 1316678Smckusick (flag == 0 || flag == p->tval)) 1326678Smckusick return(p); /* found it */ 1336678Smckusick return(NULL); /* not found */ 1346678Smckusick } 1356678Smckusick 1366678Smckusick awkfloat setfval(vp, f) 1376678Smckusick register cell *vp; 1386678Smckusick awkfloat f; 1396678Smckusick { 1406678Smckusick dprintf("setfval: %o %g\n", vp, f, NULL); 1416678Smckusick checkval(vp); 1426678Smckusick if (vp == recloc) 1436678Smckusick error(FATAL, "can't set $0"); 1446678Smckusick vp->tval &= ~STR; /* mark string invalid */ 1456678Smckusick vp->tval |= NUM; /* mark number ok */ 14615692Sralph if ((vp->tval & FLD) && isnull(vp->nval)) 1476678Smckusick donerec = 0; 1486678Smckusick return(vp->fval = f); 1496678Smckusick } 1506678Smckusick 1516678Smckusick char *setsval(vp, s) 1526678Smckusick register cell *vp; 1536678Smckusick char *s; 1546678Smckusick { 1556678Smckusick dprintf("setsval: %o %s\n", vp, s, NULL); 1566678Smckusick checkval(vp); 1576678Smckusick if (vp == recloc) 1586678Smckusick error(FATAL, "can't set $0"); 1596678Smckusick vp->tval &= ~NUM; 1606678Smckusick vp->tval |= STR; 16115692Sralph if ((vp->tval & FLD) && isnull(vp->nval)) 1626678Smckusick donerec = 0; 1636678Smckusick if (!(vp->tval&FLD)) 16410795Ssam strfree(vp->sval); 1656678Smckusick vp->tval &= ~FLD; 1666678Smckusick return(vp->sval = tostring(s)); 1676678Smckusick } 1686678Smckusick 1696678Smckusick awkfloat getfval(vp) 1706678Smckusick register cell *vp; 1716678Smckusick { 1726678Smckusick 1736678Smckusick if (vp->sval == record && donerec == 0) 1746678Smckusick recbld(); 1756678Smckusick dprintf("getfval: %o", vp, NULL, NULL); 1766678Smckusick checkval(vp); 1776678Smckusick if ((vp->tval & NUM) == 0) { 1786678Smckusick /* the problem is to make non-numeric things */ 1796678Smckusick /* have unlikely numeric variables, so that */ 1806678Smckusick /* $1 == $2 comparisons sort of make sense when */ 1816678Smckusick /* one or the other is numeric */ 1826678Smckusick if (isnumber(vp->sval)) { 1836678Smckusick vp->fval = atof(vp->sval); 1846678Smckusick if (!(vp->tval & CON)) /* don't change type of a constant */ 1856678Smckusick vp->tval |= NUM; 1866678Smckusick } 1876678Smckusick else 1886678Smckusick vp->fval = 0.0; /* not a very good idea */ 1896678Smckusick } 1906678Smckusick dprintf(" %g\n", vp->fval, NULL, NULL); 1916678Smckusick return(vp->fval); 1926678Smckusick } 1936678Smckusick 1946678Smckusick char *getsval(vp) 1956678Smckusick register cell *vp; 1966678Smckusick { 1976678Smckusick char s[100]; 1986678Smckusick 1996678Smckusick if (vp->sval == record && donerec == 0) 2006678Smckusick recbld(); 2016678Smckusick dprintf("getsval: %o", vp, NULL, NULL); 2026678Smckusick checkval(vp); 2036678Smckusick if ((vp->tval & STR) == 0) { 2046678Smckusick if (!(vp->tval&FLD)) 20510795Ssam strfree(vp->sval); 2066678Smckusick if ((long)vp->fval==vp->fval) 20732425Sbostic (void)sprintf(s, "%.20g", vp->fval); 2086678Smckusick else 20932425Sbostic (void)sprintf(s, *OFMT, vp->fval); 2106678Smckusick vp->sval = tostring(s); 2116678Smckusick vp->tval &= ~FLD; 2126678Smckusick vp->tval |= STR; 2136678Smckusick } 2146678Smckusick dprintf(" %s\n", vp->sval, NULL, NULL); 2156678Smckusick return(vp->sval); 2166678Smckusick } 2176678Smckusick 2186678Smckusick checkval(vp) 2196678Smckusick register cell *vp; 2206678Smckusick { 2216678Smckusick if (vp->tval & ARR) 2226678Smckusick error(FATAL, "illegal reference to array %s", vp->nval); 2236678Smckusick if ((vp->tval & (NUM | STR)) == 0) 2246678Smckusick error(FATAL, "funny variable %o: %s %s %g %o", vp, vp->nval, 2256678Smckusick vp->sval, vp->fval, vp->tval); 2266678Smckusick } 2276678Smckusick 2286678Smckusick char *tostring(s) 2296678Smckusick register char *s; 2306678Smckusick { 2316678Smckusick register char *p; 2326678Smckusick 23310795Ssam if (s==NULL){ 23410795Ssam p = malloc(1); 23510795Ssam if (p == NULL) 23610795Ssam error(FATAL, "out of space in tostring on %s", s); 23710795Ssam *p = '\0'; 23810795Ssam } else { 23910795Ssam p = malloc(strlen(s)+1); 24010795Ssam if (p == NULL) 24110795Ssam error(FATAL, "out of space in tostring on %s", s); 24210795Ssam strcpy(p, s); 24310795Ssam } 2446678Smckusick return(p); 2456678Smckusick } 2466678Smckusick #ifndef yfree 2476678Smckusick yfree(a) char *a; 2486678Smckusick { 2496678Smckusick printf("%o\n", a); 2506678Smckusick free(a); 2516678Smckusick } 2526678Smckusick #endif 2536678Smckusick #ifdef malloc 2546678Smckusick #undef malloc 2556678Smckusick char *ymalloc(u) unsigned u; 2566678Smckusick { char *p; 2576678Smckusick p = malloc(u); 2586678Smckusick printf("%o %o\n", u, p); 2596678Smckusick return(p); 2606678Smckusick } 2616678Smckusick #endif 262