home *** CD-ROM | disk | FTP | other *** search
- /* interpret.c */
- /**********************************************************************
- * File Name : interpret.c
- * Function : pac calculator input tokenizer
- * Author : Istvan Mohos, 1987
- ***********************************************************************/
-
- #include "defs.h"
- #include "toktab.h"
- #define INTERMAP
- #include "maps.h"
- #undef INTERMAP
-
- #define HIDE_RES Hide = 1; rh = Stack; Stack = DISA; \
- prec = Precision; Precision = 32; show_result(1); \
- Hide = 0; Stack = rh; Precision = prec
- #define RECOVER conv_bc(sr->cell, ZERO, 1, 0); addto_ubuf(Convbuf)
-
- interpret(source)
- char *source;
- {
- char *eye, *nxeye;
- char *ip, itemp[LINEMAX];
- char stacbuf[PIPEMAX];
- int ri, rh, prec;
- int cur_cnt = 0;
- int type, value, nex_type;
- int first; /* so conversion can refer to Mainbuf */
- int conv_flag; /* to show that TO has taken place */
- char c_val;
- static char onechar[2];
- static struct stk_cell *sr = &Stk[0];
- static char *fid = "interpret";
-
- _TR
-
- #ifdef TOX
- static char Tk[100];
- char *tk = &Tk[0];
- #endif
-
-
- /* transfer raw characters from user window to Spreadbuf,
- insert spaces between all but contiguous alphanumeric characters
- to prepare for pactok */
- fill_spreadbuf(source);
-
- /* strip spaces and commas, null terminate tokens */
- place_pointers();
- *Ubuf = '\0';
- *Controlbuf = '\0';
- first = TRUE;
- conv_flag = FALSE;
-
- while ((eye = Tokp[++cur_cnt]) != ZERO) {
- type = lookup(eye);
-
- if ((nxeye = Tokp[cur_cnt + 1]) != ZERO)
- nex_type = lookup(nxeye);
- else
- nex_type = -1;
-
- #ifdef TOX
- sprintf(tk, "%d,", type);
- tk = Tk + strlen(Tk);
- #endif
-
- switch(type) {
-
- default:
- case NOTINLIST:
- upcase(eye);
- addto_ubuf(eye);
- break;
-
- case IB:
- case IBASE:
- show_result(1);
-
- /* ZERO pointer: no more tokens
- Convbuf returned: next token not in preferred list
- in either case, leave right side alone */
-
- if ((eye = substivar(-1, Tokp[++cur_cnt], 10))
- == ZERO || eye == Convbuf) {
- --cur_cnt;
- Ibase = IB_DFLT;
- }
- else {
- conv_bc(eye, ZERO, Ibase, 10);
- Ibase = atoi(Convbuf);
- if (Ibase > 16 || Ibase < 2)
- Ibase = IB_DFLT;
- }
- sprintf(Mop, "ibase=A;ibase=%d\n",Ibase);
- addto_controlbuf(Mop);
- show_result(0);
- break;
-
- case OB:
- case OBASE:
- show_result(1);
- if ((eye = substivar(-1, Tokp[++cur_cnt], 10))
- == ZERO || eye == Convbuf) {
- --cur_cnt;
- Obase = OB_DFLT;
- }
- else {
- conv_bc(eye, ZERO, Ibase, 10);
- Obase = atoi(Convbuf);
- if (Obase > 16 || Obase < 2)
- Obase = OB_DFLT;
- }
- sprintf(Mop, "ibase=A;obase=%d;ibase=%d\n", Obase, Ibase);
- addto_controlbuf(Mop);
- show_result(0);
- break;
-
- case TE:
- case TERSE:
- case VER:
- case VERBOSE:
- case XT:
- case XTERSE:
- show_result(1);
- if (type == TE || type == TERSE)
- Hf = FTER;
- else if (type == VER || type == VERBOSE)
- Hf = FVER;
- else
- Hf = FXTER;
- show_result(0);
- break;
-
- case FIX:
- case RIGHT:
- case RI:
- case LE:
- case LEFT:
- case CM:
- case COMMA:
- case SP:
- case SPACE:
- show_result(1);
- if (type == FIX)
- Justify = JF;
- else if (type == RIGHT || type == RI)
- Justify = JR;
- else if (type == LE || type == LEFT)
- Justify = JL;
- else if (type == CM || type == COMMA)
- Separator = ',', Format = COMMA_;
- else if (type == SP || type == SPACE)
- Separator = ' ', Format = SPACE_;
- show_result(0);
- break;
-
- case QUESTION:
- case HELP:
- if (nex_type == -1)
- show_help(HELP);
- else {
- ++cur_cnt;
- show_help(nex_type);
- }
- break;
-
- case TO:
- if (!first) {
- HIDE_RES;
- }
- RECOVER;
- eye = Tokp[++cur_cnt];
- if (eye == ZERO)
- --cur_cnt;
- else if ((ri = conv_id(eye)) != -1)
- Convsel = ri;
- else
- --cur_cnt;
- Do_conv = conv_flag = TRUE;
- HIDE_RES;
- show_result(0);
- RECOVER;
- break;
-
- case AND:
- case OR:
- case XOR:
- if (!first) {
- HIDE_RES;
- }
- /* resolve left side; convert it to base 2 */
- conv_bc(sr->cell, ZERO, 1, 2);
- strcpy(itemp, Convbuf);
-
- if ((eye = substivar(-1, Tokp[++cur_cnt], 2))
- == ZERO || eye == Convbuf)
- --cur_cnt, eye = itemp;
- else if (eye == Tokp[cur_cnt]) {
- /* nextok is a digit string */
- conv_bc(eye, ZERO, -1, 2);
- eye = Convbuf;
- }
- if ((ip = bitwise(type, itemp, eye, &ri)) == ZERO) {
- pac_err("conversion range");
- TR_
- return;
- }
- conv_bc(ip, ZERO, 1, 0);
- addto_ubuf(Convbuf);
- HIDE_RES;
- RECOVER;
- break;
-
- case TW:
- case TWOSCOMP:
- case NOT:
- if (type == TWOSCOMP)
- type = TW;
- if (!first) {
- HIDE_RES;
- }
- /* resolve left side; convert it to base 2 */
- conv_bc(sr->cell, ZERO, 1, 2);
- strcpy(itemp, Convbuf);
-
- if ((eye = substivar(-1, Tokp[++cur_cnt], 10))
- == ZERO || eye == Convbuf) {
- --cur_cnt;
- /* reuse previous result */
- conv_bc(sr->cell, ZERO, 1, 10);
- eye = Convbuf;
- }
- else if (eye == Tokp[cur_cnt]) {
- /* nextok is a digit string */
- conv_bc(eye, ZERO, -1, 10);
- eye = Convbuf;
- }
- if ((ip = bitwise(type, itemp, eye, &ri)) == ZERO) {
- pac_err("conversion range");
- TR_
- return;
- }
- if (ri)
- addto_ubuf("-");
- conv_bc(ip, ZERO, 1, 0);
- addto_ubuf(Convbuf);
- if (type == TW)
- addto_ubuf((ri) ? "-1" : "+1");
- HIDE_RES;
- RECOVER;
- break;
-
- case MOD:
- if (!first) {
- HIDE_RES;
- }
- ri = Precision;
- sprintf(Mop,"ibase=A;scale=0;ibase=%d\n", Ibase);
- addto_controlbuf(Mop);
- show_result(0);
- conv_bc(sr->cell, ZERO, 1, 0);
- addto_ubuf(Convbuf);
- addto_ubuf("\%");
- if ((eye = substivar(-1, Tokp[++cur_cnt], 0))
- == ZERO || eye == Convbuf) {
- --cur_cnt;
- eye = Convbuf;
- }
- addto_ubuf(eye);
- HIDE_RES;
- sprintf(Mop,"ibase=A;scale=%d;ibase=%d\n",ri, Ibase);
- addto_controlbuf(Mop);
- show_result(0);
- RECOVER;
- break;
-
- case BANG:
- if (!first) {
- HIDE_RES;
- }
- /* resolve left side; convert it to base 10 */
- conv_bc(sr->cell, ZERO, 1, 10);
- value = atoi(Convbuf);
- if (value < 0)
- value = 0;
- else if (value > 35)
- value = 35;
- conv_bc(factab[value], ZERO, 1, 0);
- addto_ubuf(Convbuf);
- HIDE_RES;
- RECOVER;
- break;
-
- case JUSTIFY:
- case JU:
- eye = Tokp[++cur_cnt];
- if (eye == ZERO) {
- show_result(1);
- Justify = JUS_DFLT;
- show_result(0);
- }
- --cur_cnt;
- break;
-
- case HF:
- case HARDFORM:
- eye = Tokp[++cur_cnt];
- if (eye == ZERO) {
- show_result(1);
- Hf = HF_DFLT;
- show_result(0);
- }
- --cur_cnt;
- break;
-
- case SHARP: /* comment start */
- (conv_flag || Autoconv == ENA) ? (O_conv = TRUE)
- : (O_conv = FALSE);
- show_result(2);
- TR_
- return;
-
- case SEMI:
- show_result(1);
- first = 2;
- break;
-
- case STACK:
- case ST:
- case SB:
- case STAYBASE:
- case AUTOTIME:
- case AT:
- ip = stacbuf;
- ri = 0;
- show_result(1);
- eye = Tokp[++cur_cnt];
- if (eye == ZERO) {
- --cur_cnt;
- if (type == STACK || type == ST)
- (Stack == ENA) ? (ri = 1) : (Stack = ENA);
- else if (type == STAYBASE || type == SB)
- Staybase = ENA;
- else if (type == AUTOTIME || type == AT)
- Autotime = ENA;
- show_result(0);
- }
- else {
- value = lookup(eye);
- if (value == ON)
- value = ENA;
- else if (value == OFF)
- value = DISA;
- else {
- --cur_cnt;
- value = ENA;
- }
- if (type == STACK || type == ST) {
- if (value == ENA && Stack == ENA)
- ri = 1;
- Stack = value;
- }
- else if (type == STAYBASE || type == SB)
- Staybase = value;
- else if (type == AUTOTIME || type == AT)
- Autotime = value;
- show_result(0);
- }
- if (Hc != -1 && ri) {
- save_stack(ip, 1);
- ri = strlen(stacbuf);
- if ((write(Hc, stacbuf, ri)) != ri)
- fatal("hardcopy stack write");
- }
- break;
-
- case FORMAT:
- case FO:
- show_result(1);
- eye = Tokp[++cur_cnt];
- if (eye == ZERO) {
- --cur_cnt;
- Format = FORM_DFLT;
- (FORM_DFLT == COMMA_) ? (Separator = '.')
- : (Separator = ' ');
- }
- else {
- value = lookup(eye);
- switch (value) {
- case CM:
- case COMMA:
- Separator = ',';
- Format = COMMA_;
- break;
- default:
- --cur_cnt;
- Format = FORM_DFLT;
- (FORM_DFLT == COMMA_) ? (Separator = '.')
- : (Separator = ' ');
- break;
- case SP:
- case SPACE:
- Separator = ' ';
- Format = SPACE_;
- break;
- case OFF:
- Separator = ' ';
- Format = DISA;
- break;
- }
- }
- show_result(0);
- break;
-
- case PR:
- case PRECISION:
- case SCALE:
- case DP:
- show_result(1);
- /* get right side literal for input */
- if ((eye = substivar(-1, Tokp[++cur_cnt], 10))
- == ZERO || eye == Convbuf) {
- --cur_cnt;
- Precision = PREC_DFLT;
- }
- else {
- Precision = atoi(eye);
- if (Precision < 0 || Precision > 32)
- Precision = PREC_DFLT;
- }
- sprintf(Mop,"ibase=A;scale=%d;ibase=%d\n",Precision, Ibase);
- addto_controlbuf(Mop);
- show_result(0);
- break;
-
- case PP: /* PercentPlus */
- case PPLUS:
- case PM: /* PercentMinus */
- case PMINUS:
- case PD: /* PercentDelta */
- case PDELTA:
- case PDIFF:
- case PV: /* PercentVersus */
- case PVERSUS:
- case PO: /* PercentOf */
- case POF:
- case PE: /* PercentEqual */
- case PEQUAL:
- if (!first) {
- HIDE_RES;
- }
- conv_bc(sr->cell, ZERO, 1, 0); /* left side is input */
-
- /* get right side literal for input */
- if ((eye = substivar(-1, Tokp[++cur_cnt], 0))
- == ZERO || eye == Convbuf) {
- --cur_cnt;
- eye = Convbuf;
- }
- ip = itemp;
- switch (type) {
- case PP:
- case PPLUS:
- sprintf(ip, "%s+(%s*%s/%s)",
- Convbuf,Convbuf,eye,hundred[Ibase]);
- break;
- case PM:
- case PMINUS:
- sprintf(ip, "%s-(%s*%s/%s)",
- Convbuf,Convbuf,eye,hundred[Ibase]);
- break;
- case PV:
- case PVERSUS:
- sprintf(ip, "%s*%s/%s",
- eye,hundred[Ibase],Convbuf);
- break;
- case PD:
- case PDELTA:
- case PDIFF:
- sprintf(ip, "(%s*(%s-%s))/%s",
- hundred[Ibase],eye,Convbuf,Convbuf);
- break;
- case PO:
- case POF:
- sprintf(ip, "(%s*%s/%s)",
- eye,Convbuf,hundred[Ibase]);
- break;
- case PE:
- case PEQUAL:
- sprintf(ip, "(%s*%s/%s)",
- eye,hundred[Ibase],Convbuf);
- break;
- }
- addto_ubuf(ip);
- break;
-
- case LOG:
- *onechar = *eye;
- addto_ubuf(onechar);
- break;
-
- case SQRT:
- addto_ubuf(eye);
- break;
-
- case INIT_:
- show_result(1);
- pacinit();
- sprintf(Mop, "ibase=A;obase=%d;ibase=%d\n", Obase, Ibase);
- addto_controlbuf(Mop);
- show_result(0);
- break;
-
- case DONTSAVE:
- case DS:
- Dontsave = 1;
- break;
-
- /* copy accum into chosen stack cell, or onto top of stack.
- Other cells are not disturbed */
- case STO:
- show_result(1);
- if (nxeye == ZERO || strlen(nxeye) > 1 ||
- (strlen(nxeye) == 1 && (*nxeye < 'h' || *nxeye > 'w')))
- c_val = 'h';
- else {
- c_val = *nxeye;
- ++cur_cnt;
- }
- stack_reg(c_val - 'g', 0);
- break;
-
- case IF:
- case WHILE:
- case FOR:
- case BREAK:
- case DEFINE:
- case LENGTH:
- pac_err("unimplemented key");
- TR_
- return;
-
- case QUIT:
- case EXIT:
- go_away(ZERO, 0);
-
- case BYE:
- clearstack(0);
- Amt = Rate = Years = 0.;
- go_away("I", 0);
-
- /* value = sum of bytes' ascii values of next token are
- substituted (in current Ibase) in input to bc */
- case TICK:
- value = 0;
- if ((eye = Tokp[++cur_cnt]) == ZERO)
- --cur_cnt;
- else
- while (*eye)
- value += *eye++;
- sprintf(Mop, "%c %d",Base_str[10], value);
- conv_bc(Mop, ZERO, 1, 0);
- addto_ubuf(Convbuf);
- break;
-
- case BACKSLASH:
- RECOVER;
- break;
-
- case KILO:
- case ATTO:
- case FEMTO:
- case GIGA:
- case MEGA:
- case MICRO:
- case MILLI:
- case NANO:
- case PICO:
- case TERA:
- case PETA:
- case EXA:
- if (first) {
- RECOVER;
- }
- addto_ubuf("*");
- addto_ubuf(substivar(type, ZERO, Ibase));
- break;
-
- case X_LOWER:
- case X_UPPER:
- sprintf(itemp, "%s", sixteen[Ibase]);
- addto_ubuf(itemp);
- break;
-
- /* shift Stack down from named register (or top, if no arg);
- bottom gets lost. Copy accum into named element.
- works independently (in addition to) stack effect */
- case PSH:
- show_result(1);
- if (nxeye == ZERO || strlen(nxeye) > 1 ||
- (strlen(nxeye) == 1 && (*nxeye < 'h' || *nxeye > 'w'))) {
- pushstack(1);
- stack_reg(1, 0);
- }
- else {
- pushstack(*nxeye - 'g');
- stack_reg(*nxeye - 'g', 0);
- ++cur_cnt;
- }
- break;
-
- /* Move stack element (or top, if no arg) into accum, move up
- all elements below it. Move 0 into bottom location */
- case PLL:
- show_result(1);
- if (nxeye == ZERO || strlen(nxeye) > 1 ||
- (strlen(nxeye) == 1 && (*nxeye < 'h' || *nxeye > 'w'))) {
- onereg(1);
- popstack(1);
- }
- else {
- onereg(*nxeye - 'g');
- popstack(*nxeye - 'g');
- ++cur_cnt;
- }
- conv_bc(Onebuf, ZERO, 1, 0);
- addto_ubuf(Convbuf);
- HIDE_RES;
- break;
-
- /* Swap accum and stacktop (no args), or accum and cell (1 arg),
- other registers remain intact */
- case SWP:
- show_result(1);
- if (nxeye == ZERO || strlen(nxeye) > 1 ||
- (strlen(nxeye) == 1 && (*nxeye < 'h' || *nxeye > 'w'))) {
- onereg(1);
- stack_reg(1, 0);
- }
- else {
- onereg(*nxeye - 'g');
- stack_reg(*nxeye - 'g', 0);
- ++cur_cnt;
- }
- conv_bc(Onebuf, ZERO, 1, 0);
- addto_ubuf(Convbuf);
- HIDE_RES;
- break;
-
- /* Discard top of stack, (no args) or named stack cell (1 arg);
- move up lower locations. Move 0 into bottom location */
- case POP:
- show_result(1);
- if (nxeye == ZERO || strlen(nxeye) > 1 ||
- (strlen(nxeye) == 1 && (*nxeye < 'h' || *nxeye > 'w')))
- popstack(1);
- else {
- popstack(*nxeye - 'g');
- ++cur_cnt;
- }
- break;
-
- case MOHOS:
- #ifdef TRACE
- if (first) {
- Trace = !Trace;
- if (Trace && Tf == NULL) {
- Tlev = 18; /* pop 2 off 20 maxdeep tabs */
- if ((Tf = fopen("pactrace", "w")) == NULL)
- go_away("bad trace file", 1);
- }
- if (!Trace && Tf != NULL) {
- fclose(Tf);
- Tf = NULL;
- }
- }
- #endif
- *Ubuf = '\0';
- *Controlbuf = '\0';
- first = TRUE;
- conv_flag = FALSE;
- break;
-
- case PI:
- case ASTRO:
- case AMASS:
- case AVOGADRO:
- case BOLTZMANN:
- case ECHARGE:
- case CHROMA:
- case EMASS:
- case EULER:
- case FARADAY:
- case G_:
- case GAS:
- case GRAVITY:
- case HEAT:
- case LIGHT:
- case LIGHTYEAR:
- case MOONMASS:
- case SUNMASS:
- case EARTHMASS:
- case NATURAL:
- case NMASS:
- case PARSEC:
- case PARALLAX:
- case PLANCK:
- case PMASS:
- case MOONRAD:
- case SUNRAD:
- case EARTHRAD:
- case RYDBERG:
- case SOUND:
- case STEFAN:
- case TOMOON:
- case TOSUN:
- case WIEN:
- addto_ubuf(substivar(type, ZERO, Ibase));
- break;
-
- case H_:
- case I_:
- case J_:
- case K_:
- case L_:
- case M_:
- case N_:
- case O_:
- case P_:
- case Q_:
- case R_:
- case S_:
- case T_:
- case U_:
- case V_:
- case W_:
- conv_bc((char *)find(*eye - 'g'), ZERO, 1, 0);
- addto_ubuf(Convbuf);
- break;
-
- case SIN:
- case COS:
- case EXP:
- case ARCT:
- if (Ibase != 10) {
- pac_err("active in 10 base only");
- TR_
- return;
- }
- *onechar = *eye;
- addto_ubuf(onechar);
- break;
-
- /* Put 0 into a specific stack cell, or into
- all cells including accum */
- case CLR:
- if (nxeye == ZERO || strlen(nxeye) > 1 ||
- (strlen(nxeye) == 1 && (*nxeye < 'h' || *nxeye > 'w'))) {
- clearstack(0);
- addto_ubuf(";0;");
- }
- else {
- clearstack(*nxeye - 'g');
- ++cur_cnt;
- }
- show_result(1);
- break;
-
- /* Values below named cell (or top) move down, bottom gets lost,
- named cell is copied into cell below */
- case DUP:
- show_result(1);
- if (nxeye == ZERO || strlen(nxeye) > 1 ||
- (strlen(nxeye) == 1 && (*nxeye < 'h' || *nxeye > 'w'))) {
- stack_reg('w' - 'g', 0); /* copy it into W first */
- pushstack(1);
- }
- else {
- stack_reg('w' - 'g', *nxeye - 'g');
- pushstack(*nxeye - 'g');
- ++cur_cnt;
- }
- break;
-
- /* Turn continuous conversion on/off */
- case AU:
- case AUTO:
- case AUTOCONV:
- show_result(1);
- Do_conv = TRUE;
- eye = Tokp[++cur_cnt];
- if (eye == ZERO) {
- --cur_cnt;
- Autoconv = ENA;
- show_result(0);
- break;
- }
- value = lookup(eye);
- if (value != ON && value != OFF) {
- --cur_cnt;
- Autoconv = ENA;
- }
- else if (value == ON)
- Autoconv = ENA;
- else {
- Autoconv = DISA;
- Do_conv = FALSE;
- }
- show_result(0);
- break;
-
- }
- (first == 2) ? (first = TRUE) : (first = FALSE);
- /* FALSE after evaluating the first token */
- }
- (conv_flag || Autoconv == ENA) ? (O_conv = TRUE) : (O_conv = FALSE);
- show_result(2);
-
- #ifdef TOX
- clear_wline(BOT, ULEFT, RBOUND, 1, 1);
- standout();
- mvaddstr(BOT, ULEFT, Tk);
- standend();
- pfresh();
- sleep(5);
- move(CY, CX);
- #endif
-
- TR_
- }
-
-