home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / memacs / ue311c.arc / EVAL.C < prev    next >
C/C++ Source or Header  |  1991-03-24  |  33KB  |  1,309 lines

  1. /*    EVAL.C: Expresion evaluation functions for
  2.         MicroEMACS
  3.  
  4.     written 1986 by Daniel Lawrence             */
  5.  
  6. #include    <stdio.h>
  7. #include    "estruct.h"
  8. #include    "eproto.h"
  9. #include    "edef.h"
  10. #include    "elang.h"
  11. #include    "evar.h"
  12.  
  13. PASCAL NEAR varinit()    /* initialize the user variable list */
  14.  
  15. {
  16.     register int i;
  17.  
  18.     for (i=0; i < MAXVARS; i++)
  19.         uv[i].u_name[0] = 0;
  20. }
  21.  
  22. PASCAL NEAR varclean()    /* initialize the user variable list */
  23.  
  24. {
  25.     register int i;
  26.  
  27.     for (i=0; i < MAXVARS; i++)
  28.         if (uv[i].u_name[0] != 0)
  29.             free(uv[i].u_value);
  30. }
  31.  
  32. char *PASCAL NEAR gtfun(fname)    /* evaluate a function */
  33.  
  34. char *fname;        /* name of function to evaluate */
  35.  
  36. {
  37.     register int fnum;        /* index to function to eval */
  38.     register int arg;        /* value of some arguments */
  39.     char arg1[NSTRING];        /* value of first argument */
  40.     char arg2[NSTRING];        /* value of second argument */
  41.     char arg3[NSTRING];        /* value of third argument */
  42.     static char result[2 * NSTRING];    /* string result */
  43. #if    ENVFUNC
  44.     char *getenv();         /* get environment string */
  45. #endif
  46.  
  47.     /* look the function up in the function table */
  48.     fname[3] = 0;    /* only first 3 chars significant */
  49.     mklower(fname); /* and let it be upper or lower case */
  50.     fnum = binary(fname, funval, NFUNCS);
  51.  
  52.     /* return errorm on a bad reference */
  53.     if (fnum == -1)
  54.         return(errorm);
  55.  
  56.     /* if needed, retrieve the first argument */
  57.     if (funcs[fnum].f_type >= MONAMIC) {
  58.         if (macarg(arg1) != TRUE)
  59.             return(errorm);
  60.  
  61.         /* if needed, retrieve the second argument */
  62.         if (funcs[fnum].f_type >= DYNAMIC) {
  63.             if (macarg(arg2) != TRUE)
  64.                 return(errorm);
  65.  
  66.             /* if needed, retrieve the third argument */
  67.             if (funcs[fnum].f_type >= TRINAMIC)
  68.                 if (macarg(arg3) != TRUE)
  69.                     return(errorm);
  70.         }
  71.     }
  72.  
  73.  
  74.     /* and now evaluate it! */
  75.     switch (fnum) {
  76.         case UFADD:    return(int_asc(asc_int(arg1) + asc_int(arg2)));
  77.         case UFSUB:    return(int_asc(asc_int(arg1) - asc_int(arg2)));
  78.         case UFTIMES:    return(int_asc(asc_int(arg1) * asc_int(arg2)));
  79.         case UFDIV:    return(int_asc(asc_int(arg1) / asc_int(arg2)));
  80.         case UFMOD:    return(int_asc(asc_int(arg1) % asc_int(arg2)));
  81.         case UFNEG:    return(int_asc(-asc_int(arg1)));
  82.         case UFCAT:    strcpy(result, arg1);
  83.                 return(strcat(result, arg2));
  84.         case UFLEFT:    return(bytecopy(result, arg1, asc_int(arg2)));
  85.         case UFRIGHT:    arg = asc_int(arg2);
  86.                 if (arg > strlen(arg1))
  87.                     arg = strlen(arg1);
  88.                 return(strcpy(result,
  89.                     &arg1[strlen(arg1) - arg]));
  90.         case UFMID:    arg = asc_int(arg2);
  91.                 if (arg > strlen(arg1))
  92.                     arg = strlen(arg1);
  93.                 return(bytecopy(result, &arg1[arg-1],
  94.                     asc_int(arg3)));
  95.         case UFNOT:    return(ltos(stol(arg1) == FALSE));
  96.         case UFEQUAL:    return(ltos(asc_int(arg1) == asc_int(arg2)));
  97.         case UFLESS:    return(ltos(asc_int(arg1) < asc_int(arg2)));
  98.         case UFGREATER: return(ltos(asc_int(arg1) > asc_int(arg2)));
  99.         case UFSEQUAL:    return(ltos(strcmp(arg1, arg2) == 0));
  100.         case UFSLESS:    return(ltos(strcmp(arg1, arg2) < 0));
  101.         case UFSGREAT:    return(ltos(strcmp(arg1, arg2) > 0));
  102.         case UFIND:    return(strcpy(result, fixnull(getval(arg1))));
  103.         case UFAND:    return(ltos(stol(arg1) && stol(arg2)));
  104.         case UFOR:    return(ltos(stol(arg1) || stol(arg2)));
  105.         case UFLENGTH:    return(int_asc(strlen(arg1)));
  106.         case UFUPPER:    return(mkupper(arg1));
  107.         case UFLOWER:    return(mklower(arg1));
  108.         case UFTRUTH:    return(ltos(asc_int(arg1) == 42));
  109.         case UFASCII:    return(int_asc((int)arg1[0]));
  110.         case UFCHR:    result[0] = asc_int(arg1);
  111.                 result[1] = 0;
  112.                 return(result);
  113.         case UFGTCMD:    cmdstr(getcmd(), result);
  114.                 return(result);
  115.         case UFGTKEY:    result[0] = tgetc();
  116.                 result[1] = 0;
  117.                 return(result);
  118.         case UFRND:    return(int_asc((ernd() % absv(asc_int(arg1))) + 1));
  119.         case UFABS:    return(int_asc(absv(asc_int(arg1))));
  120.         case UFSINDEX:    return(int_asc(sindex(arg1, arg2)));
  121.         case UFENV:
  122. #if    ENVFUNC
  123.                 return(fixnull(getenv(arg1)));
  124. #else
  125.                 return("");
  126. #endif
  127.         case UFBIND:    return(transbind(arg1));
  128.         case UFEXIST:    return(ltos(fexist(arg1)));
  129.         case UFFIND:
  130.                 return(fixnull(flook(arg1, TRUE)));
  131.         case UFBAND:    return(int_asc(asc_int(arg1) & asc_int(arg2)));
  132.         case UFBOR:    return(int_asc(asc_int(arg1) | asc_int(arg2)));
  133.         case UFBXOR:    return(int_asc(asc_int(arg1) ^ asc_int(arg2)));
  134.         case UFBNOT:    return(int_asc(~asc_int(arg1)));
  135.         case UFXLATE:    return(xlat(arg1, arg2, arg3));
  136.         case UFTRIM:    return(trimstr(arg1));
  137.         case UFSLOWER:    return(setlower(arg1, arg2), "");
  138.         case UFSUPPER:    return(setupper(arg1, arg2), "");
  139.          case UFISNUM:    return(ltos(is_num(arg1)));
  140.     }
  141.  
  142.     meexit(-11);    /* never should get here */
  143. }
  144.  
  145. char *PASCAL NEAR gtusr(vname)    /* look up a user var's value */
  146.  
  147. char *vname;        /* name of user variable to fetch */
  148.  
  149. {
  150.     register int vnum;    /* ordinal number of user var */
  151.     register char *vptr;    /* temp pointer to function value */
  152.  
  153.     /* limit comparisons to significant length */
  154.     if (strlen(vname) >= NVSIZE)    /* "%" counts, but is not passed */
  155.         vname[NVSIZE-1] = '\0';
  156.  
  157.     /* scan the list looking for the user var name */
  158.     for (vnum = 0; vnum < MAXVARS; vnum++) {
  159.         if (uv[vnum].u_name[0] == 0)
  160.             return(errorm);
  161.         if (strcmp(vname, uv[vnum].u_name) == 0) {
  162.             vptr = uv[vnum].u_value;
  163.             if (vptr)
  164.                 return(vptr);
  165.             else
  166.                 return(errorm);
  167.         }
  168.     }
  169.  
  170.     /* return errorm if we run off the end */
  171.     return(errorm);
  172. }
  173.  
  174. char *PASCAL NEAR funval(i)
  175.  
  176. int i;
  177.  
  178. {
  179.     return(funcs[i].f_name);
  180. }
  181.  
  182. char *PASCAL NEAR envval(i)
  183.  
  184. int i;
  185.  
  186. {
  187.     return(envars[i]);
  188. }
  189.  
  190. PASCAL NEAR binary(key, tval, tlength)
  191.  
  192. char *key;        /* key string to look for */
  193. char *(PASCAL NEAR *tval)();    /* ptr to function to fetch table value with */
  194. int tlength;        /* length of table to search */
  195.  
  196. {
  197.     int l, u;    /* lower and upper limits of binary search */
  198.     int i;        /* current search index */
  199.     int cresult;    /* result of comparison */
  200.  
  201.     /* set current search limit as entire list */
  202.     l = 0;
  203.     u = tlength - 1;
  204.  
  205.     /* get the midpoint! */
  206.     while (u >= l) {
  207.         i = (l + u) >> 1;
  208.  
  209.         /* do the comparison */
  210.         cresult = strcmp(key, (*tval)(i));
  211.         if (cresult == 0)
  212.             return(i);
  213.         if (cresult < 0)
  214.             u = i - 1;
  215.         else
  216.             l = i + 1;
  217.     }
  218.     return(-1);
  219. }
  220.  
  221. char *PASCAL NEAR gtenv(vname)
  222.  
  223. char *vname;        /* name of environment variable to retrieve */
  224.  
  225. {
  226.     register int vnum;    /* ordinal number of var refrenced */
  227.     static char result[2 * NSTRING];    /* string result */
  228.  
  229.     /* scan the list, looking for the referenced name */
  230.     vnum = binary(vname, envval, NEVARS);
  231.  
  232.     /* return errorm on a bad reference */
  233.     if (vnum == -1)
  234.         return(errorm);
  235.  
  236.     /* otherwise, fetch the appropriate value */
  237.     switch (vnum) {
  238.         case EVFILLCOL: return(int_asc(fillcol));
  239.         case EVPAGELEN: return(int_asc(term.t_nrow + 1));
  240.         case EVCURCOL:    return(int_asc(getccol(FALSE)));
  241.         case EVCURLINE: return(int_asc(getlinenum(curbp, curwp->w_dotp)));
  242.         case EVRAM:    return(int_asc((int)(envram / 1024l)));
  243.         case EVFLICKER: return(ltos(flickcode));
  244.         case EVCURWIDTH:return(int_asc(term.t_ncol));
  245.         case EVCBFLAGS: return(int_asc(curbp->b_flag));
  246.         case EVCBUFNAME:return(curbp->b_bname);
  247.         case EVCFNAME:    return(curbp->b_fname);
  248.         case EVSRES:    return(sres);
  249.         case EVDEBUG:    return(ltos(macbug));
  250.         case EVSTATUS:    return(ltos(cmdstatus));
  251.         case EVPALETTE: return(palstr);
  252.         case EVASAVE:    return(int_asc(gasave));
  253.         case EVACOUNT:    return(int_asc(gacount));
  254.         case EVLASTKEY: return(int_asc(lastkey));
  255.         case EVCURCHAR:
  256.             return(curwp->w_dotp->l_used ==
  257.                     curwp->w_doto ? int_asc('\r') :
  258.                 int_asc(lgetc(curwp->w_dotp, curwp->w_doto)));
  259.         case EVDISCMD:    return(ltos(discmd));
  260.         case EVVERSION: return(VERSION);
  261.         case EVPROGNAME:return(PROGNAME);
  262.         case EVLANG:    return(LANGUAGE);
  263.         case EVSEED:    return(int_asc(seed));
  264.         case EVDISINP:    return(ltos(disinp));
  265.         case EVWLINE:    return(int_asc(curwp->w_ntrows));
  266.         case EVCWLINE:    return(int_asc(getwpos()));
  267.         case EVTARGET:    saveflag = lastflag;
  268.                 return(int_asc(curgoal));
  269.         case EVSEARCH:    return(pat);
  270.         case EVTIME:    return(timeset());
  271.         case EVREPLACE: return(rpat);
  272.         case EVMATCH:    return(fixnull(patmatch));
  273.         case EVKILL:    return(getkill());
  274.         case EVREGION:    return(getreg());
  275.         case EVCMODE:    return(int_asc(curbp->b_mode));
  276.         case EVGMODE:    return(int_asc(gmode));
  277.         case EVTPAUSE:    return(int_asc(term.t_pause));
  278.         case EVPENDING:
  279. #if    TYPEAH
  280.                 return(ltos(typahead()));
  281. #else
  282.                 return(falsem);
  283. #endif
  284.         case EVLWIDTH:    return(int_asc(llength(curwp->w_dotp)));
  285.         case EVLINE:    return(getctext());
  286.         case EVGFLAGS:    return(int_asc(gflags));
  287.         case EVRVAL:    return(int_asc(rval));
  288.         case EVREADHK:    return(fixnull(getfname(&readhook)));
  289.         case EVWRAPHK:    return(fixnull(getfname(&wraphook)));
  290.         case EVCMDHK:    return(fixnull(getfname(&cmdhook)));
  291.         case EVXPOS:    return(int_asc(xpos));
  292.         case EVYPOS:    return(int_asc(ypos));
  293.         case EVSTERM:    cmdstr(sterm, result);
  294.                 return(result);
  295.         case EVMODEFLAG:return(ltos(modeflag));
  296.         case EVSSCROLL: return(ltos(sscroll));
  297.         case EVLASTMESG:return(lastmesg);
  298.         case EVHARDTAB: return(int_asc(tabsize));
  299.         case EVSOFTTAB: return(int_asc(stabsize));
  300.         case EVSSAVE:    return(ltos(ssave));
  301.         case EVFCOL:    return(int_asc(curwp->w_fcol));
  302.         case EVHSCROLL: return(ltos(hscroll));
  303.         case EVHJUMP:    return(int_asc(hjump));
  304.         case EVBUFHOOK: return(fixnull(getfname(&bufhook)));
  305.         case EVEXBHOOK: return(fixnull(getfname(&exbhook)));
  306.         case EVWRITEHK: return(fixnull(getfname(&writehook)));
  307.         case EVDIAGFLAG:return(ltos(diagflag));
  308.         case EVMSFLAG:    return(ltos(mouseflag));
  309.         case EVOCRYPT:    return(ltos(oldcrypt));
  310.         case EVSEARCHPNT:    return(int_asc(searchtype));
  311.         case EVDISPHIGH:return(ltos(disphigh));
  312.         case EVLTERM:    return(lterm);
  313.         case EVWCHARS:    return(getwlist(result));
  314.         case EVPOPFLAG: return(ltos(popflag));
  315.         case EVYANKPNT:    return(ltos(yanktype));
  316.         case EVSCRNAME:    return(cur_screen->s_screen_name);
  317.         case EVSCRNUM:    return(int_asc(scr_num));
  318.         case EVCURWIND: return(int_asc(getcwnum()));
  319.         case EVNUMWIND: return(int_asc(gettwnum()));
  320.     }
  321.     meexit(-12);    /* again, we should never get here */
  322. }
  323.  
  324. char *PASCAL NEAR fixnull(s)    /* Don't return NULL pointers! */
  325.  
  326. char *s;
  327.  
  328. {
  329.     if (s == NULL)
  330.         return("");
  331.     else
  332.         return(s);
  333. }
  334.  
  335. /* return some of the contents of the kill buffer */
  336.  
  337. char *PASCAL NEAR getkill()
  338.  
  339. {
  340.     register int size;    /* max number of chars to return */
  341.     static char value[NSTRING];    /* temp buffer for value */
  342.  
  343.     if (kbufh == NULL)
  344.         /* no kill buffer....just a null string */
  345.         value[0] = 0;
  346.     else {
  347.         /* copy in the contents... */
  348.         if (kused < NSTRING)
  349.             size = kused;
  350.         else
  351.             size = NSTRING - 1;
  352.         bytecopy(value, kbufh->d_chunk, size);
  353.         value[NSTRING - 1] = 0;
  354.     }
  355.  
  356.     /* and return the constructed value */
  357.     return(value);
  358. }
  359.  
  360. char *PASCAL NEAR trimstr(s)    /* trim whitespace off the end of a string */
  361.  
  362. char *s;    /* string to trim */
  363.  
  364. {
  365.     char *sp;    /* backward index */
  366.  
  367.     sp = s + strlen(s) - 1;
  368.     while ((sp >= s) && (*sp == ' ' || *sp == '\t'))
  369.         --sp;
  370.     *(sp+1) = 0;
  371.     return(s);
  372. }
  373.  
  374. int PASCAL NEAR setvar(f, n)        /* set a variable */
  375.  
  376. int f;        /* default flag */
  377. int n;        /* numeric arg (can overide prompted value) */
  378.  
  379. {
  380.     register int status;    /* status return */
  381.     VDESC vd;        /* variable num/type */
  382.     char var[NVSIZE+1];    /* name of variable to fetch */
  383.     char value[NSTRING];    /* value to set variable to */
  384.  
  385.     /* first get the variable to set.. */
  386.     if (clexec == FALSE) {
  387.         status = mlreply(TEXT51, &var[0], NVSIZE+1);
  388. /*                 "Variable to set: " */
  389.         if (status != TRUE)
  390.             return(status);
  391.     } else {    /* macro line argument */
  392.         /* grab token and skip it */
  393.         execstr = token(execstr, var, NVSIZE + 1);
  394.     }
  395.  
  396.     /* check the legality and find the var */
  397.     findvar(var, &vd, NVSIZE + 1);
  398.         
  399.     /* if its not legal....bitch */
  400.     if (vd.v_type == -1) {
  401.         mlwrite(TEXT52, var);
  402. /*            "%%No such variable as '%s'" */
  403.         return(FALSE);
  404.     }
  405.  
  406.     /* get the value for that variable */
  407.     if (f == TRUE)
  408.         strcpy(value, int_asc(n));
  409.     else {
  410.         status = mlreply(TEXT53, &value[0], NSTRING);
  411. /*                 "Value: " */
  412.         if (status != TRUE)
  413.             return(status);
  414.     }
  415.  
  416.     /* and set the appropriate value */
  417.     status = svar(&vd, value);
  418.  
  419. #if    DEBUGM
  420.     /* if $debug == TRUE, every assignment will echo a statment to
  421.        that effect here. */
  422.         
  423.     if (macbug && (strcmp(var, "%track") != 0)) {
  424.         strcpy(outline, "(((");
  425.  
  426.         strcat(outline, var);
  427.         strcat(outline, " <- ");
  428.  
  429.         /* and lastly the value we tried to assign */
  430.         strcat(outline, value);
  431.         strcat(outline, ")))");
  432.  
  433.         /* expand '%' to "%%" so mlwrite wont bitch */
  434.         makelit(outline);
  435.  
  436.         /* write out the debug line */
  437.         mlforce(outline);
  438.         update(TRUE);
  439.  
  440.         /* and get the keystroke to hold the output */
  441.         if (getkey() == abortc) {
  442.             mlforce(TEXT54);
  443. /*                "[Macro aborted]" */
  444.             status = FALSE;
  445.         }
  446.     }
  447. #endif
  448.  
  449.     /* and return it */
  450.     return(status);
  451. }
  452.  
  453. PASCAL NEAR findvar(var, vd, size)    /* find a variables type and name */
  454.  
  455. char *var;    /* name of var to get */
  456. VDESC *vd;    /* structure to hold type and ptr */
  457. int size;    /* size of var array */
  458.  
  459. {
  460.     register int vnum;    /* subscript in varable arrays */
  461.     register int vtype;    /* type to return */
  462.  
  463. fvar:    vtype = -1;
  464.     switch (var[0]) {
  465.  
  466.         case '$': /* check for legal enviromnent var */
  467.             for (vnum = 0; vnum < NEVARS; vnum++)
  468.                 if (strcmp(&var[1], envars[vnum]) == 0) {
  469.                     vtype = TKENV;
  470.                     break;
  471.                 }
  472.             break;
  473.  
  474.         case '%': /* check for existing legal user variable */
  475.             for (vnum = 0; vnum < MAXVARS; vnum++)
  476.                 if (strcmp(&var[1], uv[vnum].u_name) == 0) {
  477.                     vtype = TKVAR;
  478.                     break;
  479.                 }
  480.             if (vnum < MAXVARS)
  481.                 break;
  482.  
  483.             /* create a new one??? */
  484.             for (vnum = 0; vnum < MAXVARS; vnum++)
  485.                 if (uv[vnum].u_name[0] == 0) {
  486.                     vtype = TKVAR;
  487.                     strcpy(uv[vnum].u_name, &var[1]);
  488.                     uv[vnum].u_value = NULL;
  489.                     break;
  490.                 }
  491.             break;
  492.  
  493.         case '&':    /* indirect operator? */
  494.             var[4] = 0;
  495.             if (strcmp(&var[1], "ind") == 0) {
  496.                 /* grab token, and eval it */
  497.                 execstr = token(execstr, var, size);
  498.                 strcpy(var, fixnull(getval(var)));
  499.                 goto fvar;
  500.             }
  501.     }
  502.  
  503.     /* return the results */
  504.     vd->v_num = vnum;
  505.     vd->v_type = vtype;
  506.     return;
  507. }
  508.  
  509. int PASCAL NEAR svar(var, value)    /* set a variable */
  510.  
  511. VDESC *var;    /* variable to set */
  512. char *value;    /* value to set to */
  513.  
  514. {
  515.     register int vnum;    /* ordinal number of var refrenced */
  516.     register int vtype;    /* type of variable to set */
  517.     register int status;    /* status return */
  518.     register int c;     /* translated character */
  519.     register char *sp;    /* scratch string pointer */
  520.  
  521.     /* simplify the vd structure (we are gonna look at it a lot) */
  522.     vnum = var->v_num;
  523.     vtype = var->v_type;
  524.  
  525.     /* and set the appropriate value */
  526.     status = TRUE;
  527.     switch (vtype) {
  528.     case TKVAR: /* set a user variable */
  529.         if (uv[vnum].u_value != NULL)
  530.             free(uv[vnum].u_value);
  531.         sp = malloc(strlen(value) + 1);
  532.         if (sp == NULL)
  533.             return(FALSE);
  534.         strcpy(sp, value);
  535.         uv[vnum].u_value = sp;
  536.         break;
  537.  
  538.     case TKENV: /* set an environment variable */
  539.         status = TRUE;    /* by default */
  540.         switch (vnum) {
  541.         case EVFILLCOL: fillcol = asc_int(value);
  542.                 break;
  543.         case EVPAGELEN: status = newsize(TRUE, asc_int(value));
  544.                 break;
  545.         case EVCURCOL:    status = setccol(asc_int(value));
  546.                 break;
  547.         case EVCURLINE: status = gotoline(TRUE, asc_int(value));
  548.                 break;
  549.         case EVRAM:    break;
  550.         case EVFLICKER: flickcode = stol(value);
  551.                 break;
  552.         case EVCURWIDTH:status = newwidth(TRUE, asc_int(value));
  553.                 break;
  554.         case EVCBFLAGS: curbp->b_flag = (curbp->b_flag & ~(BFCHG|BFINVS))
  555.                     | (asc_int(value) & (BFCHG&BFINVS));
  556.                 lchange(WFMODE);
  557.                 break;
  558.         case EVCBUFNAME:strcpy(curbp->b_bname, value);
  559.                 curwp->w_flag |= WFMODE;
  560.                 break;
  561.         case EVCFNAME:    strcpy(curbp->b_fname, value);
  562.                 curwp->w_flag |= WFMODE;
  563.                 break;
  564.         case EVSRES:    status = TTrez(value);
  565.                 break;
  566.         case EVDEBUG:    macbug = stol(value);
  567.                 break;
  568.         case EVSTATUS:    cmdstatus = stol(value);
  569.                 break;
  570.         case EVPALETTE: bytecopy(palstr, value, 48);
  571.                 spal(palstr);
  572.                 break;
  573.         case EVASAVE:    gasave = asc_int(value);
  574.                 break;
  575.         case EVACOUNT:    gacount = asc_int(value);
  576.                 break;
  577.         case EVLASTKEY: lastkey = asc_int(value);
  578.                 break;
  579.         case EVCURCHAR: ldelete(1L, FALSE);    /* delete 1 char */
  580.                 c = asc_int(value);
  581.                 if (c == '\r')
  582.                     lnewline();
  583.                 else
  584.                     linsert(1, c);
  585.                 backchar(FALSE, 1);
  586.                 break;
  587.         case EVDISCMD:    discmd = stol(value);
  588.                 break;
  589.         case EVVERSION: break;
  590.         case EVPROGNAME:break;
  591.         case EVLANG:    break;
  592.         case EVSEED:    seed = asc_int(value);
  593.                 break;
  594.         case EVDISINP:    disinp = stol(value);
  595.                 break;
  596.         case EVWLINE:    status = resize(TRUE, asc_int(value));
  597.                 break;
  598.         case EVCWLINE:    status = forwline(TRUE,
  599.                         asc_int(value) - getwpos());
  600.                 break;
  601.         case EVTARGET:    curgoal = asc_int(value);
  602.                 thisflag = saveflag;
  603.                 break;
  604.         case EVSEARCH:    strcpy(pat, value);
  605.                 setjtable(); /* Set up fast search arrays  */
  606. #if    MAGIC
  607.                 mcclear();
  608. #endif
  609.                 break;
  610.         case EVTIME:    break;
  611.         case EVREPLACE: strcpy(rpat, value);
  612. #if    MAGIC
  613.                 rmcclear();
  614. #endif 
  615.                 break;
  616.         case EVMATCH:    break;
  617.         case EVKILL:    break;
  618.         case EVREGION:    break;
  619.         case EVCMODE:    curbp->b_mode = asc_int(value);
  620.                 curwp->w_flag |= WFMODE;
  621.                 break;
  622.         case EVGMODE:    gmode = asc_int(value);
  623.                 break;
  624.         case EVTPAUSE:    term.t_pause = asc_int(value);
  625.                 break;
  626.         case EVPENDING: break;
  627.         case EVLWIDTH:    break;
  628.         case EVLINE:    putctext(value);
  629.                 break;
  630.         case EVGFLAGS:    gflags = asc_int(value);
  631.                 break;
  632.         case EVRVAL:    break;
  633.         case EVREADHK:    setkey(&readhook, BINDFNC, value);
  634.                 break;
  635.         case EVWRAPHK:    setkey(&wraphook, BINDFNC, value);
  636.                 break;
  637.         case EVCMDHK:    setkey(&cmdhook, BINDFNC, value);
  638.                 break;
  639.         case EVXPOS:    xpos = asc_int(value);
  640.                 break;
  641.         case EVYPOS:    ypos = asc_int(value);
  642.                 break;
  643.         case EVSTERM:    sterm = stock(value);
  644.                 break;
  645.         case EVMODEFLAG:modeflag = stol(value);
  646.                 upwind();
  647.                 break;
  648.         case EVSSCROLL: sscroll = stol(value);
  649.                 break;
  650.         case EVLASTMESG:strcpy(lastmesg, value);
  651.                 break;
  652.         case EVHARDTAB: tabsize = asc_int(value);
  653.                 upwind();
  654.                 break;
  655.         case EVSOFTTAB: stabsize = asc_int(value);
  656.                 upwind();
  657.                 break;
  658.         case EVSSAVE:    ssave = stol(value);
  659.                 break;
  660.         case EVFCOL:    curwp->w_fcol = asc_int(value);
  661.                 if (curwp->w_fcol < 0)
  662.                     curwp->w_fcol = 0;
  663.                 curwp->w_flag |= WFHARD | WFMODE;
  664.                 break;
  665.         case EVHSCROLL: hscroll = stol(value);
  666.                 lbound = 0;
  667.                 break;
  668.         case EVHJUMP:    hjump = asc_int(value);
  669.                 if (hjump < 1)
  670.                     hjump = 1;
  671.                 if (hjump > term.t_ncol - 1)
  672.                     hjump = term.t_ncol - 1;
  673.                 break;
  674.         case EVBUFHOOK: setkey(&bufhook, BINDFNC, value);
  675.                 break;
  676.         case EVEXBHOOK: setkey(&exbhook, BINDFNC, value);
  677.                 break;
  678.         case EVWRITEHK: setkey(&writehook, BINDFNC, value);
  679.                 break;
  680.         case EVDIAGFLAG:diagflag = stol(value);
  681.                 break;
  682.         case EVMSFLAG:    mouseflag = stol(value);
  683.                 break;
  684.         case EVOCRYPT:    oldcrypt = stol(value);
  685.                 break;
  686.         case EVSEARCHPNT:    searchtype = asc_int(value);
  687.                 if (searchtype < SRNORM  || searchtype > SREND)
  688.                     searchtype = SRNORM;
  689.                 break;
  690.         case EVDISPHIGH:
  691.                 c = disphigh;
  692.                 disphigh = stol(value);
  693.                 if (c != disphigh)
  694.                     upwind();
  695.  
  696.                 break;
  697.         case EVLTERM:    bytecopy(lterm, value, NSTRING);
  698.                 break;
  699.         case EVWCHARS:    setwlist(value);
  700.                 break;
  701.         case EVPOPFLAG: popflag = stol(value);
  702.                 break;
  703.         case EVYANKPNT:    yanktype = stol(value);
  704.                 break;
  705.         case EVSCRNAME:    select_screen(lookup_screen(value));
  706.                 break;
  707.         case EVSCRNUM:    select_screen(index_screen(asc_int(value)));
  708.                 break;
  709.         case EVCURWIND:    nextwind(TRUE, asc_int(value));
  710.                 break;
  711.         case EVNUMWIND:    break;
  712.         }
  713.         break;
  714.     }
  715.     return(status);
  716. }
  717.  
  718. /*    asc_int:    ascii string to integer......This is too
  719.         inconsistant to use the system's    */
  720.  
  721. int PASCAL NEAR asc_int(st)
  722.  
  723. char *st;
  724.  
  725. {
  726.     int result;    /* resulting number */
  727.     int sign;    /* sign of resulting number */
  728.     char c;     /* current char being examined */
  729.  
  730.     result = 0;
  731.     sign = 1;
  732.  
  733.     /* skip preceding whitespace */
  734.     while (*st == ' ' || *st == '\t')
  735.         ++st;
  736.  
  737.     /* check for sign */
  738.     if (*st == '-') {
  739.         sign = -1;
  740.         ++st;
  741.     }
  742.     if (*st == '+')
  743.         ++st;
  744.  
  745.     /* scan digits, build value */
  746.     while ((c = *st++))
  747.         if (c >= '0' && c <= '9')
  748.             result = result * 10 + c - '0';
  749.         else
  750.             break;
  751.  
  752.     return(result * sign);
  753. }
  754.  
  755. /*    int_asc:    integer to ascii string.......... This is too
  756.             inconsistant to use the system's    */
  757.  
  758. char *PASCAL NEAR int_asc(i)
  759.  
  760. int i;    /* integer to translate to a string */
  761.  
  762. {
  763.     register int digit;        /* current digit being used */
  764.     register char *sp;        /* pointer into result */
  765.     register int sign;        /* sign of resulting number */
  766.     static char result[INTWIDTH+1]; /* resulting string */
  767.  
  768.     /* record the sign...*/
  769.     sign = 1;
  770.     if (i < 0) {
  771.         sign = -1;
  772.         i = -i;
  773.     }
  774.  
  775.     /* and build the string (backwards!) */
  776.     sp = result + INTWIDTH;
  777.     *sp = 0;
  778.     do {
  779.         digit = i % 10;
  780.         *(--sp) = '0' + digit;    /* and install the new digit */
  781.         i = i / 10;
  782.     } while (i);
  783.  
  784.     /* and fix the sign */
  785.     if (sign == -1) {
  786.         *(--sp) = '-';    /* and install the minus sign */
  787.     }
  788.  
  789.     return(sp);
  790. }
  791.  
  792. int PASCAL NEAR gettyp(token)    /* find the type of a passed token */
  793.  
  794. char *token;    /* token to analyze */
  795.  
  796. {
  797.     register char c;    /* first char in token */
  798.  
  799.     /* grab the first char (this is all we need) */
  800.     c = *token;
  801.  
  802.     /* no blanks!!! */
  803.     if (c == 0)
  804.         return(TKNUL);
  805.  
  806.     /* a numeric literal? */
  807.     if (c >= '0' && c <= '9')
  808.         return(TKLIT);
  809.  
  810.     switch (c) {
  811.         case '"':    return(TKSTR);
  812.  
  813.         case '!':    return(TKDIR);
  814.         case '@':    return(TKARG);
  815.         case '#':    return(TKBUF);
  816.         case '$':    return(TKENV);
  817.         case '%':    return(TKVAR);
  818.         case '&':    return(TKFUN);
  819.         case '*':    return(TKLBL);
  820.  
  821.         default:    return(TKCMD);
  822.     }
  823. }
  824.  
  825. char *PASCAL NEAR getval(token) /* find the value of a token */
  826.  
  827. char *token;        /* token to evaluate */
  828.  
  829. {
  830.     register int status;    /* error return */
  831.     register BUFFER *bp;    /* temp buffer pointer */
  832.     register int blen;    /* length of buffer argument */
  833.     register int distmp;    /* temporary discmd flag */
  834.     static char buf[NSTRING];/* string buffer for some returns */
  835.  
  836.     switch (gettyp(token)) {
  837.         case TKNUL:    return("");
  838.  
  839.         case TKARG:    /* interactive argument */
  840.                 strcpy(token, fixnull(getval(&token[1])));
  841.                 distmp = discmd;    /* echo it always! */
  842.                 discmd = TRUE;
  843.                 status = getstring(token,
  844.                        buf, NSTRING, ctoec('\r'));
  845.                 discmd = distmp;
  846.                 if (status == ABORT)
  847.                     return(NULL);
  848.                 return(buf);
  849.  
  850.         case TKBUF:    /* buffer contents fetch */
  851.  
  852.                 /* grab the right buffer */
  853.                 strcpy(token, fixnull(getval(&token[1])));
  854.                 bp = bfind(token, FALSE, 0);
  855.                 if (bp == NULL)
  856.                     return(NULL);
  857.             
  858.                 /* if the buffer is displayed, get the window
  859.                    vars instead of the buffer vars */
  860.                 if (bp->b_nwnd > 0) {
  861.                     curbp->b_dotp = curwp->w_dotp;
  862.                     curbp->b_doto = curwp->w_doto;
  863.                 }
  864.  
  865.                 /* make sure we are not at the end */
  866.                 if (bp->b_linep == bp->b_dotp)
  867.                     return(NULL);
  868.             
  869.                 /* grab the line as an argument */
  870.                 blen = bp->b_dotp->l_used - bp->b_doto;
  871.                 if (blen > NSTRING)
  872.                     blen = NSTRING;
  873.                 bytecopy(buf, bp->b_dotp->l_text + bp->b_doto,
  874.                     blen);
  875.                 buf[blen] = 0;
  876.             
  877.                 /* and step the buffer's line ptr ahead a line */
  878.                 bp->b_dotp = bp->b_dotp->l_fp;
  879.                 bp->b_doto = 0;
  880.  
  881.                 /* if displayed buffer, reset window ptr vars*/
  882.                 if (bp->b_nwnd > 0) {
  883.                     curwp->w_dotp = curbp->b_dotp;
  884.                     curwp->w_doto = 0;
  885.                     curwp->w_flag |= WFMOVE;
  886.                 }
  887.  
  888.                 /* and return the spoils */
  889.                 return(buf);            
  890.  
  891.         case TKVAR:    return(gtusr(token+1));
  892.         case TKENV:    return(gtenv(token+1));
  893.         case TKFUN:    return(gtfun(token+1));
  894.         case TKDIR:    return(NULL);
  895.         case TKLBL:    return(NULL);
  896.         case TKLIT:    return(token);
  897.         case TKSTR:    return(token+1);
  898.         case TKCMD:    return(token);
  899.     }
  900. }
  901.  
  902. int PASCAL NEAR stol(val)    /* convert a string to a numeric logical */
  903.  
  904. char *val;    /* value to check for stol */
  905.  
  906. {
  907.     /* check for logical values */
  908.     if (val[0] == 'F')
  909.         return(FALSE);
  910.     if (val[0] == 'T')
  911.         return(TRUE);
  912.  
  913.     /* check for numeric truth (!= 0) */
  914.     return((asc_int(val) != 0));
  915. }
  916.  
  917. char *PASCAL NEAR ltos(val)    /* numeric logical to string logical */
  918.  
  919. int val;    /* value to translate */
  920.  
  921. {
  922.     if (val)
  923.         return(truem);
  924.     else
  925.         return(falsem);
  926. }
  927.  
  928. char *PASCAL NEAR mkupper(str)    /* make a string upper case */
  929.  
  930. char *str;        /* string to upper case */
  931.  
  932. {
  933.     char *sp;
  934.  
  935.     sp = str;
  936.     while (*sp)
  937.         uppercase(sp++);
  938.     return(str);
  939. }
  940.  
  941. char *PASCAL NEAR mklower(str)    /* make a string lower case */
  942.  
  943. char *str;        /* string to lower case */
  944.  
  945. {
  946.     char *sp;
  947.  
  948.     sp = str;
  949.     while (*sp)
  950.         lowercase(sp++);
  951.     return(str);
  952. }
  953.  
  954. int PASCAL NEAR absv(x) /* take the absolute value of an integer */
  955.  
  956. int x;
  957.  
  958. {
  959.     return(x < 0 ? -x : x);
  960. }
  961.  
  962. int PASCAL NEAR ernd()    /* returns a random integer */
  963.  
  964. {
  965.     seed = absv(seed * 1721 + 10007);
  966.     return(seed);
  967. }
  968.  
  969. int PASCAL NEAR sindex(source, pattern) /* find pattern within source */
  970.  
  971. char *source;    /* source string to search */
  972. char *pattern;    /* string to look for */
  973.  
  974. {
  975.     char *sp;    /* ptr to current position to scan */
  976.     char *csp;    /* ptr to source string during comparison */
  977.     char *cp;    /* ptr to place to check for equality */
  978.  
  979.     /* scanning through the source string */
  980.     sp = source;
  981.     while (*sp) {
  982.         /* scan through the pattern */
  983.         cp = pattern;
  984.         csp = sp;
  985.         while (*cp) {
  986.             if (!eq(*cp, *csp))
  987.                 break;
  988.             ++cp;
  989.             ++csp;
  990.         }
  991.  
  992.         /* was it a match? */
  993.         if (*cp == 0)
  994.             return((int)(sp - source) + 1);
  995.         ++sp;
  996.     }
  997.  
  998.     /* no match at all.. */
  999.     return(0);
  1000. }
  1001.  
  1002. /*    Filter a string through a translation table    */
  1003.  
  1004. char *PASCAL NEAR xlat(source, lookup, trans)
  1005.  
  1006. char *source;    /* string to filter */
  1007. char *lookup;    /* characters to translate */
  1008. char *trans;    /* resulting translated characters */
  1009.  
  1010. {
  1011.     register char *sp;    /* pointer into source table */
  1012.     register char *lp;    /* pointer into lookup table */
  1013.     register char *rp;    /* pointer into result */
  1014.     static char result[NSTRING];    /* temporary result */
  1015.  
  1016.     /* scan source string */
  1017.     sp = source;
  1018.     rp = result;
  1019.     while (*sp) {
  1020.         /* scan lookup table for a match */
  1021.         lp = lookup;
  1022.         while (*lp) {
  1023.             if (*sp == *lp) {
  1024.                 *rp++ = trans[lp - lookup];
  1025.                 goto xnext;
  1026.             }
  1027.             ++lp;
  1028.         }
  1029.  
  1030.         /* no match, copy in the source char untranslated */
  1031.         *rp++ = *sp;
  1032.  
  1033. xnext:        ++sp;
  1034.     }
  1035.  
  1036.     /* terminate and return the result */
  1037.     *rp = 0;
  1038.     return(result);
  1039. }
  1040.  
  1041. /*    setwlist:    Set an alternative list of character to be
  1042.             considered "in a word */
  1043.  
  1044. PASCAL NEAR setwlist(wclist)
  1045.  
  1046. char *wclist;    /* list of characters to consider "in a word" */
  1047.  
  1048. {
  1049.     register int index;
  1050.  
  1051.     /* if we are turning this facility off, just flag so */
  1052.     if (wclist == NULL || *wclist == 0) {
  1053.         wlflag = FALSE;
  1054.         return;
  1055.     }
  1056.  
  1057.     /* first clear the table */
  1058.     for (index = 0; index < 256; index++)
  1059.         wordlist[index] = FALSE;
  1060.  
  1061.     /* and for each character in the new value, set that element
  1062.        of the word character list */
  1063.     while (*wclist)
  1064.         wordlist[*wclist++] = TRUE;
  1065.     wlflag = TRUE;
  1066.     return;
  1067. }
  1068.  
  1069. /*    getwlist:    place in a buffer a list of characters
  1070.             considered "in a word"            */
  1071.  
  1072. char *PASCAL NEAR getwlist(buf)
  1073.  
  1074. char *buf;    /* buffer to place list of characters */
  1075.  
  1076. {
  1077.     register int index;
  1078.     register char *sp;
  1079.  
  1080.     /* if we are defaulting to a standard word char list... */
  1081.     if (wlflag == FALSE)
  1082.         return("");
  1083.  
  1084.     /* build the string of characters in the return buffer */
  1085.     sp = buf;
  1086.     for (index = 0; index < 256; index++)
  1087.         if (wordlist[index])
  1088.             *sp++ = index;
  1089.     *sp = 0;
  1090.     return(buf);
  1091. }
  1092.  
  1093. /*    is_num:    ascii string is integer......This is too
  1094.         inconsistant to use the system's    */
  1095.  
  1096. int PASCAL NEAR is_num(st)
  1097.  
  1098. char *st;
  1099.  
  1100. {
  1101.     int period_flag;    /* have we seen a period yet? */
  1102.  
  1103.     /* skip preceding whitespace */
  1104.     while (*st == ' ' || *st == '\t')
  1105.         ++st;
  1106.  
  1107.     /* check for sign */
  1108.     if ((*st == '-') || (*st == '+'))
  1109.         ++st;
  1110.  
  1111.     /* scan digits */
  1112.     period_flag = FALSE;
  1113.     while ((*st >= '0') && (*st <= '9') ||
  1114.            (*st == '.' && period_flag == FALSE)) {
  1115.         if (*st == '.')
  1116.             period_flag = TRUE;
  1117.         st++;
  1118.     }
  1119.  
  1120.     /* scan rest of line for just white space */
  1121.     while (*st) {
  1122.         if ((*st != '\t') && (*st != ' '))
  1123.             return(FALSE);
  1124.         st++;
  1125.     }
  1126.     return(TRUE);
  1127. }
  1128.  
  1129. #if    DEBUGM
  1130. int PASCAL NEAR dispvar(f, n)        /* display a variable's value */
  1131.  
  1132. int f;        /* default flag */
  1133. int n;        /* numeric arg (can overide prompted value) */
  1134.  
  1135. {
  1136.     register int status;    /* status return */
  1137.     VDESC vd;        /* variable num/type */
  1138.     char var[NVSIZE+1];    /* name of variable to fetch */
  1139.  
  1140.     /* first get the variable to display.. */
  1141.     if (clexec == FALSE) {
  1142.         status = mlreply(TEXT55, &var[0], NVSIZE+1);
  1143. /*                 "Variable to display: " */
  1144.         if (status != TRUE)
  1145.             return(status);
  1146.     } else {    /* macro line argument */
  1147.         /* grab token and skip it */
  1148.         execstr = token(execstr, var, NVSIZE + 1);
  1149.     }
  1150.  
  1151.     /* check the legality and find the var */
  1152.     findvar(var, &vd, NVSIZE + 1);
  1153.         
  1154.     /* if its not legal....bitch */
  1155.     if (vd.v_type == -1) {
  1156.         mlwrite(TEXT52, var);
  1157. /*            "%%No such variable as '%s'" */
  1158.         return(FALSE);
  1159.     }
  1160.  
  1161.     /* and display the value */
  1162.     strcpy(outline, var);
  1163.     strcat(outline, " = ");
  1164.  
  1165.     /* and lastly the current value */
  1166.     strcat(outline, fixnull(getval(var)));
  1167.  
  1168.     /* expand '%' to "%%" so mlwrite wont bitch */
  1169.     makelit(outline);
  1170.  
  1171.     /* write out the result */
  1172.     mlforce(outline);
  1173.     update(TRUE);
  1174.  
  1175.     /* and return */
  1176.     return(TRUE);
  1177. }
  1178.  
  1179. /*    describe-variables    Bring up a fake buffer and list the contents
  1180.                 of all the environment variables
  1181. */
  1182.  
  1183. PASCAL NEAR desvars(f, n)
  1184.  
  1185. int f,n;    /* prefix flag and argument */
  1186.  
  1187. {
  1188.     register WINDOW *wp;    /* scanning pointer to windows */
  1189.     register BUFFER *varbuf;/* buffer to put variable list into */
  1190.     register int uindex;    /* index into uvar table */
  1191.     char outseq[256];    /* output buffer for keystroke sequence */
  1192.  
  1193.     /* and get a buffer for it */
  1194.     varbuf = bfind(TEXT56, TRUE, 0);
  1195. /*           "Variable list" */
  1196.     if (varbuf == NULL || bclear(varbuf) == FALSE) {
  1197.         mlwrite(TEXT57);
  1198. /*            "Can not display variable list" */
  1199.         return(FALSE);
  1200.     }
  1201.  
  1202.     /* let us know this is in progress */
  1203.     mlwrite(TEXT58);
  1204. /*        "[Building variable list]" */
  1205.  
  1206.     /* build the environment variable list */
  1207.     for (uindex = 0; uindex < NEVARS; uindex++) {
  1208.  
  1209.         /* add in the environment variable name */
  1210.         strcpy(outseq, "$");
  1211.         strcat(outseq, envars[uindex]);
  1212.         pad(outseq, 14);
  1213.             
  1214.         /* add in the value */
  1215.         strcat(outseq, gtenv(envars[uindex]));
  1216.  
  1217.         /* and add it as a line into the buffer */
  1218.         if (addline(varbuf, outseq) != TRUE)
  1219.             return(FALSE);
  1220.     }
  1221.  
  1222.     if (addline(varbuf, "") != TRUE)
  1223.         return(FALSE);
  1224.  
  1225.     /* build the user variable list */
  1226.     for (uindex = 0; uindex < MAXVARS; uindex++) {
  1227.         if (uv[uindex].u_name[0] == 0)
  1228.             break;
  1229.  
  1230.         /* add in the user variable name */
  1231.         strcpy(outseq, "%");
  1232.         strcat(outseq, uv[uindex].u_name);
  1233.         pad(outseq, 14);
  1234.             
  1235.         /* add in the value */
  1236.         strcat(outseq, uv[uindex].u_value);
  1237.  
  1238.         /* and add it as a line into the buffer */
  1239.         if (addline(varbuf, outseq) != TRUE)
  1240.             return(FALSE);
  1241.     }
  1242.  
  1243.     /* display the list */
  1244.     wpopup(varbuf);
  1245.     mlerase();    /* clear the mode line */
  1246.     return(TRUE);
  1247. }
  1248.  
  1249. /*    describe-functions    Bring up a fake buffer and list the
  1250.                 names of all the functions
  1251. */
  1252.  
  1253. PASCAL NEAR desfunc(f, n)
  1254.  
  1255. int f,n;    /* prefix flag and argument */
  1256.  
  1257. {
  1258.     register WINDOW *wp;    /* scanning pointer to windows */
  1259.     register BUFFER *fncbuf;/* buffer to put function list into */
  1260.     register int uindex;    /* index into funcs table */
  1261.     char outseq[80];    /* output buffer for keystroke sequence */
  1262.  
  1263.     /* get a buffer for the function list */
  1264.     fncbuf = bfind(TEXT211, TRUE, 0);
  1265. /*           "Function list" */
  1266.     if (fncbuf == NULL || bclear(fncbuf) == FALSE) {
  1267.         mlwrite(TEXT212);
  1268. /*            "Can not display function list" */
  1269.         return(FALSE);
  1270.     }
  1271.  
  1272.     /* let us know this is in progress */
  1273.     mlwrite(TEXT213);
  1274. /*        "[Building function list]" */
  1275.  
  1276.     /* build the function list */
  1277.     for (uindex = 0; uindex < NFUNCS; uindex++) {
  1278.  
  1279.         /* add in the environment variable name */
  1280.         strcpy(outseq, "&");
  1281.         strcat(outseq, funcs[uindex].f_name);
  1282.  
  1283.         /* and add it as a line into the buffer */
  1284.         if (addline(fncbuf, outseq) != TRUE)
  1285.             return(FALSE);
  1286.     }
  1287.  
  1288.     if (addline(fncbuf, "") != TRUE)
  1289.         return(FALSE);
  1290.  
  1291.     /* display the list */
  1292.     wpopup(fncbuf);
  1293.     mlerase();    /* clear the mode line */
  1294.     return(TRUE);
  1295. }
  1296.  
  1297. pad(s, len)    /* pad a string to indicated length */
  1298.  
  1299. char *s;    /* string to add spaces to */
  1300. int len;    /* wanted length of string */
  1301.  
  1302. {
  1303.     while (strlen(s) < len) {
  1304.                 strcat(s, "          ");
  1305.         s[len] = 0;
  1306.     }
  1307. }
  1308. #endif
  1309.