home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / VILE327.ZIP / VILE327.TAR / vile3.27 / eval.c < prev    next >
C/C++ Source or Header  |  1992-12-14  |  21KB  |  852 lines

  1. /*    EVAL.C:    Expression evaluation functions for
  2.         MicroEMACS
  3.  
  4.     written 1986 by Daniel Lawrence
  5.  *
  6.  * $Log: eval.c,v $
  7.  * Revision 1.39  1992/11/19  09:03:56  foxharp
  8.  * fix identification of single character tokens that happen to be prefixes
  9.  * for special constructs, like '~', '*', etc.
  10.  *
  11.  * Revision 1.38  1992/08/20  23:40:48  foxharp
  12.  * typo fixes -- thanks, eric
  13.  *
  14.  * Revision 1.37  1992/07/24  18:22:51  foxharp
  15.  * deleted local atoi() routine -- now we use the system's copy
  16.  *
  17.  * Revision 1.36  1992/07/13  20:09:57  foxharp
  18.  * "terse" is no longer a variable
  19.  *
  20.  * Revision 1.35  1992/07/13  09:26:16  foxharp
  21.  * added "force" argument to current_directory()
  22.  *
  23.  * Revision 1.34  1992/06/25  23:00:50  foxharp
  24.  * changes for dos/ibmpc
  25.  *
  26.  * Revision 1.33  1992/05/19  08:55:44  foxharp
  27.  * more prototype and shadowed decl fixups
  28.  *
  29.  * Revision 1.32  1992/05/16  12:00:31  pgf
  30.  * prototypes/ansi/void-int stuff/microsoftC
  31.  *
  32.  * Revision 1.30  1992/04/10  18:48:17  pgf
  33.  * change abs to absol to get rid of name conflicts
  34.  *
  35.  * Revision 1.29  1992/03/24  09:02:18  pgf
  36.  * need to glob() filenames for &rd and &wr
  37.  *
  38.  * Revision 1.28  1992/03/24  07:36:23  pgf
  39.  * added &rd and &wr functions, for file access, and fixed off-by-one in $curcol
  40.  *
  41.  * Revision 1.27  1992/03/19  23:19:55  pgf
  42.  * linux prototyped portability
  43.  *
  44.  * Revision 1.26  1992/03/19  23:07:47  pgf
  45.  * variable access cleanup/rearrangement
  46.  *
  47.  * Revision 1.25  1992/03/05  09:17:21  pgf
  48.  * added support for new "terse" variable, to control unnecessary messages
  49.  *
  50.  * Revision 1.24  1992/03/03  09:35:52  pgf
  51.  * added support for getting "words" out of the buffer via variables --
  52.  * needed _nonspace character type
  53.  *
  54.  * Revision 1.23  1992/02/17  09:01:16  pgf
  55.  * took out unused vars for saber
  56.  *
  57.  * Revision 1.22  1992/01/05  00:06:13  pgf
  58.  * split mlwrite into mlwrite/mlprompt/mlforce to make errors visible more
  59.  * often.  also normalized message appearance somewhat.
  60.  *
  61.  * Revision 1.21  1992/01/03  23:31:49  pgf
  62.  * use new ch_fname() to manipulate filenames, since b_fname is now
  63.  * a malloc'ed sting, to avoid length limits
  64.  *
  65.  * Revision 1.20  1991/12/24  09:18:47  pgf
  66.  * added current/change directory support  (Dave Lemke's changes)
  67.  *
  68.  * Revision 1.19  1991/11/27  10:09:09  pgf
  69.  * bug fix, from pete
  70.  *
  71.  * Revision 1.18  1991/11/13  20:09:27  pgf
  72.  * X11 changes, from dave lemke
  73.  *
  74.  * Revision 1.17  1991/11/08  13:19:01  pgf
  75.  * lint cleanup
  76.  *
  77.  * Revision 1.16  1991/11/04  14:18:09  pgf
  78.  * use lsprintf in itoa
  79.  *
  80.  * Revision 1.15  1991/11/03  17:36:13  pgf
  81.  * picky saber change
  82.  *
  83.  * Revision 1.14  1991/11/01  14:38:00  pgf
  84.  * saber cleanup
  85.  *
  86.  * Revision 1.13  1991/10/28  14:25:06  pgf
  87.  * eliminated some variables that are now buffer-values
  88.  *
  89.  * Revision 1.12  1991/10/24  13:05:52  pgf
  90.  * conversion to new regex package -- much faster
  91.  *
  92.  * Revision 1.11  1991/10/22  14:10:07  pgf
  93.  * more portable #if --> #ifdef
  94.  *
  95.  * Revision 1.10  1991/09/26  13:12:04  pgf
  96.  * new arg. to kbd_string to enable backslash processing
  97.  *
  98.  * Revision 1.9  1991/09/16  23:46:55  pgf
  99.  * more hardening
  100.  *
  101.  * Revision 1.8  1991/09/13  03:27:06  pgf
  102.  * attempt to harden against bad variable names (like lone %)
  103.  *
  104.  * Revision 1.7  1991/08/07  12:35:07  pgf
  105.  * added RCS log messages
  106.  *
  107.  * revision 1.6
  108.  * date: 1991/08/06 15:13:27;
  109.  * global/local values
  110.  * 
  111.  * revision 1.5
  112.  * date: 1991/06/25 19:52:23;
  113.  * massive data structure restructure
  114.  * 
  115.  * revision 1.4
  116.  * date: 1991/06/03 10:19:11;
  117.  * newscreensize() is now named newlength()
  118.  * 
  119.  * revision 1.3
  120.  * date: 1990/10/01 11:05:54;
  121.  * progname --> prognam
  122.  * 
  123.  * revision 1.2
  124.  * date: 1990/09/25 11:38:13;
  125.  * took out old ifdef BEFORE code
  126.  * 
  127.  * revision 1.1
  128.  * date: 1990/09/21 10:25:11;
  129.  * initial vile RCS revision
  130. */
  131.  
  132. #include    <stdio.h>
  133. #include    "estruct.h"
  134. #include    "edef.h"
  135. #include    "evar.h"
  136.  
  137. void
  138. varinit()        /* initialize the user variable list */
  139. {
  140. #if ! SMALLER
  141.     register int i;
  142.  
  143.     for (i=0; i < MAXVARS; i++)
  144.         uv[i].u_name[0] = 0;
  145. #endif
  146. }
  147.  
  148. #if ! SMALLER
  149. char *gtfun(fname)    /* evaluate a function */
  150. char *fname;        /* name of function to evaluate */
  151. {
  152.     register int fnum;        /* index to function to eval */
  153.     char arg1[NSTRING];        /* value of first argument */
  154.     char arg2[NSTRING];        /* value of second argument */
  155.     char arg3[NSTRING];        /* value of third argument */
  156.     static char result[2 * NSTRING];    /* string result */
  157. #if    ENVFUNC
  158.     char *getenv();
  159. #endif
  160.  
  161.     if (!fname[0])
  162.         return(errorm);
  163.  
  164.     /* look the function up in the function table */
  165.     fname[3] = 0;    /* only first 3 chars significant */
  166.     mklower(fname);    /* and let it be upper or lower case */
  167.     for (fnum = 0; fnum < NFUNCS; fnum++)
  168.         if (strcmp(fname, funcs[fnum].f_name) == 0)
  169.             break;
  170.  
  171.     /* return errorm on a bad reference */
  172.     if (fnum == NFUNCS)
  173.         return(errorm);
  174.  
  175.     /* if needed, retrieve the first argument */
  176.     if (funcs[fnum].f_type >= MONAMIC) {
  177.         if (macarg(arg1) != TRUE)
  178.             return(errorm);
  179.  
  180.         /* if needed, retrieve the second argument */
  181.         if (funcs[fnum].f_type >= DYNAMIC) {
  182.             if (macarg(arg2) != TRUE)
  183.                 return(errorm);
  184.     
  185.             /* if needed, retrieve the third argument */
  186.             if (funcs[fnum].f_type >= TRINAMIC)
  187.                 if (macarg(arg3) != TRUE)
  188.                     return(errorm);
  189.         }
  190.     }
  191.         
  192.  
  193.     /* and now evaluate it! */
  194.     switch (fnum) {
  195.         case UFADD:    return(l_itoa(atoi(arg1) + atoi(arg2)));
  196.         case UFSUB:    return(l_itoa(atoi(arg1) - atoi(arg2)));
  197.         case UFTIMES:    return(l_itoa(atoi(arg1) * atoi(arg2)));
  198.         case UFDIV:    return(l_itoa(atoi(arg1) / atoi(arg2)));
  199.         case UFMOD:    return(l_itoa(atoi(arg1) % atoi(arg2)));
  200.         case UFNEG:    return(l_itoa(-atoi(arg1)));
  201.         case UFCAT:    strcpy(result, arg1);
  202.                 return(strcat(result, arg2));
  203.         case UFLEFT:    return(strncpy(result, arg1, atoi(arg2)));
  204.         case UFRIGHT:    return(strcpy(result, &arg1[atoi(arg2)-1]));
  205.         case UFMID:    return(strncpy(result, &arg1[atoi(arg2)-1],
  206.                     atoi(arg3)));
  207.         case UFNOT:    return(ltos(stol(arg1) == FALSE));
  208.         case UFEQUAL:    return(ltos(atoi(arg1) == atoi(arg2)));
  209.         case UFLESS:    return(ltos(atoi(arg1) < atoi(arg2)));
  210.         case UFGREATER:    return(ltos(atoi(arg1) > atoi(arg2)));
  211.         case UFSEQUAL:    return(ltos(strcmp(arg1, arg2) == 0));
  212.         case UFSLESS:    return(ltos(strcmp(arg1, arg2) < 0));
  213.         case UFSGREAT:    return(ltos(strcmp(arg1, arg2) > 0));
  214.         case UFIND:    return(tokval(arg1));
  215.         case UFAND:    return(ltos(stol(arg1) && stol(arg2)));
  216.         case UFOR:    return(ltos(stol(arg1) || stol(arg2)));
  217.         case UFLENGTH:    return(l_itoa(strlen(arg1)));
  218.         case UFUPPER:    return(mkupper(arg1));
  219.         case UFLOWER:    return(mklower(arg1));
  220.         case UFTRUTH:    return(ltos(atoi(arg1) == 42));
  221.         case UFASCII:    return(l_itoa((int)arg1[0]));
  222.         case UFCHR:    result[0] = atoi(arg1);
  223.                 result[1] = 0;
  224.                 return(result);
  225.         case UFGTKEY:    result[0] = tgetc();
  226.                 result[1] = 0;
  227.                 return(result);
  228.         case UFRND:    return(l_itoa((ernd() % absol(atoi(arg1))) + 1));
  229.         case UFABS:    return(l_itoa(absol(atoi(arg1))));
  230.         case UFSINDEX:    return(l_itoa(sindex(arg1, arg2)));
  231.         case UFENV:
  232. #if    ENVFUNC
  233.                 return(getenv(arg1) == NULL ? "" : getenv(arg1));
  234. #else
  235.                 return("");
  236. #endif
  237.         case UFBIND:    return(prc2engl(arg1));
  238.         case UFREADABLE:glob(arg1);
  239.                 return(ltos(flook(arg1, FL_HERE) != NULL));
  240.         case UFWRITABLE:glob(arg1);
  241.                 return(ltos(!ffronly(arg1)));
  242.     }
  243.     return errorm;
  244. }
  245.  
  246. char *gtusr(vname)    /* look up a user var's value */
  247. char *vname;        /* name of user variable to fetch */
  248. {
  249.  
  250.     register int vnum;    /* ordinal number of user var */
  251.  
  252.     if (!vname[0])
  253.         return (errorm);
  254.  
  255.     /* scan the list looking for the user var name */
  256.     for (vnum = 0; vnum < MAXVARS; vnum++)
  257.         if (strcmp(vname, uv[vnum].u_name) == 0)
  258.             break;
  259.  
  260.     /* return errorm on a bad reference */
  261.     if (vnum == MAXVARS)
  262.         return(errorm);
  263.  
  264.     return(uv[vnum].u_value);
  265. }
  266.  
  267. char *gtenv(vname)
  268. char *vname;        /* name of environment variable to retrieve */
  269. {
  270.     register int vnum;    /* ordinal number of var referenced */
  271. #if X11
  272.     char    *x_current_fontname(); 
  273. #endif
  274.  
  275.     if (!vname[0])
  276.         return (errorm);
  277.  
  278.     /* scan the list, looking for the referenced name */
  279.     for (vnum = 0; vnum < NEVARS; vnum++)
  280.         if (strcmp(vname, envars[vnum]) == 0)
  281.             break;
  282.  
  283.     /* return errorm on a bad reference */
  284.     if (vnum == NEVARS)
  285.         return(errorm);
  286.  
  287.     /* otherwise, fetch the appropriate value */
  288.     switch (vnum) {
  289.         case EVPAGELEN:    return(l_itoa(term.t_nrow + 1));
  290.         case EVCURCOL:    return(l_itoa(getccol(FALSE) + 1));
  291.         case EVCURLINE: return(l_itoa(getcline()));
  292.         case EVRAM:    return(l_itoa((int)(envram / 1024l)));
  293.         case EVFLICKER:    return(ltos(flickcode));
  294.         case EVCURWIDTH:return(l_itoa(term.t_nrow));
  295.         case EVCBUFNAME:return(curbp->b_bname);
  296.         case EVCFNAME:    return(curbp->b_fname);
  297.         case EVSRES:    return(sres);
  298.         case EVDEBUG:    return(ltos(macbug));
  299.         case EVSTATUS:    return(ltos(cmdstatus));
  300.         case EVPALETTE:    return(palstr);
  301.         case EVLASTKEY: return(l_itoa(lastkey));
  302.         case EVCURCHAR:
  303.             return(is_at_end_of_line(DOT) ? l_itoa('\n') :
  304.                 l_itoa(char_at(DOT)));
  305.         case EVDISCMD:    return(ltos(discmd));
  306.         case EVVERSION:    return(version);
  307.         case EVPROGNAME:return(prognam);
  308.         case EVSEED:    return(l_itoa(seed));
  309.         case EVDISINP:    return(ltos(disinp));
  310.         case EVWLINE:    return(l_itoa(curwp->w_ntrows));
  311.         case EVCWLINE:    return(l_itoa(getwpos()));
  312.         case EVSEARCH:    return(pat);
  313.         case EVREPLACE:    return(rpat);
  314.         case EVMATCH:    return((patmatch == NULL)? "": patmatch);
  315.         case EVKILL:    return(getkill());
  316.         case EVTPAUSE:    return(l_itoa(term.t_pause));
  317.         case EVPENDING:
  318. #if    TYPEAH
  319.                 return(ltos(typahead()));
  320. #else
  321.                 return(falsem);
  322. #endif
  323.         case EVLLENGTH:    return(l_itoa(llength(DOT.l)));
  324.         case EVLINE:    return(getctext(0));
  325.         case EVWORD:    return(getctext(_nonspace));
  326.         case EVIDENTIF:    return(getctext(_ident));
  327.         case EVQIDENTIF:return(getctext(_qident));
  328.         case EVPATHNAME:return(getctext(_pathn));
  329.         case EVDIR:    return(current_directory(FALSE));
  330. #if X11
  331.         case EVFONT:    return(x_current_fontname());
  332. #endif
  333.     }
  334.     return errorm;
  335. }
  336.  
  337. char *getkill()        /* return some of the contents of the kill buffer */
  338. {
  339.     register int size;    /* max number of chars to return */
  340.     char value[NSTRING];    /* temp buffer for value */
  341.  
  342.     if (kbs[0].kbufh == NULL)
  343.         /* no kill buffer....just a null string */
  344.         value[0] = 0;
  345.     else {
  346.         /* copy in the contents... */
  347.         if (kbs[0].kused < NSTRING)
  348.             size = kbs[0].kused;
  349.         else
  350.             size = NSTRING - 1;
  351.         strncpy(value, (char *)(kbs[0].kbufh->d_chunk), size);
  352.     }
  353.  
  354.     /* and return the constructed value */
  355.     return(value);
  356. }
  357.  
  358. void
  359. findvar(var, vd)    /* find a variables type and name */
  360. char *var;    /* name of var to get */
  361. VDESC *vd;    /* structure to hold type and ptr */
  362. {
  363.     register int vnum;    /* subscript in variable arrays */
  364.     register int vtype;    /* type to return */
  365.  
  366. fvar:
  367.     vtype = vnum = -1;
  368.     if (!var[1]) {
  369.         vd->v_type = vtype;
  370.         return;
  371.     }
  372.     switch (var[0]) {
  373.  
  374.         case '$': /* check for legal enviromnent var */
  375.             for (vnum = 0; vnum < NEVARS; vnum++)
  376.                 if (strcmp(&var[1], envars[vnum]) == 0) {
  377.                     vtype = TKENV;
  378.                     break;
  379.                 }
  380.             break;
  381.  
  382.         case '%': /* check for existing legal user variable */
  383.             for (vnum = 0; vnum < MAXVARS; vnum++)
  384.                 if (strcmp(&var[1], uv[vnum].u_name) == 0) {
  385.                     vtype = TKVAR;
  386.                     break;
  387.                 }
  388.             if (vnum < MAXVARS)
  389.                 break;
  390.  
  391.             /* create a new one??? */
  392.             for (vnum = 0; vnum < MAXVARS; vnum++)
  393.                 if (uv[vnum].u_name[0] == 0) {
  394.                     vtype = TKVAR;
  395.                     strcpy(uv[vnum].u_name, &var[1]);
  396.                     break;
  397.                 }
  398.             break;
  399.  
  400.         case '&':    /* indirect operator? */
  401.             var[4] = 0;
  402.             if (strcmp(&var[1], "ind") == 0) {
  403.                 /* grab token, and eval it */
  404.                 execstr = token(execstr, var);
  405.                 strcpy(var, tokval(var));
  406.                 goto fvar;
  407.             }
  408.     }
  409.  
  410.     /* return the results */
  411.     vd->v_num = vnum;
  412.     vd->v_type = vtype;
  413. }
  414.  
  415. int 
  416. setvar(f, n)        /* set a variable */
  417. int f;        /* default flag */
  418. int n;        /* numeric arg (can overide prompted value) */
  419. {
  420.     register int status;    /* status return */
  421.     VDESC vd;        /* variable num/type */
  422.     static char var[NVSIZE+1];    /* name of variable to fetch */
  423.     char value[NSTRING];    /* value to set variable to */
  424.  
  425.     /* first get the variable to set.. */
  426.     if (clexec == FALSE) {
  427.         status = mlreply("Variable to set: ", &var[0], NVSIZE);
  428.         if (status != TRUE)
  429.             return(status);
  430.     } else {    /* macro line argument */
  431.         /* grab token and skip it */
  432.         execstr = token(execstr, var);
  433.     }
  434.  
  435.     /* check the legality and find the var */
  436.     findvar(var, &vd);
  437.     
  438.     /* if its not legal....bitch */
  439.     if (vd.v_type == -1) {
  440.         mlforce("[No such variable as '%s']", var);
  441.         return(FALSE);
  442.     }
  443.  
  444.     /* get the value for that variable */
  445.     if (f == TRUE)
  446.         strcpy(value, l_itoa(n));
  447.     else {
  448.         value[0] = 0;
  449.         status = mlreply("Value: ", &value[0], NSTRING);
  450.         if (status != TRUE)
  451.             return(status);
  452.     }
  453.  
  454.     /* and set the appropriate value */
  455.     status = svar(&vd, value);
  456.  
  457. #if    DEBUGM
  458.     /* if $debug == TRUE, every assignment will echo a statment to
  459.        that effect here. */
  460.     
  461.     if (macbug) {
  462.         strcpy(outline, "(((");
  463.  
  464.         /* assignment status */
  465.         strcat(outline, ltos(status));
  466.         strcat(outline, ":");
  467.  
  468.         /* variable name */
  469.         strcat(outline, var);
  470.         strcat(outline, ":");
  471.  
  472.         /* and lastly the value we tried to assign */
  473.         strcat(outline, value);
  474.         strcat(outline, ")))");
  475.  
  476.  
  477.         /* write out the debug line */
  478.         mlforce("%s",outline);
  479.         update(TRUE);
  480.  
  481.         /* and get the keystroke to hold the output */
  482.         if (kbd_key() == abortc) {
  483.             mlforce("[Macro aborted]");
  484.             status = FALSE;
  485.         }
  486.     }
  487. #endif
  488.  
  489.     /* and return it */
  490.     return(status);
  491. }
  492.  
  493. int svar(var, value)        /* set a variable */
  494. VDESC *var;    /* variable to set */
  495. char *value;    /* value to set to */
  496. {
  497.     register int vnum;    /* ordinal number of var referenced */
  498.     register int vtype;    /* type of variable to set */
  499.     register int status;    /* status return */
  500.     register int c;        /* translated character */
  501.     register char * sp;    /* scratch string pointer */
  502.  
  503.     /* simplify the vd structure (we are gonna look at it a lot) */
  504.     vnum = var->v_num;
  505.     vtype = var->v_type;
  506.  
  507.     /* and set the appropriate value */
  508.     status = TRUE;
  509.     switch (vtype) {
  510.     case TKVAR: /* set a user variable */
  511.         if (uv[vnum].u_value != NULL)
  512.             free(uv[vnum].u_value);
  513.         sp = malloc(strlen(value) + 1);
  514.         if (sp == NULL)
  515.             return(FALSE);
  516.         strcpy(sp, value);
  517.         uv[vnum].u_value = sp;
  518.         break;
  519.  
  520.     case TKENV: /* set an environment variable */
  521.         status = TRUE;    /* by default */
  522.         switch (vnum) {
  523.         case EVCURCOL:    status = gotocol(TRUE,atoi(value));
  524.                 break;
  525.         case EVCURLINE:    status = gotoline(TRUE, atoi(value));
  526.                 break;
  527.         case EVFLICKER:    flickcode = stol(value);
  528.                 break;
  529.         case EVCURWIDTH:status = newwidth(TRUE, atoi(value));
  530.                 break;
  531.         case EVPAGELEN:    status = newlength(TRUE,atoi(value));
  532.                 break;
  533.         case EVCBUFNAME:strcpy(curbp->b_bname, value);
  534.                 curwp->w_flag |= WFMODE;
  535.                 break;
  536.         case EVCFNAME:    ch_fname(curbp, value);
  537.                 curwp->w_flag |= WFMODE;
  538.                 break;
  539.         case EVSRES:    status = TTrez(value);
  540.                 break;
  541.         case EVDEBUG:    macbug = stol(value);
  542.                 break;
  543.         case EVSTATUS:    cmdstatus = stol(value);
  544.                 break;
  545.         case EVPALETTE:    strncpy(palstr, value, 48);
  546.                 spal(palstr);
  547.                 break;
  548.         case EVLASTKEY:    lastkey = atoi(value);
  549.                 break;
  550.         case EVCURCHAR:    ldelete(1L, FALSE);    /* delete 1 char */
  551.                 c = atoi(value);
  552.                 if (c == '\n')
  553.                     lnewline();
  554.                 else
  555.                     linsert(1, c);
  556.                 backchar(FALSE, 1);
  557.                 break;
  558.         case EVDISCMD:    discmd = stol(value);
  559.                 break;
  560.         case EVSEED:    seed = atoi(value);
  561.                 break;
  562.         case EVDISINP:    disinp = stol(value);
  563.                 break;
  564.         case EVWLINE:    status = resize(TRUE, atoi(value));
  565.                 break;
  566.         case EVCWLINE:    status = forwline(TRUE,
  567.                         atoi(value) - getwpos());
  568.                 break;
  569.         case EVSEARCH:    strcpy(pat, value);
  570.                 if (gregexp) free((char *)gregexp);
  571.                 gregexp = regcomp(pat, b_val(curbp, MDMAGIC));
  572.                 break;
  573.         case EVREPLACE:    strcpy(rpat, value);
  574.                 break;
  575.         case EVTPAUSE:    term.t_pause = atoi(value);
  576.                 break;
  577.         case EVPROGNAME:
  578.         case EVVERSION:
  579.         case EVMATCH:
  580.         case EVKILL:
  581.         case EVPENDING:
  582.         case EVLLENGTH:
  583.         case EVRAM:    break;
  584.         case EVLINE:    (void)putctext(value);
  585.                 break;
  586.         case EVDIR:    set_directory(value);
  587.                 break;
  588. #if X11
  589.         case EVFONT:    status = x_setfont(value);
  590.                 break;
  591. #endif
  592.         }
  593.         break;
  594.     }
  595.     return(status);
  596. }
  597. #endif
  598.  
  599.  
  600. #if ! SMALLER
  601.  
  602. /*    l_itoa:    integer to ascii string.......... This is too
  603.         inconsistent to use the system's    */
  604.  
  605. char *l_itoa(i)
  606. int i;    /* integer to translate to a string */
  607. {
  608.     static char result[INTWIDTH+1];    /* resulting string */
  609.     lsprintf(result,"%d",i);
  610.     return result;
  611. }
  612. #endif
  613.  
  614. int toktyp(tokn)    /* find the type of a passed token */
  615. char *tokn;    /* token to analyze */
  616. {
  617.  
  618.     /* no blanks!!! */
  619.     if (tokn[0] == '\0')
  620.         return(TKNUL);
  621.  
  622.     /* a numeric literal? */
  623.     if (isdigit(tokn[0]))
  624.         return(TKLIT);
  625.  
  626.     if (tokn[0] == '"')
  627.         return(TKSTR);
  628.  
  629.     /* if it's any other single char, it must be itself */
  630.     if (tokn[1] == '\0')
  631.         return(TKCMD);
  632.  
  633. #if ! SMALLER
  634.     switch (tokn[0]) {
  635.         case '"':    return(TKSTR);
  636.  
  637.         case '~':    return(TKDIR);
  638.         case '@':    return(TKARG);
  639.         case '#':    return(TKBUF);
  640.         case '$':    return(TKENV);
  641.         case '%':    return(TKVAR);
  642.         case '&':    return(TKFUN);
  643.         case '*':    return(TKLBL);
  644.  
  645.         default:    return(TKCMD);
  646.     }
  647. #else
  648.     return(TKCMD);
  649. #endif
  650. }
  651.  
  652. char *
  653. tokval(tokn)    /* find the value of a token */
  654. char *tokn;        /* token to evaluate */
  655. {
  656. #if ! SMALLER
  657.     register int status;    /* error return */
  658.     register BUFFER *bp;    /* temp buffer pointer */
  659.     register int blen;    /* length of buffer argument */
  660.     register int distmp;    /* temporary discmd flag */
  661.     int    oclexec;
  662.     static char buf[NSTRING];/* string buffer for some returns */
  663.  
  664.     switch (toktyp(tokn)) {
  665.         case TKNUL:    return("");
  666.  
  667.         case TKARG:    /* interactive argument */
  668.                 oclexec = clexec;
  669.  
  670.                 /* clexec = FALSE; * in cline execution - added pjr */
  671.  
  672.                 strcpy(tokn, tokval(&tokn[1]));
  673.                 distmp = discmd;    /* echo it always! */
  674.                 discmd = TRUE;
  675.                 clexec = FALSE;
  676.                 buf[0] = 0;
  677.                 status = kbd_string(tokn,
  678.                        buf, NSTRING, '\n',EXPAND,TRUE);
  679.                 discmd = distmp;
  680.                 clexec = oclexec;
  681.  
  682.                 if (status == ABORT)
  683.                     return(errorm);
  684.                 return(buf);
  685.  
  686.         case TKBUF:    /* buffer contents fetch */
  687.  
  688.                 /* grab the right buffer */
  689.                 strcpy(tokn, tokval(&tokn[1]));
  690.                 bp = bfind(tokn, NO_CREAT, 0);
  691.                 if (bp == NULL)
  692.                     return(errorm);
  693.         
  694.                 /* if the buffer is displayed, get the window
  695.                    vars instead of the buffer vars */
  696.                 if (bp->b_nwnd > 0) {
  697.                     curbp->b_dot = curwp->w_dot;
  698.                 }
  699.  
  700.                 /* make sure we are not at the end */
  701.                 if (is_header_line(bp->b_dot,bp))
  702.                     return(errorm);
  703.         
  704.                 /* grab the line as an argument */
  705.                 blen = llength(bp->b_dot.l) - bp->b_dot.o;
  706.                 if (blen > NSTRING)
  707.                     blen = NSTRING;
  708.                 strncpy(buf, bp->b_dot.l->l_text + bp->b_dot.o,
  709.                     blen);
  710.                 buf[blen] = 0;
  711.         
  712.                 /* and step the buffer's line ptr 
  713.                     ahead a line */
  714.                 bp->b_dot.l = lforw(bp->b_dot.l);
  715.                 bp->b_dot.o = 0;
  716.  
  717.                 /* if displayed buffer, reset window ptr vars*/
  718.                 if (bp->b_nwnd > 0) {
  719.                     curwp->w_dot.l = curbp->b_dot.l;
  720.                     curwp->w_dot.o = 0;
  721.                     curwp->w_flag |= WFMOVE;
  722.                 }
  723.  
  724.                 /* and return the spoils */
  725.                 return(buf);        
  726.  
  727.         case TKVAR:    return(gtusr(tokn+1));
  728.         case TKENV:    return(gtenv(tokn+1));
  729.         case TKFUN:    return(gtfun(tokn+1));
  730.         case TKDIR:    return(errorm);
  731.         case TKLBL:    return(l_itoa(gtlbl(tokn)));
  732.         case TKLIT:    return(tokn);
  733.         case TKSTR:    return(tokn+1);
  734.         case TKCMD:    return(tokn);
  735.     }
  736.     return errorm;
  737. #else
  738.     return tokn;
  739. #endif
  740. }
  741.  
  742. #if ! SMALLER
  743.  
  744. /* ARGSUSED */
  745. int
  746. gtlbl(tokn)    /* find the line number of the given label */
  747. char *tokn;    /* label name to find */
  748. {
  749.     return(1);
  750. }
  751.  
  752. int stol(val)    /* convert a string to a numeric logical */
  753. char *val;    /* value to check for stol */
  754. {
  755.     /* check for logical values */
  756.     if (val[0] == 'F' || val[0] == 'f')
  757.         return(FALSE);
  758.     if (val[0] == 'T' || val[0] == 't')
  759.         return(TRUE);
  760.  
  761.     /* check for numeric truth (!= 0) */
  762.     return((atoi(val) != 0));
  763. }
  764.  
  765. char *ltos(val)        /* numeric logical to string logical */
  766. int val;    /* value to translate */
  767. {
  768.     if (val)
  769.         return(truem);
  770.     else
  771.         return(falsem);
  772. }
  773.  
  774. char *mkupper(str)    /* make a string upper case */
  775. char *str;        /* string to upper case */
  776. {
  777.     char *sp;
  778.  
  779.     sp = str;
  780.     while (*sp) {
  781.         if (islower(*sp))
  782.             *sp += 'A' - 'a';
  783.         ++sp;
  784.     }
  785.     return(str);
  786. }
  787. #endif
  788.  
  789. #if ! SMALLER || MSDOS
  790.  
  791. char *mklower(str)    /* make a string lower case */
  792. char *str;        /* string to lower case */
  793. {
  794.     char *sp;
  795.  
  796.     sp = str;
  797.     while (*sp) {
  798.         if (isupper(*sp))
  799.             *sp += 'a' - 'A';
  800.         ++sp;
  801.     }
  802.     return(str);
  803. }
  804. #endif
  805.  
  806. #if ! SMALLER
  807.  
  808. int absol(x)    /* take the absolute value of an integer */
  809. int x;
  810. {
  811.     return(x < 0 ? -x : x);
  812. }
  813.  
  814. int ernd()    /* returns a random integer */
  815. {
  816.     seed = absol(seed * 1721 + 10007);
  817.     return(seed);
  818. }
  819.  
  820. int sindex(sourc, pattern)    /* find pattern within source */
  821. char *sourc;    /* source string to search */
  822. char *pattern;    /* string to look for */
  823. {
  824.     char *sp;    /* ptr to current position to scan */
  825.     char *csp;    /* ptr to source string during comparison */
  826.     char *cp;    /* ptr to place to check for equality */
  827.  
  828.     /* scanning through the source string */
  829.     sp = sourc;
  830.     while (*sp) {
  831.         /* scan through the pattern */
  832.         cp = pattern;
  833.         csp = sp;
  834.         while (*cp) {
  835.             if (!eq(*cp, *csp))
  836.                 break;
  837.             ++cp;
  838.             ++csp;
  839.         }
  840.  
  841.         /* was it a match? */
  842.         if (*cp == 0)
  843.             return((int)(sp - sourc) + 1);
  844.         ++sp;
  845.     }
  846.  
  847.     /* no match at all.. */
  848.     return(0);
  849. }
  850.  
  851. #endif
  852.