e.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 extern char **FS, **OFS, **ORS, **OFMT;
00022 extern double *RSTART, *RLENGTH;
00023 extern char record[];
00024 extern CELL *field[];
00025 
00026 extern int r_start, r_length;
00027 
00028 double getfval(), atof();
00029 char *strsave(), *getsval(), *strcat(), *strstr();
00030 CELL *mkcell(), *mktmp();
00031 CELL *Field(), *Split(), *Forin();
00032 CELL *Arith(), *Assign(), *Stat(), *Mathfun(), *Strfun(), *Cond();
00033 CELL *Print(), *Cat(), *Array(), *Element();
00034 CELL *If(), *While(), *For(), *Do(), *Jump();
00035 CELL *P1stat(), *P2stat(), *Print0();
00036 CELL *Arg(), *Call(), *Ret();
00037 CELL *Subst(), *In(), *Getline(), *Delete(), *Close();
00038 CELL *Nulproc(), *Usrfun();
00039 CELL *_Arg();
00040 
00041 FILE *getfp();  /* r.c */
00042 
00043 CELL truecell = { NUM, NULL, 1.0 };
00044 CELL falsecell = { NUM, NULL, 0.0 };
00045 static CELL breakcell = { BRK, NULL, 0.0 };
00046 static CELL contcell = { CNT, NULL, 0.0 };
00047 static CELL nextcell = { NXT, NULL, 0.0 };
00048 static CELL retcell = { RTN, NULL, 0.0 };
00049 
00050 static CELL *retval;    /* function return value */
00051 
00052 int pateval;    /* used in P1STAT & P2STAT */
00053 static char *r_str;     /* STR in 'str ~ STR */
00054 static regexp *r_pat;   /* compiled pattern for STR */
00055 
00056 CELL *(*proctab[])() = {
00057   Arg, Arith, Array, Assign, Call, Cat, Cond, Delete, Do, Element,
00058   Field, For, Forin, Getline, If, In, Jump, Mathfun, Nulproc, P1stat,
00059   P2stat, Print, Print0, Strfun, Subst, Usrfun, While
00060 };
00061 
00062 CELL *
00063 execute(p) NODE *p;
00064 {
00065   int type, i;
00066   CELL *r, *(*proc)();
00067 
00068   type = p->n_type;
00069   if (type == VALUE) {
00070         if ((r = (CELL *) p->n_arg[0])->c_type & PAT && pateval) {
00071                 i = match(r->c_sval, (char *)record) ? 1 : 0;
00072                 r = mktmp(NUM, NULL, (double) i);
00073         }
00074         return r;
00075   }
00076   for ( ; p != NULL; p = p->n_next) {
00077 #if 0
00078         if (p->n_type == VALUE) continue;       /* neglect */
00079 #endif
00080 /*
00081         switch ((int) p->n_type) {
00082         case ARRAY:
00083                 r = Array(p);
00084                 break;
00085         case ARITH:
00086                 r = Arith(p);
00087                 break;
00088         case ASSIGN:
00089                 r = Assign(p);
00090                 break;
00091         case PRINT:
00092                 r = Print(p);
00093                 break;
00094         case PRINT0:
00095                 r = Print0(p);
00096                 break;
00097         case CAT:
00098                 r = Cat(p);
00099                 break;
00100         case MATHFUN:
00101                 r = Mathfun(p);
00102                 break;
00103         case STRFUN:
00104                 r = Strfun(p);
00105                 break;
00106         case COND:
00107                 r = Cond(p);
00108                 break;
00109         case IF:
00110                 r = If(p);
00111                 break;
00112         case P1STAT:
00113                 r = P1stat(p);
00114                 break;
00115         case P2STAT:
00116                 r = P2stat(p);
00117                 break;
00118         case WHILE:
00119                 r = While(p);
00120                 break;
00121         case DO:
00122                 r = Do(p);
00123                 break;
00124         case FOR:
00125                 r = For(p);
00126                 break;
00127         case FORIN:
00128                 r = Forin(p);
00129                 break;
00130         case FIELD:
00131                 r = Field(p);
00132                 break;
00133         case JUMP:
00134                 r = Jump(p);
00135                 break;
00136         case ARG:
00137                 r = Arg(p);
00138                 break;
00139         case CALL:
00140                 r = Call(p);
00141                 break;
00142         case SUBST:
00143                 r = Subst(p);
00144                 break;
00145         case ELEMENT:
00146                 r = Element(p);
00147                 break;
00148         case IN:
00149                 r = In(p);
00150                 break;
00151         case GETLINE:
00152                 r = Getline(p);
00153                 break;
00154         case DELETE:
00155                 r = Delete(p);
00156                 break;
00157         case NULPROC:
00158                 r = &truecell;
00159                 break;
00160         default:
00161                 printf("PROGRAM ERROR ? ILLEGAL NODE TYPE(%d)\n", type);
00162                 exit(1);
00163                 break;
00164         }
00165 */
00166         i = (int) p->n_type;
00167         if (i < FIRSTP || i > LASTP)
00168                 error("ILLEGAL PROC (%d)", i);
00169         proc = proctab[i - FIRSTP];
00170         r = (*proc)(p);
00171         if (r->c_type & (BRK|CNT|NXT|RTN))
00172                 return r;
00173         if (p->n_next != NULL)
00174                 c_free(r);
00175 #ifdef DOS
00176         kbhit();        /* needs in MS-DOS */
00177 #endif
00178   }
00179   return r;
00180 }
00181 
00182 static CELL *
00183 Arith(p) NODE *p;
00184 {
00185   int op;
00186   CELL *r, *u, *v, *execute();
00187   double x, y, fmod(), pow();
00188 
00189   op = (int) p->n_arg[0];
00190   if (op == UMINUS) {
00191         u = execute(p->n_arg[1]);
00192         x = - getfval(u);
00193   }
00194   else if (op == INCDEC) {
00195         u = execute(p->n_arg[1]);
00196         x = getfval(u);
00197         setfval(u, x + (int) p->n_arg[2]);
00198         if ((int) p->n_arg[3] == PRE)
00199                 return u;
00200         /* return dummy */
00201   }
00202   else {
00203         u = execute(p->n_arg[1]);
00204         v = execute(p->n_arg[2]);
00205         x = getfval(u);
00206         y = getfval(v);
00207         if (op == DIV || op == MOD) {
00208                 if (y == 0.0)
00209                         fprintf(stderr, "divid by 0\n");
00210         }
00211         switch (op) {
00212         case SUB: x -= y;break;
00213         case ADD: x += y; break;
00214         case MULT: x *= y; break;
00215         case DIV:
00216                 if (y == 0.0)
00217                         error("division by zero in \"/\"", (char *)0);
00218                 x /= y; break;
00219         case MOD:
00220                 if (y == 0.0)
00221                         error("division by zero in \"%%\"", (char *)0);
00222                 x = fmod(x, y); break;
00223         case POWER: x = pow(x, y); break;
00224         default: printf("UNSUPPORTED ARITH OPERATOR !\n"); break;
00225         }
00226         c_free(v);
00227   }
00228   c_free(u);
00229   r = mktmp(NUM, NULL, x);
00230   return r;
00231 }
00232 
00233 static CELL *
00234 Assign(p) NODE *p;
00235 {
00236   CELL *u, *v, *execute();
00237   int op;
00238   double x, y, fmod(), pow();
00239 
00240   op = (int) p->n_arg[0];
00241   u = execute(p->n_arg[1]);
00242 
00243 #if 0
00244   if (u->c_type == UDF) /* fix up local var */
00245         u->c_type |= VAR|STR;
00246 #endif
00247   if (!(u->c_type & (VAR|FLD|REC)) && (u->c_type != UDF))
00248         fprintf(stderr, "ASSIGN TO NON VARIABLE (%d)\n", u->c_type);
00249   v = execute(p->n_arg[2]);
00250 
00251   if (u == v)
00252         goto rtn;       /* same node */
00253 
00254   if (op == ASSIGN) {
00255         if (v->c_type & NUM/* || isnum(v->c_sval)*/)
00256                 setfval(u, getfval(v));
00257         else
00258                 setsval(u, getsval(v));
00259   }
00260   else {
00261         x = getfval(u);
00262         y = getfval(v);
00263         switch (op) {
00264         case ADDEQ:     x += y; break;
00265         case SUBEQ:     x -= y; break;
00266         case MULTEQ:    x *= y; break;
00267         case DIVEQ:
00268                 if (y == 0.0)
00269                         error("division by zero in \"/=\"", (char *)0);
00270                 x /= y; break;
00271         case MODEQ:
00272                 if (y == 0.0)
00273                         error("division by zero in \"%=\"", (char *)0);
00274                 x = fmod(x, y); break;
00275         case POWEQ:     x = pow(x, y); break;
00276         default:
00277                 synerr("illegal assign op (%d)", op);
00278                 break;
00279         }
00280         setfval(u, x);
00281   }
00282 rtn:
00283   c_free(v);
00284   return u;
00285 }
00286 
00287 static CELL *
00288 Cat(p) NODE *p;
00289 {
00290   CELL *u;
00291   char *s, *t, str[BUFSIZ];
00292 
00293   u = execute(p->n_arg[0]);
00294   s = getsval(u);
00295   for (t = str; *s; )
00296         *t++ = *s++;
00297   c_free(u);
00298   u = execute(p->n_arg[1]);
00299   s = getsval(u);
00300   while (*s)
00301         *t++ = *s++;
00302   c_free(u);
00303   *t = '\0';
00304  return mktmp(STR, str, 0.0);
00305 }
00306 
00307 static CELL *
00308 Print(p) NODE *p;
00309 {
00310   register int i, redir, typ;
00311   CELL *u;
00312   char *s, str[BUFSIZ];
00313   char *file;
00314   FILE *fp;
00315 
00316   redir = (int) p->n_arg[0];
00317   if (typ = redir & PRMASK) {   /* redirect */
00318         u = execute(p->n_arg[1]);
00319         file = getsval(u);
00320         if (typ == R_PIPE)
00321                 typ = R_POUT;
00322         fp = getfp(file, typ);
00323         c_free(u);
00324   }
00325   else
00326         fp = stdout;
00327   if (redir & FORMAT)   /* format */
00328         format(str, p);
00329   else {
00330         *str = '\0';
00331         for (i = 2; p->n_arg[i] != NULL; i++) {
00332                 if (i > 2)
00333                         strcat(str, *OFS);
00334                 u = execute(p->n_arg[i]);
00335                 s = getsval(u);
00336                 strcat(str, s);
00337                 c_free(u);
00338         }
00339         strcat(str, *ORS);
00340   }
00341   if (redir & STROUT)   /* sprintf */
00342         return mktmp(STR, str, 0.0);
00343   fputs(str, fp);
00344   fflush(fp);
00345   return &truecell;
00346 }
00347 
00348 static CELL *
00349 Mathfun(p) NODE *p;
00350 {
00351   CELL *u, *v;
00352   double x, y;
00353   double atan2(), cos(), exp(), log(), sin(), sqrt(), modf();
00354 
00355   if ((int) p->n_arg[1] == 0) {
00356         u = NULL;
00357         x = 0.0;
00358   }
00359   else {
00360         u = execute(p->n_arg[2]);
00361         x = getfval(u);
00362   }
00363   switch ((int) p->n_arg[0]) {
00364   case ATAN2:
00365         if ((int) p->n_arg[1] == 2) {
00366                 v = execute(p->n_arg[3]);
00367                 y = getfval(v);
00368                 x = atan2(x, y);
00369                 c_free(v);
00370         }
00371         else
00372                 x = 0.0;
00373         break;
00374   case COS:     x = cos(x); break;
00375   case EXP:     x = exp(x); break;
00376   case INT:     y = modf(x, &x); break;
00377   case LOG:     x = log(x); break;
00378   case SIN:     x = sin(x); break;
00379   case SQRT:    x = sqrt(x); break;
00380   case RAND:    x = (double) rand() / 32768.0; break;
00381   case SRAND:   if (x == 0.0)
00382                         x = (double) time(0);
00383                 x = (double) srand((int) x);
00384                 break;
00385   default:
00386         fprintf(stderr, "unknown math function (%d)\n", p->n_arg[2]);
00387         break;
00388   }
00389   if (u != NULL)
00390         c_free(u);
00391   return mktmp(NUM, NULL, x);
00392 }
00393 
00394 static CELL *
00395 Strfun(p) NODE *p;
00396 {
00397   CELL *u, *v, *r;
00398   char *s, *t, str[BUFSIZ];
00399   int i, m, n;
00400   double x;
00401   regexp *pat, *getpat();
00402 
00403   n = (int) p->n_arg[1];
00404   if (n > 0 && (int) p->n_arg[0] != SPLIT) {
00405         u = execute(p->n_arg[2]);
00406         s = getsval(u);
00407   }
00408   else {
00409         s = "";
00410         u = NULL;
00411   }
00412   switch ((int) p->n_arg[0]) {
00413   case INDEX:
00414         if (n > 1) {
00415                 v = execute(p->n_arg[3]);
00416                 t = getsval(v);
00417                 i = Index(s, t);
00418                 c_free(v);
00419         }
00420         else
00421                 i = 0;
00422         r = mktmp(NUM, NULL, (double) i);
00423         break;
00424   case LENGTH:
00425         i = (n > 0) ? jstrlen(s) : jstrlen(record);
00426         r = mktmp(NUM, NULL, (double) i);
00427         break;
00428   case SPLIT:
00429         r = Split(p);
00430         break;
00431   case SUBSTR:
00432         if (n > 1) {
00433                 v = execute(p->n_arg[3]);
00434                 m = (int) getfval(v) - 1;
00435                 c_free(v);
00436         }
00437         else
00438                 m = 0;
00439         if (n > 2) {
00440                 v = execute(p->n_arg[4]);
00441                 n = (int) getfval(v);
00442                 c_free(v);
00443         }
00444         else
00445                 n = jstrlen(s) - m;
00446         for (t = str; *s && m-- > 0; s++)
00447                 if (isKanji(*s))
00448                         s++;
00449         while (*s && n-- > 0) {
00450                 if (isKanji(*s))
00451                         *t++ = *s++;
00452                 *t++ = *s++;
00453         }
00454         *t = '\0';
00455         r = mktmp(STR, str, 0.0);
00456         break;
00457   case RMATCH:
00458         if (n > 1) {
00459                 v = execute(p->n_arg[3]);
00460                 pat = getpat(v);
00461                 match(pat, s);
00462                 c_free(v);
00463                 if (r_start) {  /* change only if match */
00464                         *RSTART = (double) r_start;
00465                         *RLENGTH = (double) r_length;
00466                 }
00467                 r = mktmp(NUM, NULL, (double) r_start);
00468         }
00469         else
00470                 error("missing regexpr in match(str, regexpr)");
00471         break;
00472   case CLOSE:
00473         r = Close(s);
00474         break;
00475   case SYSTEM:
00476         r = mktmp(NUM, NULL, system(s) == -1 ? 0.0 : 1.0);
00477         break;
00478   default:
00479         fprintf(stderr, "unknown string function");
00480         break;
00481   }
00482   c_free(u);
00483   return r;
00484 }
00485 
00486 static regexp *
00487 getpat(r) CELL *r;
00488 {
00489   regexp *pat, *mkpat();
00490 
00491   if (r->c_type & PAT)
00492         pat = (regexp *) r->c_sval;
00493   else {
00494         if (r_str && strcmp(r_str, r->c_sval) == 0)
00495                 pat = r_pat;
00496         else {
00497                 sfree(r_str); sfree(r_pat);
00498                 r_str = strsave(getsval(r));
00499                 pat = r_pat = mkpat(r_str);
00500         }
00501   }
00502   return pat;
00503 }
00504 
00505 static CELL *
00506 Subst(p) NODE *p;
00507 {
00508   CELL *u, *v, *w;
00509   char *s, *t, *r, str[BUFSIZ], *strcpy();
00510   int i, n;
00511 
00512   n = (int) p->n_arg[1];
00513   if (n > 1) {
00514         u = execute(p->n_arg[3]);       /* substitute string */
00515         s = getsval(u);
00516         v = execute(p->n_arg[2]);       /* expr */
00517         if (n > 2) {
00518                 w = execute(p->n_arg[4]);
00519                 t = getsval(w);
00520                 r = str;
00521         }
00522         else {
00523                 t = r = record;
00524                 w = NULL;
00525         }
00526         i = (int) p->n_arg[0] == RGSUB ? 0 : 1;
00527         if (v->c_type & (PAT|STR))
00528                 i = Sub(r, v->c_sval, (v->c_type & STR), s, t, i);
00529         else
00530                 error("[g]sub(PAT, .. ) must be /../ or string (%d)",
00531                         w->c_type);
00532         if (n > 2) {
00533                 if (w->c_type & REC) {
00534                         strcpy(record, str);
00535                         mkfld(record, *FS, field);
00536                 }
00537                 else
00538                         setsval(w, str);
00539         }
00540         else
00541                 mkfld(record, *FS, field);
00542         c_free(u);
00543         c_free(v);
00544         c_free(w);
00545   }
00546   else
00547         i = 0;
00548   return mktmp(NUM, NULL, (double) i);
00549 }
00550 
00551 static CELL *
00552 Cond(p) NODE *p;
00553 {
00554   CELL *u, *v;
00555   double x, y;
00556   int op, i, j;
00557   char *s;
00558   int save = pateval;
00559 
00560   op = (int) p->n_arg[0];
00561   u = execute(p->n_arg[1]);
00562   x = getfval(u);
00563 /*
00564 printf("Cond(%d)(%s)\n", u->c_type, u->c_sval);
00565 */
00566   if (op == AND || op == OR || op == NOT) {
00567         if (u->c_type & NUM)
00568                 i = (x != 0.0);
00569         else {
00570                 s = getsval(u);
00571                 i = (s != (char *)NULL) && (*s != '\0');
00572         }
00573   }
00574   if (op == AND && !i) {
00575         c_free(u);
00576         return &falsecell;
00577   }
00578   if (op == OR && i) {
00579         c_free(u);
00580         return &truecell;
00581   }
00582   if (op == NOT)
00583         i = i == 0 ? 1 : 0;
00584   else {
00585         if (op == MATCH || op == NOMATCH)
00586                 pateval = 0;
00587         v = execute(p->n_arg[2]);
00588         y = getfval(v);
00589         if (op == AND || op == OR || op == BINAND || op == BINOR) {
00590                 if (v->c_type & NUM)
00591                         j = (y != 0.0);
00592                 else {
00593                         s = getsval(v);
00594                         j = (s != (char *)NULL) && (*s != '\0');
00595                 }
00596                 switch (op) {
00597                 case AND:       i = i && j; break;
00598                 case OR:        i = i || j; break;
00599                 case BINAND:    i = i & j; break;
00600                 case BINOR:     i = i | j; break;
00601                 }
00602         }
00603         else if (op == MATCH || op == NOMATCH) {
00604                 char *s;
00605                 regexp *pat, *getpat();
00606 
00607                 s = getsval(u);
00608                 pat = getpat(v);
00609                 i = match(pat, s) == 0 ? 0 : 1;
00610                 if (op == NOMATCH)
00611                         i = i == 0 ? 1 : 0;
00612         }
00613         else {  /* relative operator */
00614 /*
00615 printf("Cond(%d)(%d)(%s)(%s)\n", u->c_type, v->c_type, u->c_sval, v->c_sval);
00616 */
00617                 if ((u->c_type & NUM) && (v->c_type & NUM))
00618                         i = x < y ? -1 : (x > y ? 1 : 0);
00619                 else
00620                         i = strcmp(getsval(u), getsval(v));
00621 /*
00622 printf("Cond(%d)(%d)(%g)(%g)(%d)\n", u->c_type, v->c_type, x, y, i);
00623 */
00624 
00625                 switch (op) {
00626                 case LT:        i = i < 0 ? 1 : 0; break;
00627                 case LE:        i = i <= 0 ? 1 : 0; break;
00628                 case EQ:        i = i == 0 ? 1 : 0; break;
00629                 case NE:        i = i != 0 ? 1 : 0; break;
00630                 case GT:        i = i > 0 ? 1 : 0; break;
00631                 case GE:        i = i >= 0 ? 1 : 0; break;
00632                 default:
00633                         fprintf(stderr, "unknown relative operator (%d)\n", op);
00634                         break;
00635                 }
00636         }
00637         c_free(v);
00638   }
00639   c_free(u);
00640   pateval = save;
00641   return mktmp(NUM, NULL, (double) i);
00642 }
00643 
00644 static CELL *
00645 If(p) NODE *p;
00646 {
00647   CELL *u;
00648   int i;
00649   char *s;
00650 
00651   u = execute(p->n_arg[0]);
00652   if (u->c_type & NUM)
00653         i = (getfval(u) != 0.0);
00654   else {
00655         s = getsval(u);
00656         i = (s != (char *)NULL) && (*s != '\0');
00657   }
00658   c_free(u);
00659   if (i)
00660         u = execute(p->n_arg[1]);
00661   else if (p->n_arg[2])
00662         u = execute(p->n_arg[2]);
00663   else
00664         u = &truecell;
00665   return u;
00666 }
00667 
00668 static CELL *
00669 While(p) NODE *p;
00670 {
00671   CELL *u;
00672   double x;
00673 
00674   for (;;) {
00675         u = execute(p->n_arg[0]);
00676         x = getfval(u);
00677         if (x == 0.0)
00678                 break;
00679         c_free(u);
00680         u = execute(p->n_arg[1]);
00681         switch (u->c_type) {
00682         case BRK:
00683                 goto rtn;
00684         case NXT: case EXT: case RTN:
00685                 return u;
00686         }
00687         c_free(u);
00688   }
00689 rtn:
00690   c_free(u);
00691   return &truecell;
00692 }
00693 
00694 static CELL *
00695 Do(p) NODE *p;
00696 {
00697   CELL *u;
00698   double x;
00699 
00700   for (;;) {
00701         u = execute(p->n_arg[0]);
00702         switch (u->c_type) {
00703         case BRK:
00704                 goto rtn;
00705         case NXT: case EXT: case RTN:
00706                 return u;
00707         }
00708         c_free(u);
00709         u = execute(p->n_arg[1]);
00710         if(getfval(u) == 0.0)
00711                 break;
00712         c_free(u);
00713   }
00714 rtn:
00715   c_free(u);
00716   return &truecell;
00717 }
00718 
00719 static CELL *
00720 For(p) NODE *p;
00721 {
00722   CELL *u;
00723   double x;
00724 
00725   if (p->n_arg[0] != NULL) {
00726         u = execute(p->n_arg[0]);
00727         c_free(u);
00728   }
00729   for (;;) {
00730         if (p->n_arg[1] != NULL) {
00731                 u = execute(p->n_arg[1]);
00732                 x = getfval(u);
00733                 c_free(u);
00734                 if (x == 0.0)
00735                         break;
00736         }
00737         u = execute(p->n_arg[3]);
00738         switch (u->c_type) {
00739         case BRK:
00740                 c_free(u);
00741                 goto rtn;
00742         case NXT: case EXT: case RTN:
00743                 return u;
00744         }
00745         if (p->n_arg[2] != NULL) {
00746                 u = execute(p->n_arg[2]);
00747                 c_free(u);
00748         }
00749   }
00750 rtn:
00751   return &truecell;
00752 }
00753 
00754 static CELL *
00755 Jump(p) NODE *p;
00756 {
00757   CELL *u;
00758   int i;
00759 
00760   switch ((int) p->n_arg[0]) {
00761   case BREAK:   u = &breakcell; break;
00762   case CONTIN:  u = &contcell;  break;
00763   case EXIT:
00764         if ((int) p->n_arg[1]) {
00765                 u = execute(p->n_arg[1]);
00766                 i = (int) getfval(u);
00767         }
00768         else
00769                 i = 0;
00770         closeall();
00771         exit(i);
00772   case RETURN:
00773         Return(p);
00774         u = &retcell;
00775         break;
00776   case NEXT:    u = &nextcell; break;
00777   }
00778   return u;
00779 }
00780 
00781 static
00782 Return(p) NODE *p;
00783 {
00784   CELL *u;
00785   int i;
00786   char *s, str[BUFSIZ];
00787 
00788   c_free(retval);
00789   if (p->n_arg[1] != NULL) {
00790         if (p->n_arg[2] == NULL) {
00791 /*
00792 if (0) {
00793 */
00794                 u = execute(p->n_arg[1]);
00795                 if (u->c_type == UDF)
00796                         retval = mktmp(STR, "", 0.0);
00797                 else
00798                         retval = mktmp(u->c_type, u->c_sval, u->c_fval);
00799                 c_free(u);
00800         }
00801         else {
00802                 for (i = 1; p->n_arg[i] != NULL; i++) {
00803                         if (i == 1)
00804                                 *str = '\0';
00805                         else
00806                                 strcat(str, *OFS);
00807                         u = execute(p->n_arg[i]);
00808                         s = getsval(u);
00809                         strcat(str, s);
00810                         c_free(u);
00811                 }
00812 /*
00813 printf("Ret(%s)(%d)\n", str, isnum(str));
00814 */
00815                 if (isnum(str))
00816                         retval = mktmp(STR|NUM, str, atof(str));
00817                 else
00818                         retval = mktmp(STR, str, 0.0);
00819         }
00820   }
00821   else
00822         retval = &truecell;
00823 }
00824 
00825 #define MAXFRAME        100
00826 CELL **frame[MAXFRAME];
00827 static int framep;
00828 
00829 static CELL *
00830 Arg(p) NODE *p;
00831 {
00832   CELL *u;
00833   int i;
00834 
00835   u = (CELL *)p->n_arg[0];
00836   return _Arg((int)u->c_fval);
00837 }
00838 
00839 CELL *
00840 _Arg(i)
00841 {
00842 /*
00843 printf("Arg(%d)\n", i);
00844 */
00845   return frame[framep - 1][i];
00846 }
00847 
00848 static CELL *
00849 Call(p) NODE *p;
00850 {
00851   CELL *u, *v, *r, **arg;
00852   NODE *q;
00853   int i, j, k, n;
00854   char *emalloc();
00855 
00856   if (framep >= MAXFRAME - 2)
00857         error("stack frame overflow", (char *)0);
00858   retval = &truecell;
00859   r = (CELL *) p->n_arg[0];
00860   if (r->c_type != FUN)
00861         synerr("called function is not declared", (char *)0);
00862   n = (int) r->c_fval;  /* # of params */
00863   if (n > 0) {
00864         arg = (CELL **) emalloc(sizeof(u) * n);
00865         for (i = 2, j = 0, k = (int) p->n_arg[1]; j < k; i++) {
00866                 u = execute(p->n_arg[i]);
00867 /*
00868 printf("pass, j(%d)typ(%d)\n", j, u->c_type);
00869 */
00870                 if (u->c_type & ARR)
00871                         v = u;  /* pass by reference */
00872                 else {  /* pass by value */
00873                         v = mkcell(UDF, u->c_sval, u->c_fval);
00874                         if (u->c_type != UDF) {
00875 #if 0
00876                                 v->c_type = u->c_type;
00877                                 if (v->c_type & (NUM|STR))
00878                                         v->c_type |= VAR;
00879                                 v->c_type &= ~TMP;      /* dont't free */
00880 #else
00881                                 v->c_type |= (u->c_type & (NUM|STR))|VAR;
00882                                 /*v->c_type &= ~TMP;*/
00883 #endif
00884                                 /* Don't free original */
00885                         }
00886 /*
00887 printf("pass1, j(%d)typ(%d)\n", j, v->c_type);
00888 */
00889                 }
00890                 arg[j++] = v;
00891         }
00892         for ( ; j < n; )        /* local var */
00893                 arg[j++] = mkcell(UDF, NULL, 0.0);
00894   }
00895   else
00896         arg = NULL;
00897 
00898   frame[framep] = arg;
00899   framep++;
00900 
00901   r = execute(r->c_sval);
00902   c_free(r);
00903   framep--;
00904   if (n > 0) {
00905         for (j = n - 1 ; j > k; j--) {  /* local var */
00906                 u = arg[j];
00907                 if (u->c_type & ARR)
00908                         a_free(u);
00909                 else
00910                         c_free(u);
00911         }
00912         for ( ; j >= 0; j--) {
00913                 u = arg[j];
00914                 if (!(u->c_type & ARR)) {
00915 /*                      c_free(u);*/
00916                         sfree(u->c_sval);
00917                         sfree(u);
00918                 }
00919                 else {
00920                         v = execute(p->n_arg[j + 2]);
00921                         if (v->c_type == UDF) { /* copy back */
00922 /*
00923 printf("copy_back_UDF(%d)(%d)\n", j, u->c_type);
00924 */
00925                                 v->c_type = u->c_type;
00926                                 sfree(v->c_sval);
00927                                 v->c_sval = u->c_sval;
00928                                 v->c_fval = u->c_fval;
00929                                 sfree(u);
00930                         }
00931                 }
00932         }
00933   }
00934   sfree(arg);
00935 /*  return retval;*/
00936   u = mktmp(retval->c_type, retval->c_sval, retval->c_fval);
00937   return u;
00938 }
00939 
00940 CELL *Nulproc()
00941 {
00942   return &truecell;
00943 }
00944 
00945 CELL *
00946 Usrfun(p) NODE *p;
00947 {
00948   CELL *u;
00949 
00950   u = execute(p);
00951   return u;
00952 }

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