home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff119.lzh / MicroEMACS / src / src.zoo / eval.c < prev    next >
C/C++ Source or Header  |  1987-12-09  |  20KB  |  840 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    "edef.h"
  9. #include    "evar.h"
  10.  
  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.  
  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('\n') :
  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.     }
  214.     exit(-12);    /* again, we should never get here */
  215. }
  216.  
  217. char *getkill()        /* return some of the contents of the kill buffer */
  218.  
  219. {
  220.     register int size;    /* max number of chars to return */
  221.     char value[NSTRING];    /* temp buffer for value */
  222.  
  223.     if (kbufh == NULL)
  224.         /* no kill buffer....just a null string */
  225.         value[0] = 0;
  226.     else {
  227.         /* copy in the contents... */
  228.         if (kused < NSTRING)
  229.             size = kused;
  230.         else
  231.             size = NSTRING - 1;
  232.         strncpy(value, kbufh->d_chunk, size);
  233.     }
  234.  
  235.     /* and return the constructed value */
  236.     return(value);
  237. }
  238.  
  239. int setvar(f, n)        /* set a variable */
  240.  
  241. int f;        /* default flag */
  242. int n;        /* numeric arg (can overide prompted value) */
  243.  
  244. {
  245.     register int status;    /* status return */
  246. #if    DEBUGM
  247.     register char *sp;    /* temp string pointer */
  248.     register char *ep;    /* ptr to end of outline */
  249. #endif
  250.     VDESC vd;        /* variable num/type */
  251.     char var[NVSIZE+1];    /* name of variable to fetch */
  252.     char value[NSTRING];    /* value to set variable to */
  253.  
  254.     /* first get the variable to set.. */
  255.     if (clexec == FALSE) {
  256.         status = mlreply("Variable to set: ", &var[0], NVSIZE);
  257.         if (status != TRUE)
  258.             return(status);
  259.     } else {    /* macro line argument */
  260.         /* grab token and skip it */
  261.         execstr = token(execstr, var, NVSIZE + 1);
  262.     }
  263.  
  264.     /* check the legality and find the var */
  265.     findvar(var, &vd, NVSIZE + 1);
  266.     
  267.     /* if its not legal....bitch */
  268.     if (vd.v_type == -1) {
  269.         mlwrite("%%No such variable as '%s'", var);
  270.         return(FALSE);
  271.     }
  272.  
  273.     /* get the value for that variable */
  274.     if (f == TRUE)
  275.         strcpy(value, itoa(n));
  276.     else {
  277.         status = mlreply("Value: ", &value[0], NSTRING);
  278.         if (status != TRUE)
  279.             return(status);
  280.     }
  281.  
  282.     /* and set the appropriate value */
  283.     status = svar(&vd, value);
  284.  
  285. #if    DEBUGM
  286.     /* if $debug == TRUE, every assignment will echo a statment to
  287.        that effect here. */
  288.     
  289.     if (macbug) {
  290.         strcpy(outline, "(((");
  291.  
  292.         /* assignment status */
  293.         strcat(outline, ltos(status));
  294.         strcat(outline, ":");
  295.  
  296.         /* variable name */
  297.         strcat(outline, var);
  298.         strcat(outline, ":");
  299.  
  300.         /* and lastly the value we tried to assign */
  301.         strcat(outline, value);
  302.         strcat(outline, ")))");
  303.  
  304.         /* expand '%' to "%%" so mlwrite wont bitch */
  305.         sp = outline;
  306.         while (*sp)
  307.             if (*sp++ == '%') {
  308.                 /* advance to the end */
  309.                 ep = --sp;
  310.                 while (*ep++)
  311.                     ;
  312.                 /* null terminate the string one out */
  313.                 *(ep + 1) = 0;
  314.                 /* copy backwards */
  315.                 while(ep-- > sp)
  316.                     *(ep + 1) = *ep;
  317.  
  318.                 /* and advance sp past the new % */
  319.                 sp += 2;                    
  320.             }
  321.  
  322.         /* write out the debug line */
  323.         mlforce(outline);
  324.         update(TRUE);
  325.  
  326.         /* and get the keystroke to hold the output */
  327.         if (get1key() == abortc) {
  328.             mlforce("[Macro aborted]");
  329.             status = FALSE;
  330.         }
  331.     }
  332. #endif
  333.  
  334.     /* and return it */
  335.     return(status);
  336. }
  337.  
  338. findvar(var, vd, size)    /* find a variables type and name */
  339.  
  340. char *var;    /* name of var to get */
  341. VDESC *vd;    /* structure to hold type and ptr */
  342. int size;    /* size of var array */
  343.  
  344. {
  345.     register int vnum;    /* subscript in varable arrays */
  346.     register int vtype;    /* type to return */
  347.  
  348. fvar:    vtype = -1;
  349.     switch (var[0]) {
  350.  
  351.         case '$': /* check for legal enviromnent var */
  352.             for (vnum = 0; vnum < NEVARS; vnum++)
  353.                 if (strcmp(&var[1], envars[vnum]) == 0) {
  354.                     vtype = TKENV;
  355.                     break;
  356.                 }
  357.             break;
  358.  
  359.         case '%': /* check for existing legal user variable */
  360.             for (vnum = 0; vnum < MAXVARS; vnum++)
  361.                 if (strcmp(&var[1], uv[vnum].u_name) == 0) {
  362.                     vtype = TKVAR;
  363.                     break;
  364.                 }
  365.             if (vnum < MAXVARS)
  366.                 break;
  367.  
  368.             /* create a new one??? */
  369.             for (vnum = 0; vnum < MAXVARS; vnum++)
  370.                 if (uv[vnum].u_name[0] == 0) {
  371.                     vtype = TKVAR;
  372.                     strcpy(uv[vnum].u_name, &var[1]);
  373.                     break;
  374.                 }
  375.             break;
  376.  
  377.         case '&':    /* indirect operator? */
  378.             var[4] = 0;
  379.             if (strcmp(&var[1], "ind") == 0) {
  380.                 /* grab token, and eval it */
  381.                 execstr = token(execstr, var, size);
  382.                 strcpy(var, getval(var));
  383.                 goto fvar;
  384.             }
  385.     }
  386.  
  387.     /* return the results */
  388.     vd->v_num = vnum;
  389.     vd->v_type = vtype;
  390.     return;
  391. }
  392.  
  393. int svar(var, value)        /* set a variable */
  394.  
  395. VDESC *var;    /* variable to set */
  396. char *value;    /* value to set to */
  397.  
  398. {
  399.     register int vnum;    /* ordinal number of var refrenced */
  400.     register int vtype;    /* type of variable to set */
  401.     register int status;    /* status return */
  402.     register int c;        /* translated character */
  403.     register char * sp;    /* scratch string pointer */
  404.  
  405.     /* simplify the vd structure (we are gonna look at it a lot) */
  406.     vnum = var->v_num;
  407.     vtype = var->v_type;
  408.  
  409.     /* and set the appropriate value */
  410.     status = TRUE;
  411.     switch (vtype) {
  412.     case TKVAR: /* set a user variable */
  413.         if (uv[vnum].u_value != NULL)
  414.             free(uv[vnum].u_value);
  415.         sp = malloc(strlen(value) + 1);
  416.         if (sp == NULL)
  417.             return(FALSE);
  418.         strcpy(sp, value);
  419.         uv[vnum].u_value = sp;
  420.         break;
  421.  
  422.     case TKENV: /* set an environment variable */
  423.         status = TRUE;    /* by default */
  424.         switch (vnum) {
  425.         case EVFILLCOL:    fillcol = atoi(value);
  426.                 break;
  427.         case EVPAGELEN:    status = newsize(TRUE, atoi(value));
  428.                 break;
  429.         case EVCURCOL:    status = setccol(atoi(value));
  430.                 break;
  431.         case EVCURLINE:    status = gotoline(TRUE, atoi(value));
  432.                 break;
  433.         case EVRAM:    break;
  434.         case EVFLICKER:    flickcode = stol(value);
  435.                 break;
  436.         case EVCURWIDTH:status = newwidth(TRUE, atoi(value));
  437.                 break;
  438.         case EVCBUFNAME:strcpy(curbp->b_bname, value);
  439.                 curwp->w_flag |= WFMODE;
  440.                 break;
  441.         case EVCFNAME:    strcpy(curbp->b_fname, value);
  442.                 curwp->w_flag |= WFMODE;
  443.                 break;
  444.         case EVSRES:    status = TTrez(value);
  445.                 break;
  446.         case EVDEBUG:    macbug = stol(value);
  447.                 break;
  448.         case EVSTATUS:    cmdstatus = stol(value);
  449.                 break;
  450.         case EVPALETTE:    strncpy(palstr, value, 48);
  451.                 spal(palstr);
  452.                 break;
  453.         case EVASAVE:    gasave = atoi(value);
  454.                 break;
  455.         case EVACOUNT:    gacount = atoi(value);
  456.                 break;
  457.         case EVLASTKEY:    lastkey = atoi(value);
  458.                 break;
  459.         case EVCURCHAR:    ldelete(1L, FALSE);    /* delete 1 char */
  460.                 c = atoi(value);
  461.                 if (c == '\n')
  462.                     lnewline(FALSE, 1);
  463.                 else
  464.                     linsert(1, c);
  465.                 backchar(FALSE, 1);
  466.                 break;
  467.         case EVDISCMD:    discmd = stol(value);
  468.                 break;
  469.         case EVVERSION:    break;
  470.         case EVPROGNAME:break;
  471.         case EVSEED:    seed = atoi(value);
  472.                 break;
  473.         case EVDISINP:    disinp = stol(value);
  474.                 break;
  475.         case EVWLINE:    status = resize(TRUE, atoi(value));
  476.                 break;
  477.         case EVCWLINE:    status = forwline(TRUE,
  478.                         atoi(value) - getwpos());
  479.                 break;
  480.         case EVTARGET:    curgoal = atoi(value);
  481.                 thisflag = saveflag;
  482.                 break;
  483.         case EVSEARCH:    strcpy(pat, value);
  484.                 rvstrcpy(tap, pat);
  485. #if    MAGIC
  486.                 mcclear();
  487. #endif
  488.                 break;
  489.         case EVREPLACE:    strcpy(rpat, value);
  490.                 break;
  491.         case EVMATCH:    break;
  492.         case EVKILL:    break;
  493.         case EVCMODE:    curbp->b_mode = atoi(value);
  494.                 curwp->w_flag |= WFMODE;
  495.                 break;
  496.         case EVGMODE:    gmode = atoi(value);
  497.                 break;
  498.         case EVTPAUSE:    term.t_pause = atoi(value);
  499.                 break;
  500.         case EVPENDING:    break;
  501.         case EVLWIDTH:    break;
  502.         case EVLINE:    putctext(value);
  503.         case EVGFLAGS:    gflags = atoi(value);
  504.                 break;
  505.         case EVRVAL:    break;
  506.         }
  507.         break;
  508.     }
  509.     return(status);
  510. }
  511.  
  512. /*    atoi:    ascii string to integer......This is too
  513.         inconsistant to use the system's    */
  514.  
  515. atoi(st)
  516.  
  517. char *st;
  518.  
  519. {
  520.     int result;    /* resulting number */
  521.     int sign;    /* sign of resulting number */
  522.     char c;        /* current char being examined */
  523.  
  524.     result = 0;
  525.     sign = 1;
  526.  
  527.     /* skip preceding whitespace */
  528.     while (*st == ' ' || *st == '\t')
  529.         ++st;
  530.  
  531.     /* check for sign */
  532.     if (*st == '-') {
  533.         sign = -1;
  534.         ++st;
  535.     }
  536.     if (*st == '+')
  537.         ++st;
  538.  
  539.     /* scan digits, build value */
  540.     while ((c = *st++))
  541.         if (c >= '0' && c <= '9')
  542.             result = result * 10 + c - '0';
  543.         else
  544.             return(0);
  545.  
  546.     return(result * sign);
  547. }
  548.  
  549. /*    itoa:    integer to ascii string.......... This is too
  550.         inconsistant to use the system's    */
  551.  
  552. char *itoa(i)
  553.  
  554. int i;    /* integer to translate to a string */
  555.  
  556. {
  557.     register int digit;        /* current digit being used */
  558.     register char *sp;        /* pointer into result */
  559.     register int sign;        /* sign of resulting number */
  560.     static char result[INTWIDTH+1];    /* resulting string */
  561.  
  562.     /* record the sign...*/
  563.     sign = 1;
  564.     if (i < 0) {
  565.         sign = -1;
  566.         i = -i;
  567.     }
  568.  
  569.     /* and build the string (backwards!) */
  570.     sp = result + INTWIDTH;
  571.     *sp = 0;
  572.     do {
  573.         digit = i % 10;
  574.         *(--sp) = '0' + digit;    /* and install the new digit */
  575.         i = i / 10;
  576.     } while (i);
  577.  
  578.     /* and fix the sign */
  579.     if (sign == -1) {
  580.         *(--sp) = '-';    /* and install the minus sign */
  581.     }
  582.  
  583.     return(sp);
  584. }
  585.  
  586. int gettyp(token)    /* find the type of a passed token */
  587.  
  588. char *token;    /* token to analyze */
  589.  
  590. {
  591.     register char c;    /* first char in token */
  592.  
  593.     /* grab the first char (this is all we need) */
  594.     c = *token;
  595.  
  596.     /* no blanks!!! */
  597.     if (c == 0)
  598.         return(TKNUL);
  599.  
  600.     /* a numeric literal? */
  601.     if (c >= '0' && c <= '9')
  602.         return(TKLIT);
  603.  
  604.     switch (c) {
  605.         case '"':    return(TKSTR);
  606.  
  607.         case '!':    return(TKDIR);
  608.         case '@':    return(TKARG);
  609.         case '#':    return(TKBUF);
  610.         case '$':    return(TKENV);
  611.         case '%':    return(TKVAR);
  612.         case '&':    return(TKFUN);
  613.         case '*':    return(TKLBL);
  614.  
  615.         default:    return(TKCMD);
  616.     }
  617. }
  618.  
  619. char *getval(token)    /* find the value of a token */
  620.  
  621. char *token;        /* token to evaluate */
  622.  
  623. {
  624.     register int status;    /* error return */
  625.     register BUFFER *bp;    /* temp buffer pointer */
  626.     register int blen;    /* length of buffer argument */
  627.     register int distmp;    /* temporary discmd flag */
  628.     static char buf[NSTRING];/* string buffer for some returns */
  629.  
  630.     switch (gettyp(token)) {
  631.         case TKNUL:    return("");
  632.  
  633.         case TKARG:    /* interactive argument */
  634.                 strcpy(token, getval(&token[1]));
  635.                 distmp = discmd;    /* echo it always! */
  636.                 discmd = TRUE;
  637.                 status = getstring(token,
  638.                        buf, NSTRING, ctoec('\n'));
  639.                 discmd = distmp;
  640.                 if (status == ABORT)
  641.                     return(errorm);
  642.                 return(buf);
  643.  
  644.         case TKBUF:    /* buffer contents fetch */
  645.  
  646.                 /* grab the right buffer */
  647.                 strcpy(token, getval(&token[1]));
  648.                 bp = bfind(token, FALSE, 0);
  649.                 if (bp == NULL)
  650.                     return(errorm);
  651.         
  652.                 /* if the buffer is displayed, get the window
  653.                    vars instead of the buffer vars */
  654.                 if (bp->b_nwnd > 0) {
  655.                     curbp->b_dotp = curwp->w_dotp;
  656.                     curbp->b_doto = curwp->w_doto;
  657.                 }
  658.  
  659.                 /* make sure we are not at the end */
  660.                 if (bp->b_linep == bp->b_dotp)
  661.                     return(errorm);
  662.         
  663.                 /* grab the line as an argument */
  664.                 blen = bp->b_dotp->l_used - bp->b_doto;
  665.                 if (blen > NSTRING)
  666.                     blen = NSTRING;
  667.                 strncpy(buf, bp->b_dotp->l_text + bp->b_doto,
  668.                     blen);
  669.                 buf[blen] = 0;
  670.         
  671.                 /* and step the buffer's line ptr ahead a line */
  672.                 bp->b_dotp = bp->b_dotp->l_fp;
  673.                 bp->b_doto = 0;
  674.  
  675.                 /* if displayed buffer, reset window ptr vars*/
  676.                 if (bp->b_nwnd > 0) {
  677.                     curwp->w_dotp = curbp->b_dotp;
  678.                     curwp->w_doto = 0;
  679.                     curwp->w_flag |= WFMOVE;
  680.                 }
  681.  
  682.                 /* and return the spoils */
  683.                 return(buf);        
  684.  
  685.         case TKVAR:    return(gtusr(token+1));
  686.         case TKENV:    return(gtenv(token+1));
  687.         case TKFUN:    return(gtfun(token+1));
  688.         case TKDIR:    return(errorm);
  689.         case TKLBL:    return(errorm);
  690.         case TKLIT:    return(token);
  691.         case TKSTR:    return(token+1);
  692.         case TKCMD:    return(token);
  693.     }
  694. }
  695.  
  696. int stol(val)    /* convert a string to a numeric logical */
  697.  
  698. char *val;    /* value to check for stol */
  699.  
  700. {
  701.     /* check for logical values */
  702.     if (val[0] == 'F')
  703.         return(FALSE);
  704.     if (val[0] == 'T')
  705.         return(TRUE);
  706.  
  707.     /* check for numeric truth (!= 0) */
  708.     return((atoi(val) != 0));
  709. }
  710.  
  711. char *ltos(val)        /* numeric logical to string logical */
  712.  
  713. int val;    /* value to translate */
  714.  
  715. {
  716.     if (val)
  717.         return(truem);
  718.     else
  719.         return(falsem);
  720. }
  721.  
  722. char *mkupper(str)    /* make a string upper case */
  723.  
  724. char *str;        /* string to upper case */
  725.  
  726. {
  727.     char *sp;
  728.  
  729.     sp = str;
  730.     while (*sp) {
  731.         if ('a' <= *sp && *sp <= 'z')
  732.             *sp += 'A' - 'a';
  733.         ++sp;
  734.     }
  735.     return(str);
  736. }
  737.  
  738. char *mklower(str)    /* make a string lower case */
  739.  
  740. char *str;        /* string to lower case */
  741.  
  742. {
  743.     char *sp;
  744.  
  745.     sp = str;
  746.     while (*sp) {
  747.         if ('A' <= *sp && *sp <= 'Z')
  748.             *sp += 'a' - 'A';
  749.         ++sp;
  750.     }
  751.     return(str);
  752. }
  753.  
  754. int abs(x)    /* take the absolute value of an integer */
  755.  
  756. int x;
  757.  
  758. {
  759.     return(x < 0 ? -x : x);
  760. }
  761.  
  762. int ernd()    /* returns a random integer */
  763.  
  764. {
  765.     seed = abs(seed * 1721 + 10007);
  766.     return(seed);
  767. }
  768.  
  769. int sindex(source, pattern)    /* find pattern within source */
  770.  
  771. char *source;    /* source string to search */
  772. char *pattern;    /* string to look for */
  773.  
  774. {
  775.     char *sp;    /* ptr to current position to scan */
  776.     char *csp;    /* ptr to source string during comparison */
  777.     char *cp;    /* ptr to place to check for equality */
  778.  
  779.     /* scanning through the source string */
  780.     sp = source;
  781.     while (*sp) {
  782.         /* scan through the pattern */
  783.         cp = pattern;
  784.         csp = sp;
  785.         while (*cp) {
  786.             if (!eq(*cp, *csp))
  787.                 break;
  788.             ++cp;
  789.             ++csp;
  790.         }
  791.  
  792.         /* was it a match? */
  793.         if (*cp == 0)
  794.             return((int)(sp - source) + 1);
  795.         ++sp;
  796.     }
  797.  
  798.     /* no match at all.. */
  799.     return(0);
  800. }
  801.  
  802. /*    Filter a string through a translation table    */
  803.  
  804. char *xlat(source, lookup, trans)
  805.  
  806. char *source;    /* string to filter */
  807. char *lookup;    /* characters to translate */
  808. char *trans;    /* resulting translated characters */
  809.  
  810. {
  811.     register char *sp;    /* pointer into source table */
  812.     register char *lp;    /* pointer into lookup table */
  813.     register char *rp;    /* pointer into result */
  814.     static char result[NSTRING];    /* temporary result */
  815.  
  816.     /* scan source string */
  817.     sp = source;
  818.     rp = result;
  819.     while (*sp) {
  820.         /* scan lookup table for a match */
  821.         lp = lookup;
  822.         while (*lp) {
  823.             if (*sp == *lp) {
  824.                 *rp++ = trans[lp - lookup];
  825.                 goto xnext;
  826.             }
  827.             ++lp;
  828.         }
  829.  
  830.         /* no match, copy in the source char untranslated */
  831.         *rp++ = *sp;
  832.  
  833. xnext:        ++sp;
  834.     }
  835.  
  836.     /* terminate and return the result */
  837.     *rp = 0;
  838.     return(result);
  839. }
  840.