| /* eval.c |
| * |
| * Expression evaluation functions |
| * |
| * written 1986 by Daniel Lawrence |
| * modified by Petri Kutvonen |
| */ |
| |
| #include <stdio.h> |
| #include "estruct.h" |
| #include "edef.h" |
| #include "efunc.h" |
| #include "evar.h" |
| #include "util.h" |
| #include "version.h" |
| |
| /* Initialize the user variable list. */ |
| void varinit(void) |
| { |
| int i; |
| for (i = 0; i < MAXVARS; i++) |
| uv[i].u_name[0] = 0; |
| } |
| |
| /* |
| * Evaluate a function. |
| * |
| * @fname: name of function to evaluate. |
| */ |
| char *gtfun(char *fname) |
| { |
| int fnum; /* index to function to eval */ |
| int status; /* return status */ |
| char *tsp; /* temporary string pointer */ |
| char arg1[NSTRING]; /* value of first argument */ |
| char arg2[NSTRING]; /* value of second argument */ |
| char arg3[NSTRING]; /* value of third argument */ |
| static char result[2 * NSTRING]; /* string result */ |
| |
| /* look the function up in the function table */ |
| fname[3] = 0; /* only first 3 chars significant */ |
| mklower(fname); /* and let it be upper or lower case */ |
| for (fnum = 0; fnum < ARRAY_SIZE(funcs); fnum++) |
| if (strcmp(fname, funcs[fnum].f_name) == 0) |
| break; |
| |
| /* return errorm on a bad reference */ |
| if (fnum == ARRAY_SIZE(funcs)) |
| return (errorm); |
| |
| /* if needed, retrieve the first argument */ |
| if (funcs[fnum].f_type >= MONAMIC) { |
| if ((status = macarg(arg1)) != TRUE) |
| return (errorm); |
| |
| /* if needed, retrieve the second argument */ |
| if (funcs[fnum].f_type >= DYNAMIC) { |
| if ((status = macarg(arg2)) != TRUE) |
| return (errorm); |
| |
| /* if needed, retrieve the third argument */ |
| if (funcs[fnum].f_type >= TRINAMIC) |
| if ((status = macarg(arg3)) != TRUE) |
| return (errorm); |
| } |
| } |
| |
| |
| /* and now evaluate it! */ |
| switch (fnum) { |
| case UFADD: |
| return (itoa(atoi(arg1) + atoi(arg2))); |
| case UFSUB: |
| return (itoa(atoi(arg1) - atoi(arg2))); |
| case UFTIMES: |
| return (itoa(atoi(arg1) * atoi(arg2))); |
| case UFDIV: |
| return (itoa(atoi(arg1) / atoi(arg2))); |
| case UFMOD: |
| return (itoa(atoi(arg1) % atoi(arg2))); |
| case UFNEG: |
| return (itoa(-atoi(arg1))); |
| case UFCAT: |
| strcpy(result, arg1); |
| return (strcat(result, arg2)); |
| case UFLEFT: |
| return (strncpy(result, arg1, atoi(arg2))); |
| case UFRIGHT: |
| return (strcpy(result, |
| &arg1[(strlen(arg1) - atoi(arg2))])); |
| case UFMID: |
| return (strncpy(result, &arg1[atoi(arg2) - 1], |
| atoi(arg3))); |
| case UFNOT: |
| return (ltos(stol(arg1) == FALSE)); |
| case UFEQUAL: |
| return (ltos(atoi(arg1) == atoi(arg2))); |
| case UFLESS: |
| return (ltos(atoi(arg1) < atoi(arg2))); |
| case UFGREATER: |
| return (ltos(atoi(arg1) > atoi(arg2))); |
| case UFSEQUAL: |
| return (ltos(strcmp(arg1, arg2) == 0)); |
| case UFSLESS: |
| return (ltos(strcmp(arg1, arg2) < 0)); |
| case UFSGREAT: |
| return (ltos(strcmp(arg1, arg2) > 0)); |
| case UFIND: |
| return (strcpy(result, getval(arg1))); |
| case UFAND: |
| return (ltos(stol(arg1) && stol(arg2))); |
| case UFOR: |
| return (ltos(stol(arg1) || stol(arg2))); |
| case UFLENGTH: |
| return (itoa(strlen(arg1))); |
| case UFUPPER: |
| return (mkupper(arg1)); |
| case UFLOWER: |
| return (mklower(arg1)); |
| case UFTRUTH: |
| return (ltos(atoi(arg1) == 42)); |
| case UFASCII: |
| return (itoa((int) arg1[0])); |
| case UFCHR: |
| result[0] = atoi(arg1); |
| result[1] = 0; |
| return (result); |
| case UFGTKEY: |
| result[0] = tgetc(); |
| result[1] = 0; |
| return (result); |
| case UFRND: |
| return (itoa((ernd() % abs(atoi(arg1))) + 1)); |
| case UFABS: |
| return (itoa(abs(atoi(arg1)))); |
| case UFSINDEX: |
| return (itoa(sindex(arg1, arg2))); |
| case UFENV: |
| #if ENVFUNC |
| tsp = getenv(arg1); |
| return (tsp == NULL ? "" : tsp); |
| #else |
| return (""); |
| #endif |
| case UFBIND: |
| return (transbind(arg1)); |
| case UFEXIST: |
| return (ltos(fexist(arg1))); |
| case UFFIND: |
| tsp = flook(arg1, TRUE); |
| return (tsp == NULL ? "" : tsp); |
| case UFBAND: |
| return (itoa(atoi(arg1) & atoi(arg2))); |
| case UFBOR: |
| return (itoa(atoi(arg1) | atoi(arg2))); |
| case UFBXOR: |
| return (itoa(atoi(arg1) ^ atoi(arg2))); |
| case UFBNOT: |
| return (itoa(~atoi(arg1))); |
| case UFXLATE: |
| return (xlat(arg1, arg2, arg3)); |
| } |
| |
| exit(-11); /* never should get here */ |
| } |
| |
| /* |
| * look up a user var's value |
| * |
| * char *vname; name of user variable to fetch |
| */ |
| char *gtusr(char *vname) |
| { |
| |
| int vnum; /* ordinal number of user var */ |
| |
| /* scan the list looking for the user var name */ |
| for (vnum = 0; vnum < MAXVARS; vnum++) { |
| if (uv[vnum].u_name[0] == 0) |
| return (errorm); |
| if (strcmp(vname, uv[vnum].u_name) == 0) |
| return (uv[vnum].u_value); |
| } |
| |
| /* return errorm if we run off the end */ |
| return (errorm); |
| } |
| |
| extern char *getkill(void); |
| |
| /* |
| * gtenv() |
| * |
| * char *vname; name of environment variable to retrieve |
| */ |
| char *gtenv(char *vname) |
| { |
| int vnum; /* ordinal number of var refrenced */ |
| |
| /* scan the list, looking for the referenced name */ |
| for (vnum = 0; vnum < ARRAY_SIZE(envars); vnum++) |
| if (strcmp(vname, envars[vnum]) == 0) |
| break; |
| |
| /* return errorm on a bad reference */ |
| if (vnum == ARRAY_SIZE(envars)) |
| #if ENVFUNC |
| { |
| char *ename = getenv(vname); |
| |
| if (ename != NULL) |
| return (ename); |
| else |
| return (errorm); |
| } |
| #else |
| return (errorm); |
| #endif |
| |
| /* otherwise, fetch the appropriate value */ |
| switch (vnum) { |
| case EVFILLCOL: |
| return (itoa(fillcol)); |
| case EVPAGELEN: |
| return (itoa(term.t_nrow + 1)); |
| case EVCURCOL: |
| return (itoa(getccol(FALSE))); |
| case EVCURLINE: |
| return (itoa(getcline())); |
| case EVRAM: |
| return (itoa((int) (envram / 1024l))); |
| case EVFLICKER: |
| return (ltos(flickcode)); |
| case EVCURWIDTH: |
| return (itoa(term.t_ncol)); |
| case EVCBUFNAME: |
| return (curbp->b_bname); |
| case EVCFNAME: |
| return (curbp->b_fname); |
| case EVSRES: |
| return (sres); |
| case EVDEBUG: |
| return (ltos(macbug)); |
| case EVSTATUS: |
| return (ltos(cmdstatus)); |
| case EVPALETTE: |
| return (palstr); |
| case EVASAVE: |
| return (itoa(gasave)); |
| case EVACOUNT: |
| return (itoa(gacount)); |
| case EVLASTKEY: |
| return (itoa(lastkey)); |
| case EVCURCHAR: |
| return (curwp->w_dotp->l_used == |
| curwp->w_doto ? itoa('\n') : |
| itoa(lgetc(curwp->w_dotp, curwp->w_doto))); |
| case EVDISCMD: |
| return (ltos(discmd)); |
| case EVVERSION: |
| return (VERSION); |
| case EVPROGNAME: |
| return (PROGRAM_NAME_LONG); |
| case EVSEED: |
| return (itoa(seed)); |
| case EVDISINP: |
| return (ltos(disinp)); |
| case EVWLINE: |
| return (itoa(curwp->w_ntrows)); |
| case EVCWLINE: |
| return (itoa(getwpos())); |
| case EVTARGET: |
| saveflag = lastflag; |
| return (itoa(curgoal)); |
| case EVSEARCH: |
| return (pat); |
| case EVREPLACE: |
| return (rpat); |
| case EVMATCH: |
| return ((patmatch == NULL) ? "" : patmatch); |
| case EVKILL: |
| return (getkill()); |
| case EVCMODE: |
| return (itoa(curbp->b_mode)); |
| case EVGMODE: |
| return (itoa(gmode)); |
| case EVTPAUSE: |
| return (itoa(term.t_pause)); |
| case EVPENDING: |
| #if TYPEAH |
| return (ltos(typahead())); |
| #else |
| return (falsem); |
| #endif |
| case EVLWIDTH: |
| return (itoa(llength(curwp->w_dotp))); |
| case EVLINE: |
| return (getctext()); |
| case EVGFLAGS: |
| return (itoa(gflags)); |
| case EVRVAL: |
| return (itoa(rval)); |
| case EVTAB: |
| return (itoa(tabmask + 1)); |
| case EVOVERLAP: |
| return (itoa(overlap)); |
| case EVSCROLLCOUNT: |
| return (itoa(scrollcount)); |
| #if SCROLLCODE |
| case EVSCROLL: |
| return (ltos(term.t_scroll != NULL)); |
| #else |
| case EVSCROLL: |
| return (ltos(0)); |
| #endif |
| } |
| exit(-12); /* again, we should never get here */ |
| } |
| |
| /* |
| * return some of the contents of the kill buffer |
| */ |
| char *getkill(void) |
| { |
| int size; /* max number of chars to return */ |
| static char value[NSTRING]; /* temp buffer for value */ |
| |
| if (kbufh == NULL) |
| /* no kill buffer....just a null string */ |
| value[0] = 0; |
| else { |
| /* copy in the contents... */ |
| if (kused < NSTRING) |
| size = kused; |
| else |
| size = NSTRING - 1; |
| strncpy(value, kbufh->d_chunk, size); |
| } |
| |
| /* and return the constructed value */ |
| return (value); |
| } |
| |
| /* |
| * set a variable |
| * |
| * int f; default flag |
| * int n; numeric arg (can overide prompted value) |
| */ |
| int setvar(int f, int n) |
| { |
| int status; /* status return */ |
| #if DEBUGM |
| char *sp; /* temp string pointer */ |
| char *ep; /* ptr to end of outline */ |
| #endif |
| VDESC vd; /* variable num/type */ |
| char var[NVSIZE + 1]; /* name of variable to fetch */ |
| char value[NSTRING]; /* value to set variable to */ |
| |
| /* first get the variable to set.. */ |
| if (clexec == FALSE) { |
| status = mlreply("Variable to set: ", &var[0], NVSIZE); |
| if (status != TRUE) |
| return (status); |
| } else { /* macro line argument */ |
| /* grab token and skip it */ |
| execstr = token(execstr, var, NVSIZE + 1); |
| } |
| |
| /* check the legality and find the var */ |
| findvar(var, &vd, NVSIZE + 1); |
| |
| /* if its not legal....bitch */ |
| if (vd.v_type == -1) { |
| mlwrite("%%No such variable as '%s'", var); |
| return (FALSE); |
| } |
| |
| /* get the value for that variable */ |
| if (f == TRUE) |
| strcpy(value, itoa(n)); |
| else { |
| status = mlreply("Value: ", &value[0], NSTRING); |
| if (status != TRUE) |
| return (status); |
| } |
| |
| /* and set the appropriate value */ |
| status = svar(&vd, value); |
| |
| #if DEBUGM |
| /* if $debug == TRUE, every assignment will echo a statment to |
| that effect here. */ |
| |
| if (macbug) { |
| strcpy(outline, "((("); |
| |
| /* assignment status */ |
| strcat(outline, ltos(status)); |
| strcat(outline, ":"); |
| |
| /* variable name */ |
| strcat(outline, var); |
| strcat(outline, ":"); |
| |
| /* and lastly the value we tried to assign */ |
| strcat(outline, value); |
| strcat(outline, ")))"); |
| |
| /* expand '%' to "%%" so mlwrite wont bitch */ |
| sp = outline; |
| while (*sp) |
| if (*sp++ == '%') { |
| /* advance to the end */ |
| ep = --sp; |
| while (*ep++); |
| /* null terminate the string one out */ |
| *(ep + 1) = 0; |
| /* copy backwards */ |
| while (ep-- > sp) |
| *(ep + 1) = *ep; |
| |
| /* and advance sp past the new % */ |
| sp += 2; |
| } |
| |
| /* write out the debug line */ |
| mlforce(outline); |
| update(TRUE); |
| |
| /* and get the keystroke to hold the output */ |
| if (get1key() == abortc) { |
| mlforce("(Macro aborted)"); |
| status = FALSE; |
| } |
| } |
| #endif |
| |
| /* and return it */ |
| return (status); |
| } |
| |
| /* |
| * find a variables type and name |
| * |
| * char *var; name of var to get |
| * VDESC *vd; structure to hold type and ptr |
| * int size; size of var array |
| */ |
| void findvar(char *var, VDESC *vd, int size) |
| { |
| int vnum; /* subscript in variable arrays */ |
| int vtype; /* type to return */ |
| |
| vnum = -1; |
| fvar: |
| vtype = -1; |
| switch (var[0]) { |
| |
| case '$': /* check for legal enviromnent var */ |
| for (vnum = 0; vnum < ARRAY_SIZE(envars); vnum++) |
| if (strcmp(&var[1], envars[vnum]) == 0) { |
| vtype = TKENV; |
| break; |
| } |
| break; |
| |
| case '%': /* check for existing legal user variable */ |
| for (vnum = 0; vnum < MAXVARS; vnum++) |
| if (strcmp(&var[1], uv[vnum].u_name) == 0) { |
| vtype = TKVAR; |
| break; |
| } |
| if (vnum < MAXVARS) |
| break; |
| |
| /* create a new one??? */ |
| for (vnum = 0; vnum < MAXVARS; vnum++) |
| if (uv[vnum].u_name[0] == 0) { |
| vtype = TKVAR; |
| strcpy(uv[vnum].u_name, &var[1]); |
| break; |
| } |
| break; |
| |
| case '&': /* indirect operator? */ |
| var[4] = 0; |
| if (strcmp(&var[1], "ind") == 0) { |
| /* grab token, and eval it */ |
| execstr = token(execstr, var, size); |
| strcpy(var, getval(var)); |
| goto fvar; |
| } |
| } |
| |
| /* return the results */ |
| vd->v_num = vnum; |
| vd->v_type = vtype; |
| return; |
| } |
| |
| /* |
| * set a variable |
| * |
| * VDESC *var; variable to set |
| * char *value; value to set to |
| */ |
| int svar(VDESC *var, char *value) |
| { |
| int vnum; /* ordinal number of var refrenced */ |
| int vtype; /* type of variable to set */ |
| int status; /* status return */ |
| int c; /* translated character */ |
| char *sp; /* scratch string pointer */ |
| |
| /* simplify the vd structure (we are gonna look at it a lot) */ |
| vnum = var->v_num; |
| vtype = var->v_type; |
| |
| /* and set the appropriate value */ |
| status = TRUE; |
| switch (vtype) { |
| case TKVAR: /* set a user variable */ |
| if (uv[vnum].u_value != NULL) |
| free(uv[vnum].u_value); |
| sp = malloc(strlen(value) + 1); |
| if (sp == NULL) |
| return (FALSE); |
| strcpy(sp, value); |
| uv[vnum].u_value = sp; |
| break; |
| |
| case TKENV: /* set an environment variable */ |
| status = TRUE; /* by default */ |
| switch (vnum) { |
| case EVFILLCOL: |
| fillcol = atoi(value); |
| break; |
| case EVPAGELEN: |
| status = newsize(TRUE, atoi(value)); |
| break; |
| case EVCURCOL: |
| status = setccol(atoi(value)); |
| break; |
| case EVCURLINE: |
| status = gotoline(TRUE, atoi(value)); |
| break; |
| case EVRAM: |
| break; |
| case EVFLICKER: |
| flickcode = stol(value); |
| break; |
| case EVCURWIDTH: |
| status = newwidth(TRUE, atoi(value)); |
| break; |
| case EVCBUFNAME: |
| strcpy(curbp->b_bname, value); |
| curwp->w_flag |= WFMODE; |
| break; |
| case EVCFNAME: |
| strcpy(curbp->b_fname, value); |
| curwp->w_flag |= WFMODE; |
| break; |
| case EVSRES: |
| status = TTrez(value); |
| break; |
| case EVDEBUG: |
| macbug = stol(value); |
| break; |
| case EVSTATUS: |
| cmdstatus = stol(value); |
| break; |
| case EVPALETTE: |
| strncpy(palstr, value, 48); |
| spal(palstr); |
| break; |
| case EVASAVE: |
| gasave = atoi(value); |
| break; |
| case EVACOUNT: |
| gacount = atoi(value); |
| break; |
| case EVLASTKEY: |
| lastkey = atoi(value); |
| break; |
| case EVCURCHAR: |
| ldelete(1L, FALSE); /* delete 1 char */ |
| c = atoi(value); |
| if (c == '\n') |
| lnewline(); |
| else |
| linsert(1, c); |
| backchar(FALSE, 1); |
| break; |
| case EVDISCMD: |
| discmd = stol(value); |
| break; |
| case EVVERSION: |
| break; |
| case EVPROGNAME: |
| break; |
| case EVSEED: |
| seed = atoi(value); |
| break; |
| case EVDISINP: |
| disinp = stol(value); |
| break; |
| case EVWLINE: |
| status = resize(TRUE, atoi(value)); |
| break; |
| case EVCWLINE: |
| status = forwline(TRUE, atoi(value) - getwpos()); |
| break; |
| case EVTARGET: |
| curgoal = atoi(value); |
| thisflag = saveflag; |
| break; |
| case EVSEARCH: |
| strcpy(pat, value); |
| rvstrcpy(tap, pat); |
| #if MAGIC |
| mcclear(); |
| #endif |
| break; |
| case EVREPLACE: |
| strcpy(rpat, value); |
| break; |
| case EVMATCH: |
| break; |
| case EVKILL: |
| break; |
| case EVCMODE: |
| curbp->b_mode = atoi(value); |
| curwp->w_flag |= WFMODE; |
| break; |
| case EVGMODE: |
| gmode = atoi(value); |
| break; |
| case EVTPAUSE: |
| term.t_pause = atoi(value); |
| break; |
| case EVPENDING: |
| break; |
| case EVLWIDTH: |
| break; |
| case EVLINE: |
| putctext(value); |
| case EVGFLAGS: |
| gflags = atoi(value); |
| break; |
| case EVRVAL: |
| break; |
| case EVTAB: |
| tabmask = atoi(value) - 1; |
| if (tabmask != 0x07 && tabmask != 0x03) |
| tabmask = 0x07; |
| curwp->w_flag |= WFHARD; |
| break; |
| case EVOVERLAP: |
| overlap = atoi(value); |
| break; |
| case EVSCROLLCOUNT: |
| scrollcount = atoi(value); |
| break; |
| case EVSCROLL: |
| #if SCROLLCODE |
| if (!stol(value)) |
| term.t_scroll = NULL; |
| #endif |
| break; |
| } |
| break; |
| } |
| return (status); |
| } |
| |
| /* |
| * itoa: |
| * integer to ascii string.......... This is too |
| * inconsistant to use the system's |
| * |
| * int i; integer to translate to a string |
| */ |
| char *itoa(int i) |
| { |
| int digit; /* current digit being used */ |
| char *sp; /* pointer into result */ |
| int sign; /* sign of resulting number */ |
| static char result[INTWIDTH + 1]; /* resulting string */ |
| |
| /* record the sign... */ |
| sign = 1; |
| if (i < 0) { |
| sign = -1; |
| i = -i; |
| } |
| |
| /* and build the string (backwards!) */ |
| sp = result + INTWIDTH; |
| *sp = 0; |
| do { |
| digit = i % 10; |
| *(--sp) = '0' + digit; /* and install the new digit */ |
| i = i / 10; |
| } while (i); |
| |
| /* and fix the sign */ |
| if (sign == -1) { |
| *(--sp) = '-'; /* and install the minus sign */ |
| } |
| |
| return (sp); |
| } |
| |
| /* |
| * find the type of a passed token |
| * |
| * char *token; token to analyze |
| */ |
| int gettyp(char *token) |
| { |
| char c; /* first char in token */ |
| |
| /* grab the first char (this is all we need) */ |
| c = *token; |
| |
| /* no blanks!!! */ |
| if (c == 0) |
| return (TKNUL); |
| |
| /* a numeric literal? */ |
| if (c >= '0' && c <= '9') |
| return (TKLIT); |
| |
| switch (c) { |
| case '"': |
| return (TKSTR); |
| |
| case '!': |
| return (TKDIR); |
| case '@': |
| return (TKARG); |
| case '#': |
| return (TKBUF); |
| case '$': |
| return (TKENV); |
| case '%': |
| return (TKVAR); |
| case '&': |
| return (TKFUN); |
| case '*': |
| return (TKLBL); |
| |
| default: |
| return (TKCMD); |
| } |
| } |
| |
| /* |
| * find the value of a token |
| * |
| * char *token; token to evaluate |
| */ |
| char *getval(char *token) |
| { |
| int status; /* error return */ |
| struct buffer *bp; /* temp buffer pointer */ |
| int blen; /* length of buffer argument */ |
| int distmp; /* temporary discmd flag */ |
| static char buf[NSTRING]; /* string buffer for some returns */ |
| |
| switch (gettyp(token)) { |
| case TKNUL: |
| return (""); |
| |
| case TKARG: /* interactive argument */ |
| strcpy(token, getval(&token[1])); |
| distmp = discmd; /* echo it always! */ |
| discmd = TRUE; |
| status = getstring(token, buf, NSTRING, ctoec('\n')); |
| discmd = distmp; |
| if (status == ABORT) |
| return (errorm); |
| return (buf); |
| |
| case TKBUF: /* buffer contents fetch */ |
| |
| /* grab the right buffer */ |
| strcpy(token, getval(&token[1])); |
| bp = bfind(token, FALSE, 0); |
| if (bp == NULL) |
| return (errorm); |
| |
| /* if the buffer is displayed, get the window |
| vars instead of the buffer vars */ |
| if (bp->b_nwnd > 0) { |
| curbp->b_dotp = curwp->w_dotp; |
| curbp->b_doto = curwp->w_doto; |
| } |
| |
| /* make sure we are not at the end */ |
| if (bp->b_linep == bp->b_dotp) |
| return (errorm); |
| |
| /* grab the line as an argument */ |
| blen = bp->b_dotp->l_used - bp->b_doto; |
| if (blen > NSTRING) |
| blen = NSTRING; |
| strncpy(buf, bp->b_dotp->l_text + bp->b_doto, blen); |
| buf[blen] = 0; |
| |
| /* and step the buffer's line ptr ahead a line */ |
| bp->b_dotp = bp->b_dotp->l_fp; |
| bp->b_doto = 0; |
| |
| /* if displayed buffer, reset window ptr vars */ |
| if (bp->b_nwnd > 0) { |
| curwp->w_dotp = curbp->b_dotp; |
| curwp->w_doto = 0; |
| curwp->w_flag |= WFMOVE; |
| } |
| |
| /* and return the spoils */ |
| return (buf); |
| |
| case TKVAR: |
| return (gtusr(token + 1)); |
| case TKENV: |
| return (gtenv(token + 1)); |
| case TKFUN: |
| return (gtfun(token + 1)); |
| case TKDIR: |
| return (errorm); |
| case TKLBL: |
| return (errorm); |
| case TKLIT: |
| return (token); |
| case TKSTR: |
| return (token + 1); |
| case TKCMD: |
| return (token); |
| } |
| return (errorm); |
| } |
| |
| /* |
| * convert a string to a numeric logical |
| * |
| * char *val; value to check for stol |
| */ |
| int stol(char *val) |
| { |
| /* check for logical values */ |
| if (val[0] == 'F') |
| return (FALSE); |
| if (val[0] == 'T') |
| return (TRUE); |
| |
| /* check for numeric truth (!= 0) */ |
| return ((atoi(val) != 0)); |
| } |
| |
| /* |
| * numeric logical to string logical |
| * |
| * int val; value to translate |
| */ |
| char *ltos(int val) |
| { |
| if (val) |
| return (truem); |
| else |
| return (falsem); |
| } |
| |
| /* |
| * make a string upper case |
| * |
| * char *str; string to upper case |
| */ |
| char *mkupper(char *str) |
| { |
| char *sp; |
| |
| sp = str; |
| while (*sp) { |
| if ('a' <= *sp && *sp <= 'z') |
| *sp += 'A' - 'a'; |
| ++sp; |
| } |
| return (str); |
| } |
| |
| /* |
| * make a string lower case |
| * |
| * char *str; string to lower case |
| */ |
| char *mklower(char *str) |
| { |
| char *sp; |
| |
| sp = str; |
| while (*sp) { |
| if ('A' <= *sp && *sp <= 'Z') |
| *sp += 'a' - 'A'; |
| ++sp; |
| } |
| return (str); |
| } |
| |
| /* |
| * take the absolute value of an integer |
| */ |
| int abs(int x) |
| { |
| return (x < 0 ? -x : x); |
| } |
| |
| /* |
| * returns a random integer |
| */ |
| int ernd(void) |
| { |
| seed = abs(seed * 1721 + 10007); |
| return (seed); |
| } |
| |
| /* |
| * find pattern within source |
| * |
| * char *source; source string to search |
| * char *pattern; string to look for |
| */ |
| int sindex(char *source, char *pattern) |
| { |
| char *sp; /* ptr to current position to scan */ |
| char *csp; /* ptr to source string during comparison */ |
| char *cp; /* ptr to place to check for equality */ |
| |
| /* scanning through the source string */ |
| sp = source; |
| while (*sp) { |
| /* scan through the pattern */ |
| cp = pattern; |
| csp = sp; |
| while (*cp) { |
| if (!eq(*cp, *csp)) |
| break; |
| ++cp; |
| ++csp; |
| } |
| |
| /* was it a match? */ |
| if (*cp == 0) |
| return ((int) (sp - source) + 1); |
| ++sp; |
| } |
| |
| /* no match at all.. */ |
| return (0); |
| } |
| |
| /* |
| * Filter a string through a translation table |
| * |
| * char *source; string to filter |
| * char *lookup; characters to translate |
| * char *trans; resulting translated characters |
| */ |
| char *xlat(char *source, char *lookup, char *trans) |
| { |
| char *sp; /* pointer into source table */ |
| char *lp; /* pointer into lookup table */ |
| char *rp; /* pointer into result */ |
| static char result[NSTRING]; /* temporary result */ |
| |
| /* scan source string */ |
| sp = source; |
| rp = result; |
| while (*sp) { |
| /* scan lookup table for a match */ |
| lp = lookup; |
| while (*lp) { |
| if (*sp == *lp) { |
| *rp++ = trans[lp - lookup]; |
| goto xnext; |
| } |
| ++lp; |
| } |
| |
| /* no match, copy in the source char untranslated */ |
| *rp++ = *sp; |
| |
| xnext:++sp; |
| } |
| |
| /* terminate and return the result */ |
| *rp = 0; |
| return (result); |
| } |