| /* 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 "line.h" |
| #include "util.h" |
| #include "version.h" |
| |
| #define MAXVARS 255 |
| |
| /* User variables */ |
| static struct user_variable uv[MAXVARS + 1]; |
| |
| /* 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 |
| struct variable_description 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. |
| * |
| * @var: name of variable to get. |
| * @vd: structure to hold type and pointer. |
| * @size: size of variable array. |
| */ |
| void findvar(char *var, struct variable_description *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. |
| * |
| * @var: variable to set. |
| * @value: value to set to. |
| */ |
| int svar(struct variable_description *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 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; |
| } |