v.c

Go to the documentation of this file.
00001 /*
00002  * a small awk clone
00003  *
00004  * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
00005  *
00006  * Absolutely no warranty. Use this software with your own risk.
00007  *
00008  * Permission to use, copy, modify and distribute this software for any
00009  * purpose and without fee is hereby granted, provided that the above
00010  * copyright and disclaimer notice.
00011  *
00012  * This program was written to fit into 64K+64K memory of the Minix 1.2.
00013  */
00014 
00015 
00016 #include <stdio.h>
00017 #include <ctype.h>
00018 #include "awk.h"
00019 #include "regexp.h"
00020 
00021 #define PI      3.14159265358979323846
00022 
00023 #define HASHSIZE        50
00024 #define MAXFIELD        100
00025 
00026 double atof();
00027 char *getsval(), *jStrchar();
00028 extern CELL *execute(), *_Arg();
00029 
00030 extern char record[];
00031 extern CELL *field[];
00032 
00033 extern CELL truecell, falsecell;
00034 extern prmflg;
00035 
00036 SYMBOL *hashtab[HASHSIZE];
00037 SYMBOL *funtab[HASHSIZE];
00038 SYMBOL *argtab[HASHSIZE];
00039 
00040 char *strsave(), *emalloc(), *strchr();
00041 CELL *lookup(), *install(), *_install(), *mkcell(), *mktmp(), *getvar();
00042 
00043 char **FS, **RS, **OFS, **ORS, **OFMT, **FILENAME;
00044 char **SUBSEP;
00045 double *NR, *NF;
00046 double *FNR, *ARGC, *RSTART, *RLENGTH;
00047 
00048 init()
00049 {
00050   FS = &install("FS", VAR|STR, " ", 0.0, hashtab)->c_sval;
00051   RS = &install("RS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
00052   OFS = &install("OFS", VAR|STR , " ", 0.0, hashtab)->c_sval;
00053   ORS = &install("ORS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
00054   OFMT = &install("OFMT", VAR|STR, "%.6g", 0.0, hashtab)->c_sval;
00055   NR = &install("NR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
00056   NF = &install("NF", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
00057   FILENAME = &install("FILENAME", VAR|STR, (char *)NULL, 0.0, hashtab)->c_sval;
00058   install("PI", VAR|NUM, (char *)NULL, PI, hashtab);
00059   field[0] = mkcell(REC|STR, (char *)NULL, 0.0);        /* $0 */
00060   field[0]->c_sval = record;
00061   SUBSEP = &install("SUBSEP", VAR|STR, "\034", 0.0, hashtab)->c_sval;
00062   FNR = &install("FNR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
00063   RSTART = &install("RSTART", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
00064   RLENGTH = &install("RLENGTH", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
00065 }
00066 
00067 setvar(s) char *s;
00068 {
00069   CELL *u;
00070   char *t;
00071 
00072   for (t = s; *t && *t != '='; t++)
00073         ;
00074   *t++ = '\0';
00075   if ((u = lookup(s, hashtab)) == (CELL *)NULL) {
00076         if (isnum(t))
00077                 install(s, VAR|NUM|STR, t, atof(t), hashtab);
00078         else
00079                 install(s, VAR|STR, t, 0.0, hashtab);
00080   }
00081   else {
00082         if (isnum(t))
00083                 setfval(u, atof(t));
00084         else
00085                 setsval(u, t);
00086   }
00087 }
00088 
00089 initarg(arg0, argc, argv) char *arg0, **argv;
00090 {
00091   CELL *u;
00092   register int i;
00093   register char str[4];
00094 
00095   ARGC = &install("ARGC", VAR|NUM, (char *)NULL, (double)argc+1, hashtab)->c_fval;
00096   u = install("ARGV", ARR, (char *)NULL, 0.0, hashtab);
00097   u->c_sval = (char *) argtab;
00098   install("0", VAR|STR, arg0, 0.0, argtab);
00099   for (i = 0; i < argc; i++) {
00100         sprintf(str, "%d", i+1);
00101         if (isnum(argv[i]))
00102                 install(str, VAR|STR|NUM, argv[i], atof(argv[i]), argtab);
00103         else
00104                 install(str, VAR|STR, argv[i], 0.0, argtab);
00105   }
00106 }
00107 
00108 static
00109 hash(s) unsigned char *s;
00110 {
00111   register unsigned int h;
00112 
00113   for (h = 0; *s; )
00114         h += *s++;
00115   return h % HASHSIZE;
00116 }
00117 
00118 CELL *
00119 lookup(s, h) char *s; SYMBOL *h[];
00120 {
00121   register SYMBOL *p;
00122 
00123   for (p = h[hash(s)]; p; p = p->s_next)
00124         if (strcmp(s, p->s_name) == 0)
00125                 return p->s_val;
00126   return (CELL *)NULL;
00127 }
00128 
00129 static CELL *
00130 install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];
00131 {
00132   CELL *u;
00133 
00134   if ((u = lookup(name, h)) == (CELL *)NULL)
00135         u = _install(name, type, sval, fval, h);
00136   else
00137         error("%s is doubly defined", name);
00138   return u;
00139 }
00140 
00141 static CELL *
00142 _install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];{
00143   register SYMBOL *p;
00144   CELL *u;
00145   int hval;
00146 
00147   p = (SYMBOL *) emalloc(sizeof(*p));
00148   u = (CELL *) emalloc(sizeof(*u));
00149   p->s_name = strsave(name);
00150   p->s_val = u;
00151   hval = hash(name);
00152   p->s_next = h[hval];
00153   h[hval] = p;
00154   u->c_type = type;
00155   u->c_sval = strsave(sval);
00156 #if 0
00157   if (!(type & NUM) && isnum(sval)) {
00158         u->c_fval = atof(sval);
00159         u->c_type |= NUM;
00160   }
00161   else
00162 #endif
00163         u->c_fval = fval;
00164   return u;
00165 }
00166 
00167 CELL *
00168 getvar(s, h, typ) char *s; SYMBOL *h[];
00169 {
00170   CELL *u;
00171   SYMBOL *p;
00172   char *t;
00173   int i, hval;
00174 
00175   if ((u = lookup(s, h)) == (CELL *)NULL) {
00176         if (prmflg) {
00177                 u = _install(s, UDF, "", 0.0, h);
00178                 goto rtn;
00179         }
00180         else if (typ & ARR) {
00181                 t = emalloc(sizeof(SYMBOL *) * HASHSIZE);
00182                 for (i = 0; i < HASHSIZE; i++)
00183                         ((SYMBOL **) t)[i] = (SYMBOL *)NULL;
00184                 u = (CELL *) emalloc(sizeof(*u));
00185                 u->c_type = typ;
00186                 u->c_sval = t;
00187                 u->c_fval = 0.0;
00188                 p = (SYMBOL *) emalloc(sizeof(*p));
00189                 p->s_name = strsave(s);
00190                 p->s_val = u;
00191                 hval = hash(s);
00192                 p->s_next = h[hval];
00193                 h[hval] = p;
00194         }
00195         else
00196                 u = _install(s, typ, "", 0.0, h);
00197   }
00198   else if (!prmflg && (u->c_type == UDF) && (typ != UDF)) {
00199         /* fix up local_var/forward_function */
00200         if (typ == ARR) {
00201 /*
00202 printf("getvar_correct_to_array\n");
00203 */
00204                 u->c_type = typ;
00205                 sfree(u->c_sval);
00206                 u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
00207                 for (i = 0; i < HASHSIZE; i++)
00208                         ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
00209                 u->c_fval = 0.0;
00210         }
00211         else if (typ != UDF) {
00212                 u->c_type = typ;
00213         }
00214  }
00215 rtn:
00216   return u;
00217 }
00218 
00219 fixarray(u) CELL *u;
00220 {
00221   int i;
00222 
00223   if (u->c_type == UDF) {       /* fix up local var */
00224 /*
00225 printf("fixarray\n");
00226 */
00227         u->c_type = ARR;
00228         sfree(u->c_sval);
00229         u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
00230         for (i = 0; i < HASHSIZE; i++)
00231                 ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
00232         u->c_fval = 0.0;
00233   }
00234 }
00235 
00236 a_free(u) CELL *u;
00237 {       /* free local array */
00238   SYMBOL **h, *q, *r;
00239   CELL *v;
00240   int i;
00241 
00242   if (!(u->c_type & ARR))
00243         error("try to free non array variable", (char *)0);
00244   h = (SYMBOL **) u->c_sval;
00245   for (i = 0; i < HASHSIZE; i++)
00246         for (q = h[i]; q; q = r) {
00247                 r = q->s_next;
00248                 sfree(q->s_name);
00249                 v = q->s_val;   /* CELL */
00250                 c_free(v);
00251                 sfree(q);       /* SYMBOL */
00252         }
00253 
00254   sfree(u->c_sval);     /* symbol table */
00255   c_free(u);
00256 }
00257 
00258 CELL *
00259 Array(p) NODE *p;
00260 {
00261   CELL *u;
00262   char str[BUFSIZ];
00263   int i, n;
00264 
00265   CELL *v;
00266 
00267   u = (CELL *) p->n_arg[0];
00268   if (u->c_type == POS) {
00269         i = (int)u->c_fval;
00270 /*
00271 printf("**ARG_ARRAY(%d)*\n", i);
00272 */
00273         u = _Arg(i);
00274         if (u->c_type == UDF) { /* fix up local array */
00275 /*
00276 printf("local_var_to_array\n");
00277 */
00278                 fixarray(u);
00279         }
00280   }
00281   else if (!(u->c_type & ARR))
00282         error("non array refference");
00283   arrayelm(p, str);
00284   u = getvar(str, u->c_sval, VAR|NUM|STR);      /* "rtsort in AWK book */
00285   return u;
00286 }
00287 
00288 static
00289 arrayelm(p, s) NODE *p; char *s;
00290 {
00291   CELL *u;
00292   int i, n;
00293   char *t;
00294 
00295 /*
00296 char *tt = s;
00297 */
00298   n = (int) p->n_arg[1] + 2;
00299   for (i = 2; i < n; i++) {
00300         if (i > 2)
00301                 *s++ = **SUBSEP;
00302         u = execute(p->n_arg[i]);
00303         for (t = getsval(u); *t; )
00304                 *s++ = *t++;
00305         c_free(u);
00306   }
00307   *s = '\0';
00308 /*
00309 printf("array_elm(%s)\n", tt);
00310 */
00311 }
00312 
00313 CELL *
00314 Element(p) NODE *p;
00315 {
00316   char str[BUFSIZ];
00317 
00318   arrayelm(p, str);
00319   return mktmp(STR, str, 0.0);
00320 }
00321 
00322 CELL *
00323 Delete(p) NODE *p;
00324 {
00325   CELL *u;
00326   char str[BUFSIZ];
00327   int i;
00328   SYMBOL *q, *r, **h;
00329 
00330   u = (CELL *) p->n_arg[0];
00331   if (!(u->c_type & ARR))
00332         error("can't delete non array variable");
00333   arrayelm(p, str);
00334   h = (SYMBOL **) u->c_sval;
00335   for (r = (SYMBOL *)NULL, i = hash(str), q = h[i]; q; r = q, q = q->s_next)
00336         if (strcmp(str, q->s_name) == 0)
00337                 break;
00338   if (q) {
00339         sfree(q->s_val->c_sval);
00340         sfree(q->s_name);
00341         if (r)
00342                 r->s_next = q->s_next;
00343         if (q == h[i])
00344                 h[i] = (SYMBOL *)NULL;
00345   }
00346   return &truecell;
00347 }
00348 
00349 CELL *
00350 In(p) NODE *p;
00351 {
00352   SYMBOL **h, *q;
00353   CELL *u, *v;
00354   char *s;
00355   int i;
00356 
00357   u = (CELL *) p->n_arg[1];     /* array */
00358   if (!(u->c_type & ARR))
00359         error("%s is not an array", u->c_sval);
00360   h = (SYMBOL **) u->c_sval;
00361   if (u->c_sval != (char *)NULL) {
00362         v = execute(p->n_arg[0]);       /* var */
00363         s = getsval(v);
00364         for (i = 0; i < HASHSIZE; i++)
00365                 for (q = h[i]; q; q = q->s_next) {
00366                         if (strcmp(s, q->s_name) == 0) {
00367                                 c_free(v);
00368                                 return &truecell;
00369                         }
00370                 }
00371         c_free(v);
00372   }
00373   return &falsecell;
00374 }
00375 
00376 CELL *
00377 Split(p) NODE *p;
00378 {
00379   CELL *u, *v, *w;
00380   char *s, *t, *h, *name, *sep;
00381   int i, n, skip;
00382   char elm[8], str[BUFSIZ];
00383   static char *s_str;
00384   static regexp *s_pat;
00385   regexp *mkpat();
00386   extern int r_start, r_length;
00387 
00388   n = (int) p->n_arg[1];
00389   if (n > 1) {
00390         u = execute(p->n_arg[2]);
00391         s = getsval(u);                 /* str */
00392         v = execute(p->n_arg[3]);       /* array */
00393         if (!(v->c_type & ARR)) {
00394 /*
00395 printf("Split fix_to_array(%d)\n", v->c_type);
00396 */
00397                 if (v->c_type == UDF)   /* fix up local array */
00398                         fixarray(v);
00399                 else
00400                         error("split to non array variable", (char *)0);
00401         }
00402         h = v->c_sval;
00403         c_free(v);
00404         if (n > 2) {
00405                 v = execute(p->n_arg[4]);
00406                 sep = getsval(v);
00407         }
00408         else {
00409                 v = (CELL *)NULL;
00410                 sep = *FS;
00411         }
00412         if (strlen(sep) > 1) {  /* reg_exp */
00413                 if (strcmp(sep, s_str) != 0) {
00414                         sfree(s_str); sfree(s_pat);
00415                         s_str = strsave(sep);
00416                         s_pat = mkpat(s_str);
00417                 }
00418                 for (i = 0, t = str; *s; ) {
00419                         if (match(s_pat, s)) {
00420                                 for (n = r_start; --n > 0; )
00421                                         *t++ = *s++;
00422                         }
00423                         else {
00424                                 while(*s)
00425                                         *t++ = *s++;
00426                         }
00427                         *t = '\0';
00428                         t = str;
00429                         sprintf(elm, "%d", ++i);
00430                         w = getvar(elm, h, VAR);
00431                         if (isnum(str))
00432                                 setfval(w, atof(str));
00433                         else
00434                                 setsval(w, str);
00435                         if (*s)
00436                                 s += r_length;
00437                 }
00438         }
00439         else {
00440                 skip = *sep == ' ';
00441                 for (i = 0; t = str, *s; ) {
00442                         if (skip)
00443                                 while (jStrchr(" \t\n", *s))
00444                                         s++;
00445                         if (!(*s))
00446                                 break;
00447                         while (*s && !jStrchr(sep, *s)) {
00448                                 if (isKanji(*s))
00449                                         *t++ = *s++;
00450                                 *t++ = *s++;
00451                         }
00452                         *t = '\0';
00453                         sprintf(elm, "%d", ++i);
00454                         w = getvar(elm, h, VAR);
00455                         if (isnum(str))
00456                                 setfval(w, atof(str));
00457                         else
00458                                 setsval(w, str);
00459                         if (*s && !skip)
00460                                 s++;
00461                 }
00462         }
00463         c_free(v);      /* sep */
00464         c_free(u);      /* str may be CATed */
00465   }
00466   else
00467         i = 0;
00468   return mktmp(NUM, (char *)NULL, (double) i);
00469 }
00470 
00471 CELL *
00472 Forin(p) NODE *p;
00473 {
00474   CELL *u, *v;
00475   SYMBOL **h, *q;
00476   char *name;
00477   int i;
00478 
00479   u = execute(p->n_arg[1]);
00480   if (!(u->c_type & ARR))
00481         synerr(
00482         "non array variable is specified in 'for (. in var)'", (char *)0);
00483   h = (SYMBOL **) u->c_sval;
00484   c_free(u);
00485   u = execute(p->n_arg[0]);
00486   if (u->c_type == UDF) {
00487 /*
00488 printf("Forin_fix_to_VAR|NUM\n");
00489 */
00490         u->c_type = VAR|NUM;
00491   }
00492   if (!(u->c_type & VAR))
00493         error("'for (VAR in .)' is not variable (%d)", name, u->c_type);
00494   for (i = 0; i < HASHSIZE; i++) {
00495         for (q = h[i]; q; q = q->s_next) {
00496                 setsval(u, q->s_name);
00497                 v = execute(p->n_arg[2]);
00498                 c_free(v);
00499         }
00500   }
00501   c_free(u);
00502   return &truecell;
00503 }
00504 
00505 char *
00506 strsave(s) char *s;
00507 {
00508   register int n;
00509   char *emalloc(), *strcpy();
00510 
00511   if (s == (char *)NULL)
00512         return (char *)NULL;
00513   n = strlen(s) + 1;
00514   return strcpy(emalloc(n), s);
00515 }
00516 
00517 sfree(p) char *p;
00518 {
00519   if (p != (char *)NULL)
00520         Free(p);
00521 }
00522 
00523 isnum(s) char *s;
00524 {
00525   char *strchr();
00526 
00527   if (s == NULL || *s == '\0' || !strcmp(s, "."))
00528         return 0;
00529   if (*s && strchr("+-", *s) != (char *)NULL)
00530         s++;
00531   if (*s == '\0')
00532         return 0;
00533   while (isdigit(*s))
00534         s++;
00535   if (*s == '.') {
00536         s++;
00537         while (isdigit(*s))
00538                 s++;
00539   }
00540   if (*s && strchr("eE", *s) != (char *)NULL) {
00541         s++;
00542         if (*s == '\0')
00543                 return 0;
00544         if (*s && strchr("+-", *s) != (char *)NULL)
00545                 s++;
00546         while (isdigit(*s))
00547                 s++;
00548   }
00549   return *s == '\0';
00550 }
00551 
00552 setfval(u, f) CELL *u; double f;
00553 {
00554   if (u->c_type == UDF) {       /* fix up local var */
00555 /*
00556 printf("setfval_fix_to_VAR\n");
00557 */
00558         u->c_type |= VAR;
00559   }
00560   if (u->c_type & (VAR|FLD|REC|TMP)) {
00561         u->c_type &= ~STR;
00562         u->c_type |= NUM;
00563         sfree(u->c_sval);
00564         u->c_sval = (char *)NULL;
00565         u->c_fval = f;
00566         if (u->c_type & FLD)
00567                 mkrec(u);
00568   }
00569   else
00570         fprintf(stderr, "assign to nonvariable (%d)\n", u->c_type);
00571 }
00572 
00573 setsval(u, s) CELL *u; char *s;
00574 {
00575   double atof();
00576 
00577   if (u->c_type == UDF) {       /* fix up local var */
00578 /*
00579 printf("setsval_fix_to_VAR\n");
00580 */
00581         u->c_type |= VAR;
00582   }
00583   if (u->c_type & (VAR|FLD|REC|TMP)) {
00584         u->c_type &= ~NUM;
00585         u->c_type |= STR;
00586         sfree(u->c_sval);
00587         u->c_sval = strsave(s);
00588 #if 0   /* "table2" in AWK book */
00589         if (isnum(u->c_sval)) {
00590                 u->c_fval = atof(u->c_sval);
00591                 u->c_type |= NUM;
00592         }
00593         else
00594 #endif
00595                 u->c_fval = 0.0;
00596         if (u->c_type & FLD)
00597                 mkrec(u);
00598   }
00599   else
00600         fprintf(stderr, "assign to constant (%d)\n", u->c_type);
00601 }
00602 
00603 double
00604 getfval(u) CELL *u;
00605 {
00606   double x, atof();
00607 
00608   if (u->c_type == UDF) {       /* local var */
00609         u->c_type |= VAR|STR|NUM;
00610         u->c_sval = strsave("");
00611         x = u->c_fval = 0.0;
00612   }
00613   else if (u->c_type & NUM)
00614         x = u->c_fval;
00615 #if 1
00616   else {
00617         x = atof(u->c_sval);
00618 #else
00619   else {
00620         if (isnum(u->c_sval))
00621                 x = atof(u->c_sval);
00622         else
00623                 x = 0.0;
00624 #endif
00625   }
00626   return x;
00627 }
00628 
00629 char *
00630 getsval(u) CELL *u;
00631 {
00632   char *s, str[80];
00633 
00634   if (u->c_type & STR)
00635         s = u->c_sval;
00636   else if (u->c_type & NUM) {
00637 /*      if (u->c_fval >= -2147483648.0 && u->c_fval <= 2147483647.0)*/
00638         if ((long)u->c_fval == u->c_fval)
00639                 s = "%.16g";
00640         else
00641                 s = *OFMT;
00642         sprintf(str, s, u->c_fval);
00643         sfree(u->c_sval);
00644         s = u->c_sval = strsave(str);
00645   }
00646 #if 1
00647   else if (u->c_type == UDF) {  /* local var */
00648 /*
00649 printf("getsval_fix_to_VAR|STR\n");
00650 */
00651         u->c_type |= VAR|STR|NUM;
00652         s = u->c_sval = strsave("");
00653         u->c_fval = 0.0;
00654   }
00655 #endif
00656   else
00657         fprintf(stderr, "abnormal value (STR|NUM == 0)(%d)\n", u->c_type);
00658   return s;
00659 }
00660 
00661 char *
00662 emalloc(n) unsigned n;
00663 {
00664   char *p;
00665 #if 0
00666   char far *_fmalloc();
00667 #else
00668   char *malloc();
00669 #endif
00670 
00671 #if 0
00672   if ((p = _fmalloc(n)) == (char *)NULL)
00673 #else
00674   if ((p = malloc(n)) == (char *)NULL)
00675 #endif
00676         error("memory over");
00677   return p;
00678 }
00679 
00680 Free(s) char *s;
00681 {
00682 #if DOS
00683   void _ffree();
00684 
00685   _ffree(s);
00686 #else
00687   free(s);
00688 #endif
00689 }

Generated on Fri Apr 14 22:56:41 2006 for minix by  doxygen 1.4.6