1*14475Ssam #ifndef lint 2*14475Ssam static char sccsid[] = "@(#)tran.c 4.3 08/11/83"; 3*14475Ssam #endif 46678Smckusick 56678Smckusick #include "stdio.h" 66678Smckusick #include "awk.def" 76678Smckusick #include "awk.h" 86678Smckusick 96678Smckusick cell *symtab[MAXSYM]; /* symbol table pointers */ 106678Smckusick 116678Smckusick char **FS; /* initial field sep */ 126678Smckusick char **RS; /* initial record sep */ 136678Smckusick char **OFS; /* output field sep */ 146678Smckusick char **ORS; /* output record sep */ 156678Smckusick char **OFMT; /*output format for numbers*/ 166678Smckusick awkfloat *NF; /* number of fields in current record */ 176678Smckusick awkfloat *NR; /* number of current record */ 186678Smckusick char **FILENAME; /* current filename argument */ 196678Smckusick 206678Smckusick cell *recloc; /* location of record */ 216678Smckusick cell *nrloc; /* NR */ 226678Smckusick cell *nfloc; /* NF */ 236678Smckusick 246678Smckusick syminit() 256678Smckusick { 266678Smckusick setsymtab("0", tostring("0"), 0.0, NUM|STR|CON|FLD, symtab); 276678Smckusick /* this one is used for if(x)... tests: */ 286678Smckusick setsymtab("$zero&null", tostring(""), 0.0, NUM|STR|CON|FLD, symtab); 296678Smckusick recloc = setsymtab("$record", record, 0.0, STR|FLD, symtab); 306678Smckusick dprintf("recloc %o lookup %o\n", recloc, lookup("$record", symtab, 0), NULL); 316678Smckusick FS = &setsymtab("FS", tostring(" "), 0.0, STR|FLD, symtab)->sval; 326678Smckusick RS = &setsymtab("RS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; 336678Smckusick OFS = &setsymtab("OFS", tostring(" "), 0.0, STR|FLD, symtab)->sval; 346678Smckusick ORS = &setsymtab("ORS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; 356678Smckusick OFMT = &setsymtab("OFMT", tostring("%.6g"), 0.0, STR|FLD, symtab)->sval; 3610795Ssam FILENAME = &setsymtab("FILENAME", EMPTY, 0.0, STR|FLD, symtab)->sval; 3710795Ssam nfloc = setsymtab("NF", EMPTY, 0.0, NUM, symtab); 386678Smckusick NF = &nfloc->fval; 3910795Ssam nrloc = setsymtab("NR", EMPTY, 0.0, NUM, symtab); 406678Smckusick NR = &nrloc->fval; 416678Smckusick } 426678Smckusick 436678Smckusick cell **makesymtab() 446678Smckusick { 456678Smckusick int i; 466678Smckusick cell **cp; 476678Smckusick 486678Smckusick cp = (cell **) malloc(MAXSYM * sizeof(cell *)); 496678Smckusick if (cp == NULL) 506678Smckusick error(FATAL, "out of space in makesymtab"); 516678Smckusick for (i = 0; i < MAXSYM; i++) 526678Smckusick cp[i] = 0; 536678Smckusick return(cp); 546678Smckusick } 556678Smckusick 566678Smckusick freesymtab(ap) /* free symbol table */ 576678Smckusick cell *ap; 586678Smckusick { 596678Smckusick cell *cp, **tp; 606678Smckusick int i; 616678Smckusick 626678Smckusick if (!(ap->tval & ARR)) 636678Smckusick return; 646678Smckusick tp = (cell **) ap->sval; 656678Smckusick for (i = 0; i < MAXSYM; i++) { 666678Smckusick for (cp = tp[i]; cp != NULL; cp = cp->nextval) { 6710795Ssam strfree(cp->nval); 6810795Ssam strfree(cp->sval); 696678Smckusick free(cp); 706678Smckusick } 716678Smckusick } 726678Smckusick xfree(tp); 736678Smckusick } 746678Smckusick 756678Smckusick cell *setsymtab(n, s, f, t, tab) 766678Smckusick char *n, *s; 776678Smckusick awkfloat f; 786678Smckusick unsigned t; 796678Smckusick cell **tab; 806678Smckusick { 816678Smckusick register h; 826678Smckusick register cell *p; 836678Smckusick cell *lookup(); 846678Smckusick 856678Smckusick if (n != NULL && (p = lookup(n, tab, 0)) != NULL) { 8610795Ssam if (s != EMPTY ) xfree(s); /* careful here */ 876678Smckusick dprintf("setsymtab found %o: %s", p, p->nval, NULL); 886678Smckusick dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); 896678Smckusick return(p); 906678Smckusick } 916678Smckusick p = (cell *) malloc(sizeof(cell)); 926678Smckusick if (p == NULL) 936678Smckusick error(FATAL, "symbol table overflow at %s", n); 946678Smckusick p->nval = tostring(n); 956678Smckusick p->sval = s; 966678Smckusick p->fval = f; 976678Smckusick p->tval = t; 986678Smckusick h = hash(n); 996678Smckusick p->nextval = tab[h]; 1006678Smckusick tab[h] = p; 1016678Smckusick dprintf("setsymtab set %o: %s", p, p->nval, NULL); 1026678Smckusick dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); 1036678Smckusick return(p); 1046678Smckusick } 1056678Smckusick 1066678Smckusick hash(s) /* form hash value for string s */ 1076678Smckusick register unsigned char *s; 1086678Smckusick { 1096678Smckusick register int hashval; 1106678Smckusick 1116678Smckusick for (hashval = 0; *s != '\0'; ) 1126678Smckusick hashval += *s++; 1136678Smckusick return(hashval % MAXSYM); 1146678Smckusick } 1156678Smckusick 1166678Smckusick cell *lookup(s, tab, flag) /* look for s in tab, flag must match*/ 1176678Smckusick register char *s; 1186678Smckusick cell **tab; 1196678Smckusick { 1206678Smckusick register cell *p; 1216678Smckusick 1226678Smckusick for (p = tab[hash(s)]; p != NULL; p = p->nextval) 1236678Smckusick if (strcmp(s, p->nval) == 0 && 1246678Smckusick (flag == 0 || flag == p->tval)) 1256678Smckusick return(p); /* found it */ 1266678Smckusick return(NULL); /* not found */ 1276678Smckusick } 1286678Smckusick 1296678Smckusick awkfloat setfval(vp, f) 1306678Smckusick register cell *vp; 1316678Smckusick awkfloat f; 1326678Smckusick { 1336678Smckusick dprintf("setfval: %o %g\n", vp, f, NULL); 1346678Smckusick checkval(vp); 1356678Smckusick if (vp == recloc) 1366678Smckusick error(FATAL, "can't set $0"); 1376678Smckusick vp->tval &= ~STR; /* mark string invalid */ 1386678Smckusick vp->tval |= NUM; /* mark number ok */ 1396678Smckusick if ((vp->tval & FLD) && vp->nval == 0) 1406678Smckusick donerec = 0; 1416678Smckusick return(vp->fval = f); 1426678Smckusick } 1436678Smckusick 1446678Smckusick char *setsval(vp, s) 1456678Smckusick register cell *vp; 1466678Smckusick char *s; 1476678Smckusick { 1486678Smckusick dprintf("setsval: %o %s\n", vp, s, NULL); 1496678Smckusick checkval(vp); 1506678Smckusick if (vp == recloc) 1516678Smckusick error(FATAL, "can't set $0"); 1526678Smckusick vp->tval &= ~NUM; 1536678Smckusick vp->tval |= STR; 1546678Smckusick if ((vp->tval & FLD) && vp->nval == 0) 1556678Smckusick donerec = 0; 1566678Smckusick if (!(vp->tval&FLD)) 15710795Ssam strfree(vp->sval); 1586678Smckusick vp->tval &= ~FLD; 1596678Smckusick return(vp->sval = tostring(s)); 1606678Smckusick } 1616678Smckusick 1626678Smckusick awkfloat getfval(vp) 1636678Smckusick register cell *vp; 1646678Smckusick { 1656678Smckusick 1666678Smckusick if (vp->sval == record && donerec == 0) 1676678Smckusick recbld(); 1686678Smckusick dprintf("getfval: %o", vp, NULL, NULL); 1696678Smckusick checkval(vp); 1706678Smckusick if ((vp->tval & NUM) == 0) { 1716678Smckusick /* the problem is to make non-numeric things */ 1726678Smckusick /* have unlikely numeric variables, so that */ 1736678Smckusick /* $1 == $2 comparisons sort of make sense when */ 1746678Smckusick /* one or the other is numeric */ 1756678Smckusick if (isnumber(vp->sval)) { 1766678Smckusick vp->fval = atof(vp->sval); 1776678Smckusick if (!(vp->tval & CON)) /* don't change type of a constant */ 1786678Smckusick vp->tval |= NUM; 1796678Smckusick } 1806678Smckusick else 1816678Smckusick vp->fval = 0.0; /* not a very good idea */ 1826678Smckusick } 1836678Smckusick dprintf(" %g\n", vp->fval, NULL, NULL); 1846678Smckusick return(vp->fval); 1856678Smckusick } 1866678Smckusick 1876678Smckusick char *getsval(vp) 1886678Smckusick register cell *vp; 1896678Smckusick { 1906678Smckusick char s[100]; 1916678Smckusick 1926678Smckusick if (vp->sval == record && donerec == 0) 1936678Smckusick recbld(); 1946678Smckusick dprintf("getsval: %o", vp, NULL, NULL); 1956678Smckusick checkval(vp); 1966678Smckusick if ((vp->tval & STR) == 0) { 1976678Smckusick if (!(vp->tval&FLD)) 19810795Ssam strfree(vp->sval); 1996678Smckusick if ((long)vp->fval==vp->fval) 2006678Smckusick sprintf(s, "%.20g", vp->fval); 2016678Smckusick else 2026678Smckusick sprintf(s, *OFMT, vp->fval); 2036678Smckusick vp->sval = tostring(s); 2046678Smckusick vp->tval &= ~FLD; 2056678Smckusick vp->tval |= STR; 2066678Smckusick } 2076678Smckusick dprintf(" %s\n", vp->sval, NULL, NULL); 2086678Smckusick return(vp->sval); 2096678Smckusick } 2106678Smckusick 2116678Smckusick checkval(vp) 2126678Smckusick register cell *vp; 2136678Smckusick { 2146678Smckusick if (vp->tval & ARR) 2156678Smckusick error(FATAL, "illegal reference to array %s", vp->nval); 2166678Smckusick if ((vp->tval & (NUM | STR)) == 0) 2176678Smckusick error(FATAL, "funny variable %o: %s %s %g %o", vp, vp->nval, 2186678Smckusick vp->sval, vp->fval, vp->tval); 2196678Smckusick } 2206678Smckusick 2216678Smckusick char *tostring(s) 2226678Smckusick register char *s; 2236678Smckusick { 2246678Smckusick register char *p; 2256678Smckusick 22610795Ssam if (s==NULL){ 22710795Ssam p = malloc(1); 22810795Ssam if (p == NULL) 22910795Ssam error(FATAL, "out of space in tostring on %s", s); 23010795Ssam *p = '\0'; 23110795Ssam } else { 23210795Ssam p = malloc(strlen(s)+1); 23310795Ssam if (p == NULL) 23410795Ssam error(FATAL, "out of space in tostring on %s", s); 23510795Ssam strcpy(p, s); 23610795Ssam } 2376678Smckusick return(p); 2386678Smckusick } 2396678Smckusick #ifndef yfree 2406678Smckusick yfree(a) char *a; 2416678Smckusick { 2426678Smckusick printf("%o\n", a); 2436678Smckusick free(a); 2446678Smckusick } 2456678Smckusick #endif 2466678Smckusick #ifdef malloc 2476678Smckusick #undef malloc 2486678Smckusick char *ymalloc(u) unsigned u; 2496678Smckusick { char *p; 2506678Smckusick p = malloc(u); 2516678Smckusick printf("%o %o\n", u, p); 2526678Smckusick return(p); 2536678Smckusick } 2546678Smckusick #endif 255