home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / microema.sit / src / eval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-09  |  19.6 KB  |  843 lines  |  [TEXT/Earl]

  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    "edef.h"
  9. #include    "evar.h"
  10. #define __SEG__ INIT
  11. varinit()        /* initialize the user variable list */
  12.  
  13. {
  14.     register int i;
  15.  
  16.     for (i=0; i < MAXVARS; i++)
  17.         uv[i].u_name[0] = 0;
  18. }
  19. #define __SEG__ eval
  20. char *gtfun(fname)    /* evaluate a function */
  21.  
  22. char *fname;        /* name of function to evaluate */
  23.  
  24. {
  25.     register int fnum;        /* index to function to eval */
  26.     register int status;        /* return status */
  27.     register char *tsp;        /* temporary string pointer */
  28.     char arg1[NSTRING];        /* value of first argument */
  29.     char arg2[NSTRING];        /* value of second argument */
  30.     char arg3[NSTRING];        /* value of third argument */
  31.     static char result[2 * NSTRING];    /* string result */
  32.     char *flook();            /* look file up on path */
  33.     char *xlat();            /* translate a char string */
  34. #if    ENVFUNC
  35.     char *getenv();         /* get environment string */
  36. #endif
  37.  
  38.     /* look the function up in the function table */
  39.     fname[3] = 0;    /* only first 3 chars significant */
  40.     mklower(fname); /* and let it be upper or lower case */
  41.     for (fnum = 0; fnum < NFUNCS; fnum++)
  42.         if (strcmp(fname, funcs[fnum].f_name) == 0)
  43.             break;
  44.  
  45.     /* return errorm on a bad reference */
  46.     if (fnum == NFUNCS)
  47.         return(errorm);
  48.  
  49.     /* if needed, retrieve the first argument */
  50.     if (funcs[fnum].f_type >= MONAMIC) {
  51.         if ((status = macarg(arg1)) != TRUE)
  52.             return(errorm);
  53.  
  54.         /* if needed, retrieve the second argument */
  55.         if (funcs[fnum].f_type >= DYNAMIC) {
  56.             if ((status = macarg(arg2)) != TRUE)
  57.                 return(errorm);
  58.     
  59.             /* if needed, retrieve the third argument */
  60.             if (funcs[fnum].f_type >= TRINAMIC)
  61.                 if ((status = macarg(arg3)) != TRUE)
  62.                     return(errorm);
  63.         }
  64.     }
  65.         
  66.  
  67.     /* and now evaluate it! */
  68.     switch (fnum) {
  69.         case UFADD:    return(itoa(atoi(arg1) + atoi(arg2)));
  70.         case UFSUB:    return(itoa(atoi(arg1) - atoi(arg2)));
  71.         case UFTIMES:    return(itoa(atoi(arg1) * atoi(arg2)));
  72.         case UFDIV:    return(itoa(atoi(arg1) / atoi(arg2)));
  73.         case UFMOD:    return(itoa(atoi(arg1) % atoi(arg2)));
  74.         case UFNEG:    return(itoa(-atoi(arg1)));
  75.         case UFCAT:    strcpy(result, arg1);
  76.                 return(strcat(result, arg2));
  77.         case UFLEFT:    return(strncpy(result, arg1, atoi(arg2)));
  78.         case UFRIGHT:    return(strcpy(result,
  79.                     &arg1[(strlen(arg1) - atoi(arg2))]));
  80.         case UFMID:    return(strncpy(result, &arg1[atoi(arg2)-1],
  81.                     atoi(arg3)));
  82.         case UFNOT:    return(ltos(stol(arg1) == FALSE));
  83.         case UFEQUAL:    return(ltos(atoi(arg1) == atoi(arg2)));
  84.         case UFLESS:    return(ltos(atoi(arg1) < atoi(arg2)));
  85.         case UFGREATER: return(ltos(atoi(arg1) > atoi(arg2)));
  86.         case UFSEQUAL:    return(ltos(strcmp(arg1, arg2) == 0));
  87.         case UFSLESS:    return(ltos(strcmp(arg1, arg2) < 0));
  88.         case UFSGREAT:    return(ltos(strcmp(arg1, arg2) > 0));
  89.         case UFIND:    return(strcpy(result, getval(arg1)));
  90.         case UFAND:    return(ltos(stol(arg1) && stol(arg2)));
  91.         case UFOR:    return(ltos(stol(arg1) || stol(arg2)));
  92.         case UFLENGTH:    return(itoa(strlen(arg1)));
  93.         case UFUPPER:    return(mkupper(arg1));
  94.         case UFLOWER:    return(mklower(arg1));
  95.         case UFTRUTH:    return(ltos(atoi(arg1) == 42));
  96.         case UFASCII:    return(itoa((int)arg1[0]));
  97.         case UFCHR:    result[0] = atoi(arg1);
  98.                 result[1] = 0;
  99.                 return(result);
  100.         case UFGTKEY:    result[0] = tgetc();
  101.                 result[1] = 0;
  102.                 return(result);
  103.         case UFRND:    return(itoa((ernd() % abs(atoi(arg1))) + 1));
  104.         case UFABS:    return(itoa(abs(atoi(arg1))));
  105.         case UFSINDEX:    return(itoa(sindex(arg1, arg2)));
  106.         case UFENV:
  107. #if    ENVFUNC
  108.                 tsp = getenv(arg1);
  109.                 return(tsp == NULL ? "" : tsp);
  110. #else
  111.                 return("");
  112. #endif
  113.         case UFBIND:    return(transbind(arg1));
  114.         case UFEXIST:    return(ltos(fexist(arg1)));
  115.         case UFFIND:
  116.                 tsp = flook(arg1, TRUE);
  117.                 return(tsp == NULL ? "" : tsp);
  118.         case UFBAND:    return(itoa(atoi(arg1) & atoi(arg2)));
  119.         case UFBOR:    return(itoa(atoi(arg1) | atoi(arg2)));
  120.         case UFBXOR:    return(itoa(atoi(arg1) ^ atoi(arg2)));
  121.         case UFBNOT:    return(itoa(~atoi(arg1)));
  122.         case UFXLATE:    return(xlat(arg1, arg2, arg3));
  123.     }
  124.  
  125.     exit(-11);    /* never should get here */
  126. }
  127.  
  128. char *gtusr(vname)    /* look up a user var's value */
  129.  
  130. char *vname;        /* name of user variable to fetch */
  131.  
  132. {
  133.  
  134.     register int vnum;    /* ordinal number of user var */
  135.  
  136.     /* scan the list looking for the user var name */
  137.     for (vnum = 0; vnum < MAXVARS; vnum++) {
  138.         if (uv[vnum].u_name[0] == 0)
  139.             return(errorm);
  140.         if (strcmp(vname, uv[vnum].u_name) == 0)
  141.             return(uv[vnum].u_value);
  142.     }
  143.  
  144.     /* return errorm if we run off the end */
  145.     return(errorm);
  146. }
  147.  
  148. char *gtenv(vname)
  149.  
  150. char *vname;        /* name of environment variable to retrieve */
  151.  
  152. {
  153.     register int vnum;    /* ordinal number of var refrenced */
  154.     char *getkill();
  155.  
  156.     /* scan the list, looking for the referenced name */
  157.     for (vnum = 0; vnum < NEVARS; vnum++)
  158.         if (strcmp(vname, envars[vnum]) == 0)
  159.             break;
  160.  
  161.     /* return errorm on a bad reference */
  162.     if (vnum == NEVARS)
  163.         return(errorm);
  164.  
  165.     /* otherwise, fetch the appropriate value */
  166.     switch (vnum) {
  167.         case EVFILLCOL: return(itoa(fillcol));
  168.         case EVPAGELEN: return(itoa(term.t_nrow + 1));
  169.         case EVCURCOL:    return(itoa(getccol(FALSE)));
  170.         case EVCURLINE: return(itoa(getcline()));
  171.         case EVRAM:    return(itoa((int)(envram / 1024l)));
  172.         case EVFLICKER: return(ltos(flickcode));
  173.         case EVCURWIDTH:return(itoa(term.t_ncol));
  174.         case EVCBUFNAME:return(curbp->b_bname);
  175.         case EVCFNAME:    return(curbp->b_fname);
  176.         case EVSRES:    return(sres);
  177.         case EVDEBUG:    return(ltos(macbug));
  178.         case EVSTATUS:    return(ltos(cmdstatus));
  179.         case EVPALETTE: return(palstr);
  180.         case EVASAVE:    return(itoa(gasave));
  181.         case EVACOUNT:    return(itoa(gacount));
  182.         case EVLASTKEY: return(itoa(lastkey));
  183.         case EVCURCHAR:
  184.             return(curwp->w_dotp->l_used ==
  185.                     curwp->w_doto ? itoa(EOLCHAR) :
  186.                 itoa(lgetc(curwp->w_dotp, curwp->w_doto)));
  187.         case EVDISCMD:    return(ltos(discmd));
  188.         case EVVERSION: return(VERSION);
  189.         case EVPROGNAME:return(PROGNAME);
  190.         case EVSEED:    return(itoa(seed));
  191.         case EVDISINP:    return(ltos(disinp));
  192.         case EVWLINE:    return(itoa(curwp->w_ntrows));
  193.         case EVCWLINE:    return(itoa(getwpos()));
  194.         case EVTARGET:    saveflag = lastflag;
  195.                 return(itoa(curgoal));
  196.         case EVSEARCH:    return(pat);
  197.         case EVREPLACE: return(rpat);
  198.         case EVMATCH:    return((patmatch == NULL)? "": patmatch);
  199.         case EVKILL:    return(getkill());
  200.         case EVCMODE:    return(itoa(curbp->b_mode));
  201.         case EVGMODE:    return(itoa(gmode));
  202.         case EVTPAUSE:    return(itoa(term.t_pause));
  203.         case EVPENDING:
  204. #if    TYPEAH
  205.                 return(ltos(typahead()));
  206. #else
  207.                 return(falsem);
  208. #endif
  209.         case EVLWIDTH:    return(itoa(llength(curwp->w_dotp)));
  210.         case EVLINE:    return(getctext());
  211.         case EVGFLAGS:    return(itoa(gflags));
  212.         case EVRVAL:    return(itoa(rval));
  213.         case EVTVAL:    return(tagsfile);
  214.     }
  215.     exit(-12);    /* again, we should never get here */
  216. }
  217.  
  218. char *getkill()     /* return some of the contents of the kill buffer */
  219.  
  220. {
  221.     register int size;    /* max number of chars to return */
  222.     char value[NSTRING];    /* temp buffer for value */
  223.  
  224.     if (kbufh == NULL)
  225.         /* no kill buffer....just a null string */
  226.         value[0] = 0;
  227.     else {
  228.         /* copy in the contents... */
  229.         if (kused < NSTRING)
  230.             size = kused;
  231.         else
  232.             size = NSTRING - 1;
  233.         strncpy(value, kbufh->d_chunk, size);
  234.     }
  235.  
  236.     /* and return the constructed value */
  237.     return(value);
  238. }
  239.  
  240. int setvar(f, n)        /* set a variable */
  241.  
  242. int f;        /* default flag */
  243. int n;        /* numeric arg (can overide prompted value) */
  244.  
  245. {
  246.     register int status;    /* status return */
  247. #if    DEBUGM
  248.     register char *sp;    /* temp string pointer */
  249.     register char *ep;    /* ptr to end of outline */
  250. #endif
  251.     VDESC vd;        /* variable num/type */
  252.     char var[NVSIZE+1];    /* name of variable to fetch */
  253.     char value[NSTRING];    /* value to set variable to */
  254.  
  255.     /* first get the variable to set.. */
  256.     if (clexec == FALSE) {
  257.         status = mlreply("Variable to set: ", &var[0], NVSIZE);
  258.         if (status != TRUE)
  259.             return(status);
  260.     } else {    /* macro line argument */
  261.         /* grab token and skip it */
  262.         execstr = token(execstr, var, NVSIZE + 1);
  263.     }
  264.  
  265.     /* check the legality and find the var */
  266.     findvar(var, &vd, NVSIZE + 1);
  267.     
  268.     /* if its not legal....bitch */
  269.     if (vd.v_type == -1) {
  270.         mlwrite("%%No such variable as '%s'", var);
  271.         return(FALSE);
  272.     }
  273.  
  274.     /* get the value for that variable */
  275.     if (f == TRUE)
  276.         strcpy(value, itoa(n));
  277.     else {
  278.         status = mlreply("Value: ", &value[0], NSTRING);
  279.         if (status != TRUE)
  280.             return(status);
  281.     }
  282.  
  283.     /* and set the appropriate value */
  284.     status = svar(&vd, value);
  285.  
  286. #if    DEBUGM
  287.     /* if $debug == TRUE, every assignment will echo a statment to
  288.        that effect here. */
  289.     
  290.     if (macbug) {
  291.         strcpy(outline, "(((");
  292.  
  293.         /* assignment status */
  294.         strcat(outline, ltos(status));
  295.         strcat(outline, ":");
  296.  
  297.         /* variable name */
  298.         strcat(outline, var);
  299.         strcat(outline, ":");
  300.  
  301.         /* and lastly the value we tried to assign */
  302.         strcat(outline, value);
  303.         strcat(outline, ")))");
  304.  
  305.         /* expand '%' to "%%" so mlwrite wont bitch */
  306.         sp = outline;
  307.         while (*sp)
  308.             if (*sp++ == '%') {
  309.                 /* advance to the end */
  310.                 ep = --sp;
  311.                 while (*ep++)
  312.                     ;
  313.                 /* null terminate the string one out */
  314.                 *(ep + 1) = 0;
  315.                 /* copy backwards */
  316.                 while(ep-- > sp)
  317.                     *(ep + 1) = *ep;
  318.  
  319.                 /* and advance sp past the new % */
  320.                 sp += 2;                    
  321.             }
  322.  
  323.         /* write out the debug line */
  324.         mlforce(outline);
  325.         update(TRUE);
  326.  
  327.         /* and get the keystroke to hold the output */
  328.         if (get1key() == abortc) {
  329.             mlforce("[Macro aborted]");
  330.             status = FALSE;
  331.         }
  332.     }
  333. #endif
  334.  
  335.     /* and return it */
  336.     return(status);
  337. }
  338.  
  339. findvar(var, vd, size)    /* find a variables type and name */
  340.  
  341. char *var;    /* name of var to get */
  342. VDESC *vd;    /* structure to hold type and ptr */
  343. int size;    /* size of var array */
  344.  
  345. {
  346.     register int vnum;    /* subscript in varable arrays */
  347.     register int vtype;    /* type to return */
  348.  
  349. fvar:    vtype = -1;
  350.     switch (var[0]) {
  351.  
  352.         case '$': /* check for legal enviromnent var */
  353.             for (vnum = 0; vnum < NEVARS; vnum++)
  354.                 if (strcmp(&var[1], envars[vnum]) == 0) {
  355.                     vtype = TKENV;
  356.                     break;
  357.                 }
  358.             break;
  359.  
  360.         case '%': /* check for existing legal user variable */
  361.             for (vnum = 0; vnum < MAXVARS; vnum++)
  362.                 if (strcmp(&var[1], uv[vnum].u_name) == 0) {
  363.                     vtype = TKVAR;
  364.                     break;
  365.                 }
  366.             if (vnum < MAXVARS)
  367.                 break;
  368.  
  369.             /* create a new one??? */
  370.             for (vnum = 0; vnum < MAXVARS; vnum++)
  371.                 if (uv[vnum].u_name[0] == 0) {
  372.                     vtype = TKVAR;
  373.                     strcpy(uv[vnum].u_name, &var[1]);
  374.                     break;
  375.                 }
  376.             break;
  377.  
  378.         case '&':    /* indirect operator? */
  379.             var[4] = 0;
  380.             if (strcmp(&var[1], "ind") == 0) {
  381.                 /* grab token, and eval it */
  382.                 execstr = token(execstr, var, size);
  383.                 strcpy(var, getval(var));
  384.                 goto fvar;
  385.             }
  386.     }
  387.  
  388.     /* return the results */
  389.     vd->v_num = vnum;
  390.     vd->v_type = vtype;
  391.     return;
  392. }
  393.  
  394. int svar(var, value)        /* set a variable */
  395.  
  396. VDESC *var;    /* variable to set */
  397. char *value;    /* value to set to */
  398.  
  399. {
  400.     register int vnum;    /* ordinal number of var refrenced */
  401.     register int vtype;    /* type of variable to set */
  402.     register int status;    /* status return */
  403.     register int c;     /* translated character */
  404.     register char * sp;    /* scratch string pointer */
  405.  
  406.     /* simplify the vd structure (we are gonna look at it a lot) */
  407.     vnum = var->v_num;
  408.     vtype = var->v_type;
  409.  
  410.     /* and set the appropriate value */
  411.     status = TRUE;
  412.     switch (vtype) {
  413.     case TKVAR: /* set a user variable */
  414.         if (uv[vnum].u_value != NULL)
  415.             free(uv[vnum].u_value);
  416.         sp = malloc(strlen(value) + 1);
  417.         if (sp == NULL)
  418.             return(FALSE);
  419.         strcpy(sp, value);
  420.         uv[vnum].u_value = sp;
  421.         break;
  422.  
  423.     case TKENV: /* set an environment variable */
  424.         status = TRUE;    /* by default */
  425.         switch (vnum) {
  426.         case EVFILLCOL: fillcol = atoi(value);
  427.                 break;
  428.         case EVPAGELEN: status = newsize(TRUE, atoi(value));
  429.                 break;
  430.         case EVCURCOL:    status = setccol(atoi(value));
  431.                 break;
  432.         case EVCURLINE: status = gotoline(TRUE, atoi(value));
  433.                 break;
  434.         case EVRAM:    break;
  435.         case EVFLICKER: flickcode = stol(value);
  436.                 break;
  437.         case EVCURWIDTH:status = newwidth(TRUE, atoi(value));
  438.                 break;
  439.         case EVCBUFNAME:strcpy(curbp->b_bname, value);
  440.                 curwp->w_flag |= WFMODE;
  441.                 break;
  442.         case EVCFNAME:    strcpy(curbp->b_fname, value);
  443.                 curwp->w_flag |= WFMODE;
  444.                 break;
  445.         case EVSRES:    status = TTrez(value);
  446.                 break;
  447.         case EVDEBUG:    macbug = stol(value);
  448.                 break;
  449.         case EVSTATUS:    cmdstatus = stol(value);
  450.                 break;
  451.         case EVPALETTE: strncpy(palstr, value, 48);
  452.                 spal(palstr);
  453.                 break;
  454.         case EVASAVE:    gasave = atoi(value);
  455.                 break;
  456.         case EVACOUNT:    gacount = atoi(value);
  457.                 break;
  458.         case EVLASTKEY: lastkey = atoi(value);
  459.                 break;
  460.         case EVCURCHAR: ldelete(1L, FALSE);    /* delete 1 char */
  461.                 c = atoi(value);
  462.                 if (c == EOLCHAR)
  463.                     lnewline(FALSE, 1);
  464.                 else
  465.                     linsert(1, c);
  466.                 backchar(FALSE, 1);
  467.                 break;
  468.         case EVDISCMD:    discmd = stol(value);
  469.                 break;
  470.         case EVVERSION: break;
  471.         case EVPROGNAME:break;
  472.         case EVSEED:    seed = atoi(value);
  473.                 break;
  474.         case EVDISINP:    disinp = stol(value);
  475.                 break;
  476.         case EVWLINE:    status = resize(TRUE, atoi(value));
  477.                 break;
  478.         case EVCWLINE:    status = forwline(TRUE,
  479.                         atoi(value) - getwpos());
  480.                 break;
  481.         case EVTARGET:    curgoal = atoi(value);
  482.                 thisflag = saveflag;
  483.                 break;
  484.         case EVSEARCH:    strcpy(pat, value);
  485.                 rvstrcpy(tap, pat);
  486. #if    MAGIC
  487.                 mcclear();
  488. #endif
  489.                 break;
  490.         case EVREPLACE: strcpy(rpat, value);
  491.                 break;
  492.         case EVMATCH:    break;
  493.         case EVKILL:    break;
  494.         case EVCMODE:    curbp->b_mode = atoi(value);
  495.                 curwp->w_flag |= WFMODE;
  496.                 break;
  497.         case EVGMODE:    gmode = atoi(value);
  498.                 break;
  499.         case EVTPAUSE:    term.t_pause = atoi(value);
  500.                 break;
  501.         case EVPENDING: break;
  502.         case EVLWIDTH:    break;
  503.         case EVLINE:    putctext(value);
  504.         case EVGFLAGS:    gflags = atoi(value);
  505.                 break;
  506.         case EVRVAL:    break;
  507.         case EVTVAL:    strcpy(tagsfile,value);
  508.             break;
  509.         }
  510.         break;
  511.     }
  512.     return(status);
  513. }
  514.  
  515. /*    atoi:    ascii string to integer......This is too
  516.         inconsistent to use the system's        */
  517.  
  518. atoi(st)
  519.  
  520. char *st;
  521.  
  522. {
  523.     int result;    /* resulting number */
  524.     int sign;    /* sign of resulting number */
  525.     char c;     /* current char being examined */
  526.  
  527.     result = 0;
  528.     sign = 1;
  529.  
  530.     /* skip preceding whitespace */
  531.     while (*st == ' ' || *st == '\t')
  532.         ++st;
  533.  
  534.     /* check for sign */
  535.     if (*st == '-') {
  536.         sign = -1;
  537.         ++st;
  538.     }
  539.     if (*st == '+')
  540.         ++st;
  541.  
  542.     /* scan digits, build value */
  543.     while ((c = *st++))
  544.         if (c >= '0' && c <= '9')
  545.             result = result * 10 + c - '0';
  546.         else
  547.             return(0);
  548.  
  549.     return(result * sign);
  550. }
  551.  
  552. /*    itoa:    integer to ascii string.......... This is too
  553.         inconsistant to use the system's        */
  554.  
  555. char *itoa(i)
  556.  
  557. int i;    /* integer to translate to a string */
  558.  
  559. {
  560.     register int digit;        /* current digit being used */
  561.     register char *sp;        /* pointer into result */
  562.     register int sign;        /* sign of resulting number */
  563.     static char result[INTWIDTH+1]; /* resulting string */
  564.  
  565.     /* record the sign...*/
  566.     sign = 1;
  567.     if (i < 0) {
  568.         sign = -1;
  569.         i = -i;
  570.     }
  571.  
  572.     /* and build the string (backwards!) */
  573.     sp = result + INTWIDTH;
  574.     *sp = 0;
  575.     do {
  576.         digit = i % 10;
  577.         *(--sp) = '0' + digit;    /* and install the new digit */
  578.         i = i / 10;
  579.     } while (i);
  580.  
  581.     /* and fix the sign */
  582.     if (sign == -1) {
  583.         *(--sp) = '-';    /* and install the minus sign */
  584.     }
  585.  
  586.     return(sp);
  587. }
  588.  
  589. int gettyp(token)    /* find the type of a passed token */
  590.  
  591. char *token;    /* token to analyze */
  592.  
  593. {
  594.     register char c;    /* first char in token */
  595.  
  596.     /* grab the first char (this is all we need) */
  597.     c = *token;
  598.  
  599.     /* no blanks!!! */
  600.     if (c == 0)
  601.         return(TKNUL);
  602.  
  603.     /* a numeric literal? */
  604.     if (c >= '0' && c <= '9')
  605.         return(TKLIT);
  606.  
  607.     switch (c) {
  608.         case '"':       return(TKSTR);
  609.  
  610.         case '!':    return(TKDIR);
  611.         case '@':    return(TKARG);
  612.         case '#':    return(TKBUF);
  613.         case '$':    return(TKENV);
  614.         case '%':    return(TKVAR);
  615.         case '&':    return(TKFUN);
  616.         case '*':    return(TKLBL);
  617.  
  618.         default:    return(TKCMD);
  619.     }
  620. }
  621.  
  622. char *getval(token)    /* find the value of a token */
  623.  
  624. char *token;        /* token to evaluate */
  625.  
  626. {
  627.     register int status;    /* error return */
  628.     register BUFFER *bp;    /* temp buffer pointer */
  629.     register int blen;    /* length of buffer argument */
  630.     register int distmp;    /* temporary discmd flag */
  631.     static char buf[NSTRING];/* string buffer for some returns */
  632.  
  633.     switch (gettyp(token)) {
  634.         case TKNUL:    return("");
  635.  
  636.         case TKARG:    /* interactive argument */
  637.                 strcpy(token, getval(&token[1]));
  638.                 distmp = discmd;    /* echo it always! */
  639.                 discmd = TRUE;
  640.                 status = getstring(token,
  641.                        buf, NSTRING, ctoec(EOLCHAR));
  642.                 discmd = distmp;
  643.                 if (status == ABORT)
  644.                     return(errorm);
  645.                 return(buf);
  646.  
  647.         case TKBUF:    /* buffer contents fetch */
  648.  
  649.                 /* grab the right buffer */
  650.                 strcpy(token, getval(&token[1]));
  651.                 bp = bfind(token, FALSE, 0);
  652.                 if (bp == NULL)
  653.                     return(errorm);
  654.         
  655.                 /* if the buffer is displayed, get the window
  656.                    vars instead of the buffer vars */
  657.                 if (bp->b_nwnd > 0) {
  658.                     curbp->b_dotp = curwp->w_dotp;
  659.                     curbp->b_doto = curwp->w_doto;
  660.                 }
  661.  
  662.                 /* make sure we are not at the end */
  663.                 if (bp->b_linep == bp->b_dotp)
  664.                     return(errorm);
  665.         
  666.                 /* grab the line as an argument */
  667.                 blen = bp->b_dotp->l_used - bp->b_doto;
  668.                 if (blen > NSTRING)
  669.                     blen = NSTRING;
  670.                 strncpy(buf, bp->b_dotp->l_text + bp->b_doto,
  671.                     blen);
  672.                 buf[blen] = 0;
  673.         
  674.                 /* and step the buffer's line ptr ahead a line */
  675.                 bp->b_dotp = bp->b_dotp->l_fp;
  676.                 bp->b_doto = 0;
  677.  
  678.                 /* if displayed buffer, reset window ptr vars*/
  679.                 if (bp->b_nwnd > 0) {
  680.                     curwp->w_dotp = curbp->b_dotp;
  681.                     curwp->w_doto = 0;
  682.                     curwp->w_flag |= WFMOVE;
  683.                 }
  684.  
  685.                 /* and return the spoils */
  686.                 return(buf);        
  687.  
  688.         case TKVAR:    return(gtusr(token+1));
  689.         case TKENV:    return(gtenv(token+1));
  690.         case TKFUN:    return(gtfun(token+1));
  691.         case TKDIR:    return(errorm);
  692.         case TKLBL:    return(errorm);
  693.         case TKLIT:    return(token);
  694.         case TKSTR:    return(token+1);
  695.         case TKCMD:    return(token);
  696.     }
  697. }
  698.  
  699. int stol(val)    /* convert a string to a numeric logical */
  700.  
  701. char *val;    /* value to check for stol */
  702.  
  703. {
  704.     /* check for logical values */
  705.     if (val[0] == 'F')
  706.         return(FALSE);
  707.     if (val[0] == 'T')
  708.         return(TRUE);
  709.  
  710.     /* check for numeric truth (!= 0) */
  711.     return((atoi(val) != 0));
  712. }
  713.  
  714. char *ltos(val)     /* numeric logical to string logical */
  715.  
  716. int val;    /* value to translate */
  717.  
  718. {
  719.     if (val)
  720.         return(truem);
  721.     else
  722.         return(falsem);
  723. }
  724.  
  725. char *mkupper(str)    /* make a string upper case */
  726.  
  727. char *str;        /* string to upper case */
  728.  
  729. {
  730.     char *sp;
  731.  
  732.     sp = str;
  733.     while (*sp) {
  734.         if ('a' <= *sp && *sp <= 'z')
  735.             *sp += 'A' - 'a';
  736.         ++sp;
  737.     }
  738.     return(str);
  739. }
  740.  
  741. char *mklower(str)    /* make a string lower case */
  742.  
  743. char *str;        /* string to lower case */
  744.  
  745. {
  746.     char *sp;
  747.  
  748.     sp = str;
  749.     while (*sp) {
  750.         if ('A' <= *sp && *sp <= 'Z')
  751.             *sp += 'a' - 'A';
  752.         ++sp;
  753.     }
  754.     return(str);
  755. }
  756.  
  757. int abs(x)    /* take the absolute value of an integer */
  758.  
  759. int x;
  760.  
  761. {
  762.     return(x < 0 ? -x : x);
  763. }
  764.  
  765. int ernd()    /* returns a random integer */
  766.  
  767. {
  768.     seed = abs(seed * 1721 + 10007);
  769.     return(seed);
  770. }
  771.  
  772. int sindex(source, pattern)    /* find pattern within source */
  773.  
  774. char *source;    /* source string to search */
  775. char *pattern;    /* string to look for */
  776.  
  777. {
  778.     char *sp;    /* ptr to current position to scan */
  779.     char *csp;    /* ptr to source string during comparison */
  780.     char *cp;    /* ptr to place to check for equality */
  781.  
  782.     /* scanning through the source string */
  783.     sp = source;
  784.     while (*sp) {
  785.         /* scan through the pattern */
  786.         cp = pattern;
  787.         csp = sp;
  788.         while (*cp) {
  789.             if (!eq(*cp, *csp))
  790.                 break;
  791.             ++cp;
  792.             ++csp;
  793.         }
  794.  
  795.         /* was it a match? */
  796.         if (*cp == 0)
  797.             return((int)(sp - source) + 1);
  798.         ++sp;
  799.     }
  800.  
  801.     /* no match at all.. */
  802.     return(0);
  803. }
  804.  
  805. /*    Filter a string through a translation table    */
  806.  
  807. char *xlat(source, lookup, trans)
  808.  
  809. char *source;    /* string to filter */
  810. char *lookup;    /* characters to translate */
  811. char *trans;    /* resulting translated characters */
  812.  
  813. {
  814.     register char *sp;    /* pointer into source table */
  815.     register char *lp;    /* pointer into lookup table */
  816.     register char *rp;    /* pointer into result */
  817.     static char result[NSTRING];    /* temporary result */
  818.  
  819.     /* scan source string */
  820.     sp = source;
  821.     rp = result;
  822.     while (*sp) {
  823.         /* scan lookup table for a match */
  824.         lp = lookup;
  825.         while (*lp) {
  826.             if (*sp == *lp) {
  827.                 *rp++ = trans[lp - lookup];
  828.                 goto xnext;
  829.             }
  830.             ++lp;
  831.         }
  832.  
  833.         /* no match, copy in the source char untranslated */
  834.         *rp++ = *sp;
  835.  
  836. xnext:        ++sp;
  837.     }
  838.  
  839.     /* terminate and return the result */
  840.     *rp = 0;
  841.     return(result);
  842. }
  843.