1*45326Sbostic /* SC A Spreadsheet Calculator
2*45326Sbostic * Lexical analyser
3*45326Sbostic *
4*45326Sbostic * original by James Gosling, September 1982
5*45326Sbostic * modifications by Mark Weiser and Bruce Israel,
6*45326Sbostic * University of Maryland
7*45326Sbostic *
8*45326Sbostic * More mods Robert Bond, 12/86
9*45326Sbostic * More mods by Alan Silverstein, 3/88, see list of changes.
10*45326Sbostic * $Revision: 6.8 $
11*45326Sbostic *
12*45326Sbostic */
13*45326Sbostic
14*45326Sbostic
15*45326Sbostic
16*45326Sbostic #if defined(BSD42) || defined(BSD43)
17*45326Sbostic #include <sys/ioctl.h>
18*45326Sbostic #endif
19*45326Sbostic
20*45326Sbostic #ifdef IEEE_MATH
21*45326Sbostic #include <ieeefp.h>
22*45326Sbostic #endif /* IEEE_MATH */
23*45326Sbostic
24*45326Sbostic #include <curses.h>
25*45326Sbostic #include <signal.h>
26*45326Sbostic #include <setjmp.h>
27*45326Sbostic #include "sc.h"
28*45326Sbostic #include <ctype.h>
29*45326Sbostic
30*45326Sbostic #ifdef BSD42
31*45326Sbostic #include <strings.h>
32*45326Sbostic #else
33*45326Sbostic #ifndef SYSIII
34*45326Sbostic #include <string.h>
35*45326Sbostic #endif
36*45326Sbostic #endif
37*45326Sbostic
38*45326Sbostic #ifdef VMS
39*45326Sbostic #include "gram_tab.h"
40*45326Sbostic typedef union {
41*45326Sbostic int ival;
42*45326Sbostic double fval;
43*45326Sbostic struct ent *ent;
44*45326Sbostic struct enode *enode;
45*45326Sbostic char *sval;
46*45326Sbostic struct range_s rval;
47*45326Sbostic } YYSTYPE;
48*45326Sbostic extern YYSTYPE yylval;
49*45326Sbostic extern int VMS_read_raw; /*sigh*/
50*45326Sbostic #else /* VMS */
51*45326Sbostic #include "y.tab.h"
52*45326Sbostic #endif /* VMS */
53*45326Sbostic
54*45326Sbostic char *strtof();
55*45326Sbostic
56*45326Sbostic jmp_buf wakeup;
57*45326Sbostic jmp_buf fpe_buf;
58*45326Sbostic
59*45326Sbostic struct key {
60*45326Sbostic char *key;
61*45326Sbostic int val;
62*45326Sbostic };
63*45326Sbostic
64*45326Sbostic struct key experres[] = {
65*45326Sbostic #include "experres.h"
66*45326Sbostic 0, 0};
67*45326Sbostic
68*45326Sbostic struct key statres[] = {
69*45326Sbostic #include "statres.h"
70*45326Sbostic 0, 0};
71*45326Sbostic
yylex()72*45326Sbostic yylex ()
73*45326Sbostic {
74*45326Sbostic register char *p = line+linelim;
75*45326Sbostic int ret;
76*45326Sbostic while (isspace(*p)) p++;
77*45326Sbostic if (*p == '\0') ret = -1;
78*45326Sbostic else if (isalpha(*p)) {
79*45326Sbostic char *tokenst = p;
80*45326Sbostic register tokenl;
81*45326Sbostic register struct key *tblp;
82*45326Sbostic tokenl = 0;
83*45326Sbostic /*
84*45326Sbostic * This picks up either 1 or 2 alpha characters (a column) or
85*45326Sbostic * tokens with at least three leading alphas and '_' or digits
86*45326Sbostic * (a function or token or command or a range name)
87*45326Sbostic */
88*45326Sbostic while (isalpha(*p) || ((*p == '_') || isdigit(*p)) && (tokenl > 2)) {
89*45326Sbostic p++;
90*45326Sbostic tokenl++;
91*45326Sbostic }
92*45326Sbostic if (tokenl <= 2) { /* a COL is 1 or 2 char alpha
93*45326Sbostic (but not pi, ln, fv, pv, if -- this should be fixed!) */
94*45326Sbostic if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') {
95*45326Sbostic ret = K_PI;
96*45326Sbostic } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') {
97*45326Sbostic ret = K_LN;
98*45326Sbostic } else if (tokenl == 2 && tokenst[0] == 'f' && tokenst[1] == 'v') {
99*45326Sbostic ret = K_FV;
100*45326Sbostic } else if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'v') {
101*45326Sbostic ret = K_PV;
102*45326Sbostic } else if (tokenl == 2 && tokenst[0] == 'i' && tokenst[1] == 'f') {
103*45326Sbostic ret = K_IF;
104*45326Sbostic
105*45326Sbostic } else {
106*45326Sbostic ret = COL;
107*45326Sbostic yylval.ival = atocol (tokenst, tokenl);
108*45326Sbostic }
109*45326Sbostic } else {
110*45326Sbostic ret = WORD;
111*45326Sbostic for (tblp = linelim ? experres : statres; tblp->key; tblp++)
112*45326Sbostic if (((tblp->key[0]^tokenst[0])&0137)==0
113*45326Sbostic && tblp->key[tokenl]==0) {
114*45326Sbostic register i = 1;
115*45326Sbostic while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0)
116*45326Sbostic i++;
117*45326Sbostic if (i>=tokenl) {
118*45326Sbostic ret = tblp->val;
119*45326Sbostic break;
120*45326Sbostic }
121*45326Sbostic }
122*45326Sbostic if (ret==WORD) {
123*45326Sbostic struct range *r;
124*45326Sbostic if (r = find_range(tokenst, tokenl,
125*45326Sbostic (struct ent *)0, (struct ent *)0)) {
126*45326Sbostic yylval.rval.left = r->r_left;
127*45326Sbostic yylval.rval.right = r->r_right;
128*45326Sbostic if (r->r_is_range)
129*45326Sbostic ret = RANGE;
130*45326Sbostic else
131*45326Sbostic ret = VAR;
132*45326Sbostic } else {
133*45326Sbostic linelim = p-line;
134*45326Sbostic yyerror ("Unintelligible word");
135*45326Sbostic }
136*45326Sbostic }
137*45326Sbostic }
138*45326Sbostic } else if ((*p == '.') || isdigit(*p)) {
139*45326Sbostic double v = 0;
140*45326Sbostic int temp;
141*45326Sbostic char *nstart = p;
142*45326Sbostic if (*p != '.') {
143*45326Sbostic do v = v*10 + (double)(*p-'0');
144*45326Sbostic while (isdigit(*++p));
145*45326Sbostic }
146*45326Sbostic if (*p=='.' || *p == 'e' || *p == 'E') {
147*45326Sbostic ret = FNUMBER;
148*45326Sbostic p = strtof(nstart, &yylval.fval);
149*45326Sbostic } else {
150*45326Sbostic /* A NUMBER must hold at least MAXROW and MAXCOL */
151*45326Sbostic /* This is consistent with a short row and col in struct ent */
152*45326Sbostic if (v > (double)32767 || v < (double)-32768) {
153*45326Sbostic ret = FNUMBER;
154*45326Sbostic yylval.fval = v;
155*45326Sbostic } else {
156*45326Sbostic temp = (int)v;
157*45326Sbostic if((double)temp != v) {
158*45326Sbostic ret = FNUMBER;
159*45326Sbostic yylval.fval = v;
160*45326Sbostic } else {
161*45326Sbostic ret = NUMBER;
162*45326Sbostic yylval.ival = temp;
163*45326Sbostic }
164*45326Sbostic }
165*45326Sbostic }
166*45326Sbostic } else if (*p=='"') {
167*45326Sbostic char *ptr;
168*45326Sbostic ptr = p+1;
169*45326Sbostic while(*ptr && *ptr++ != '"');
170*45326Sbostic ptr = xmalloc((unsigned)(ptr-p));
171*45326Sbostic yylval.sval = ptr;
172*45326Sbostic p += 1;
173*45326Sbostic while (*p && *p!='"') *ptr++ = *p++;
174*45326Sbostic *ptr = 0;
175*45326Sbostic if (*p) p += 1;
176*45326Sbostic ret = STRING;
177*45326Sbostic } else if (*p=='[') {
178*45326Sbostic while (*p && *p!=']') p++;
179*45326Sbostic if (*p) p++;
180*45326Sbostic linelim = p-line;
181*45326Sbostic return yylex();
182*45326Sbostic } else ret = *p++;
183*45326Sbostic linelim = p-line;
184*45326Sbostic return ret;
185*45326Sbostic }
186*45326Sbostic
187*45326Sbostic
188*45326Sbostic /*
189*45326Sbostic * Given a token string starting with a symbolic column name and its valid
190*45326Sbostic * length, convert column name ("A"-"Z" or "AA"-"ZZ") to a column number (0-N).
191*45326Sbostic * Never mind if the column number is illegal (too high). The procedure's name
192*45326Sbostic * and function are the inverse of coltoa().
193*45326Sbostic *
194*45326Sbostic * Case-insensitivity is done crudely, by ignoring the 040 bit.
195*45326Sbostic */
196*45326Sbostic
197*45326Sbostic int
atocol(string,len)198*45326Sbostic atocol (string, len)
199*45326Sbostic char *string;
200*45326Sbostic int len;
201*45326Sbostic {
202*45326Sbostic register int col;
203*45326Sbostic
204*45326Sbostic col = (string [0] & 0137) - 'A';
205*45326Sbostic
206*45326Sbostic if (len == 2) /* has second char */
207*45326Sbostic col = ((col + 1) * 26) + ((string [1] & 0137) - 'A');
208*45326Sbostic
209*45326Sbostic return (col);
210*45326Sbostic }
211*45326Sbostic
212*45326Sbostic
213*45326Sbostic #ifdef SIMPLE
214*45326Sbostic
initkbd()215*45326Sbostic initkbd()
216*45326Sbostic {}
217*45326Sbostic
kbd_again()218*45326Sbostic kbd_again()
219*45326Sbostic {}
220*45326Sbostic
resetkbd()221*45326Sbostic resetkbd()
222*45326Sbostic {}
223*45326Sbostic
224*45326Sbostic #ifndef VMS
225*45326Sbostic
nmgetch()226*45326Sbostic nmgetch()
227*45326Sbostic {
228*45326Sbostic return (toascii(getchar()));
229*45326Sbostic }
230*45326Sbostic
231*45326Sbostic #else /* VMS */
232*45326Sbostic
nmgetch()233*45326Sbostic nmgetch()
234*45326Sbostic /*
235*45326Sbostic This is not perfect, it doesn't move the cursor when goraw changes
236*45326Sbostic over to deraw, but it works well enough since the whole sc package
237*45326Sbostic is incredibly stable (loop constantly positions cursor).
238*45326Sbostic
239*45326Sbostic Question, why didn't the VMS people just implement cbreak?
240*45326Sbostic
241*45326Sbostic NOTE: During testing it was discovered that the DEBUGGER and curses
242*45326Sbostic and this method of reading would collide (the screen was not updated
243*45326Sbostic when continuing from screen mode in the debugger).
244*45326Sbostic */
245*45326Sbostic {
246*45326Sbostic short c;
247*45326Sbostic static int key_id=0;
248*45326Sbostic int status;
249*45326Sbostic #define VMScheck(a) {if (~(status = (a)) & 1) VMS_MSG (status);}
250*45326Sbostic
251*45326Sbostic if (VMS_read_raw) {
252*45326Sbostic VMScheck(smg$read_keystroke (&stdkb->_id, &c, 0, 0, 0));
253*45326Sbostic }
254*45326Sbostic else
255*45326Sbostic c = getchar();
256*45326Sbostic
257*45326Sbostic switch (c) {
258*45326Sbostic case SMG$K_TRM_LEFT: c = ctl('b'); break;
259*45326Sbostic case SMG$K_TRM_RIGHT: c = ctl('f'); break;
260*45326Sbostic case SMG$K_TRM_UP: c = ctl('p'); break;
261*45326Sbostic case SMG$K_TRM_DOWN: c = ctl('n'); break;
262*45326Sbostic default: c = c & 0x7f;
263*45326Sbostic }
264*45326Sbostic return (c);
265*45326Sbostic }
266*45326Sbostic
267*45326Sbostic
VMS_MSG(status)268*45326Sbostic VMS_MSG (status)
269*45326Sbostic int status;
270*45326Sbostic /*
271*45326Sbostic Routine to put out the VMS operating system error (if one occurs).
272*45326Sbostic */
273*45326Sbostic {
274*45326Sbostic #include <descrip.h>
275*45326Sbostic char errstr[81], buf[120];
276*45326Sbostic $DESCRIPTOR(errdesc, errstr);
277*45326Sbostic short int length;
278*45326Sbostic #define err_out(msg) fprintf (stderr,msg)
279*45326Sbostic
280*45326Sbostic /* Check for no error or standard error */
281*45326Sbostic
282*45326Sbostic if (~status & 1) {
283*45326Sbostic status = status & 0x8000 ? status & 0xFFFFFFF : status & 0xFFFF;
284*45326Sbostic if (SYS$GETMSG(status, &length, &errdesc, 1, 0) == SS$_NORMAL) {
285*45326Sbostic errstr[length] = '\0';
286*45326Sbostic sprintf (buf, "<0x%x> %s", status, errdesc.dsc$a_pointer);
287*45326Sbostic err_out (buf);
288*45326Sbostic }
289*45326Sbostic else
290*45326Sbostic err_out ("System error");
291*45326Sbostic }
292*45326Sbostic }
293*45326Sbostic #endif /* VMS */
294*45326Sbostic
295*45326Sbostic #else /*SIMPLE*/
296*45326Sbostic
297*45326Sbostic #if defined(BSD42) || defined (SYSIII) || defined(BSD43)
298*45326Sbostic
299*45326Sbostic #define N_KEY 4
300*45326Sbostic
301*45326Sbostic struct key_map {
302*45326Sbostic char *k_str;
303*45326Sbostic char k_val;
304*45326Sbostic char k_index;
305*45326Sbostic };
306*45326Sbostic
307*45326Sbostic struct key_map km[N_KEY];
308*45326Sbostic
309*45326Sbostic char keyarea[N_KEY*30];
310*45326Sbostic
311*45326Sbostic char *tgetstr();
312*45326Sbostic char *getenv();
313*45326Sbostic char *ks;
314*45326Sbostic char ks_buf[20];
315*45326Sbostic char *ke;
316*45326Sbostic char ke_buf[20];
317*45326Sbostic
318*45326Sbostic #ifdef TIOCSLTC
319*45326Sbostic struct ltchars old_chars, new_chars;
320*45326Sbostic #endif
321*45326Sbostic
322*45326Sbostic char dont_use[] = {
323*45326Sbostic ctl('['), ctl('a'), ctl('b'), ctl('c'), ctl('e'), ctl('f'), ctl('g'), ctl('h'),
324*45326Sbostic ctl('i'), ctl('j'), ctl('l'), ctl('m'), ctl('n'), ctl('p'), ctl('q'),
325*45326Sbostic ctl('r'), ctl('s'), ctl('t'), ctl('u'), ctl('v'), ctl('w'), ctl('x'),
326*45326Sbostic ctl('z'), 0
327*45326Sbostic };
328*45326Sbostic
charout(c)329*45326Sbostic charout(c)
330*45326Sbostic int c;
331*45326Sbostic {
332*45326Sbostic (void)putchar(c);
333*45326Sbostic }
334*45326Sbostic
initkbd()335*45326Sbostic initkbd()
336*45326Sbostic {
337*45326Sbostic register struct key_map *kp;
338*45326Sbostic register i,j;
339*45326Sbostic char *p = keyarea;
340*45326Sbostic char *ktmp;
341*45326Sbostic static char buf[1024]; /* Why do I have to do this again? */
342*45326Sbostic
343*45326Sbostic if (tgetent(buf, getenv("TERM")) <= 0)
344*45326Sbostic return;
345*45326Sbostic
346*45326Sbostic km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl('b');
347*45326Sbostic km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl('f');
348*45326Sbostic km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl('p');
349*45326Sbostic km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl('n');
350*45326Sbostic ktmp = tgetstr("ks",&p);
351*45326Sbostic if (ktmp) {
352*45326Sbostic (void) strcpy(ks_buf, ktmp);
353*45326Sbostic ks = ks_buf;
354*45326Sbostic tputs(ks, 1, charout);
355*45326Sbostic }
356*45326Sbostic ktmp = tgetstr("ke",&p);
357*45326Sbostic if (ktmp) {
358*45326Sbostic (void) strcpy(ke_buf, ktmp);
359*45326Sbostic ke = ke_buf;
360*45326Sbostic }
361*45326Sbostic
362*45326Sbostic /* Unmap arrow keys which conflict with our ctl keys */
363*45326Sbostic /* Ignore unset, longer than length 1, and 1-1 mapped keys */
364*45326Sbostic
365*45326Sbostic for (i = 0; i < N_KEY; i++) {
366*45326Sbostic kp = &km[i];
367*45326Sbostic if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val))
368*45326Sbostic for (j = 0; dont_use[j] != 0; j++)
369*45326Sbostic if (kp->k_str[0] == dont_use[j]) {
370*45326Sbostic kp->k_str = (char *)0;
371*45326Sbostic break;
372*45326Sbostic }
373*45326Sbostic }
374*45326Sbostic
375*45326Sbostic
376*45326Sbostic #ifdef TIOCSLTC
377*45326Sbostic (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
378*45326Sbostic new_chars = old_chars;
379*45326Sbostic if (old_chars.t_lnextc == ctl('v'))
380*45326Sbostic new_chars.t_lnextc = -1;
381*45326Sbostic if (old_chars.t_rprntc == ctl('r'))
382*45326Sbostic new_chars.t_rprntc = -1;
383*45326Sbostic (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
384*45326Sbostic #endif
385*45326Sbostic }
386*45326Sbostic
387*45326Sbostic void
kbd_again()388*45326Sbostic kbd_again()
389*45326Sbostic {
390*45326Sbostic if (ks)
391*45326Sbostic tputs(ks, 1, charout);
392*45326Sbostic
393*45326Sbostic #ifdef TIOCSLTC
394*45326Sbostic (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
395*45326Sbostic #endif
396*45326Sbostic }
397*45326Sbostic
398*45326Sbostic void
resetkbd()399*45326Sbostic resetkbd()
400*45326Sbostic {
401*45326Sbostic if (ke)
402*45326Sbostic tputs(ke, 1, charout);
403*45326Sbostic
404*45326Sbostic #ifdef TIOCSLTC
405*45326Sbostic (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars);
406*45326Sbostic #endif
407*45326Sbostic }
408*45326Sbostic
nmgetch()409*45326Sbostic nmgetch()
410*45326Sbostic {
411*45326Sbostic register int c;
412*45326Sbostic register struct key_map *kp;
413*45326Sbostic register struct key_map *biggest;
414*45326Sbostic register int i;
415*45326Sbostic int almost;
416*45326Sbostic int maybe;
417*45326Sbostic
418*45326Sbostic static char dumpbuf[10];
419*45326Sbostic static char *dumpindex;
420*45326Sbostic
421*45326Sbostic #ifdef SIGVOID
422*45326Sbostic void time_out();
423*45326Sbostic #else
424*45326Sbostic int time_out();
425*45326Sbostic #endif
426*45326Sbostic
427*45326Sbostic if (dumpindex && *dumpindex)
428*45326Sbostic return (*dumpindex++);
429*45326Sbostic
430*45326Sbostic c = toascii(getchar());
431*45326Sbostic biggest = 0;
432*45326Sbostic almost = 0;
433*45326Sbostic
434*45326Sbostic for (kp = &km[0]; kp < &km[N_KEY]; kp++) {
435*45326Sbostic if (!kp->k_str)
436*45326Sbostic continue;
437*45326Sbostic if (c == kp->k_str[kp->k_index]) {
438*45326Sbostic almost = 1;
439*45326Sbostic kp->k_index++;
440*45326Sbostic if (kp->k_str[kp->k_index] == 0) {
441*45326Sbostic c = kp->k_val;
442*45326Sbostic for (kp = &km[0]; kp < &km[N_KEY]; kp++)
443*45326Sbostic kp->k_index = 0;
444*45326Sbostic return(c);
445*45326Sbostic }
446*45326Sbostic }
447*45326Sbostic if (!biggest && kp->k_index)
448*45326Sbostic biggest = kp;
449*45326Sbostic else if (kp->k_index && biggest->k_index < kp->k_index)
450*45326Sbostic biggest = kp;
451*45326Sbostic }
452*45326Sbostic
453*45326Sbostic if (almost) {
454*45326Sbostic (void) signal(SIGALRM, time_out);
455*45326Sbostic (void) alarm(1);
456*45326Sbostic
457*45326Sbostic if (setjmp(wakeup) == 0) {
458*45326Sbostic maybe = nmgetch();
459*45326Sbostic (void) alarm(0);
460*45326Sbostic return(maybe);
461*45326Sbostic }
462*45326Sbostic }
463*45326Sbostic
464*45326Sbostic if (biggest) {
465*45326Sbostic for (i = 0; i<biggest->k_index; i++)
466*45326Sbostic dumpbuf[i] = biggest->k_str[i];
467*45326Sbostic if (!almost)
468*45326Sbostic dumpbuf[i++] = c;
469*45326Sbostic dumpbuf[i] = '\0';
470*45326Sbostic dumpindex = &dumpbuf[1];
471*45326Sbostic for (kp = &km[0]; kp < &km[N_KEY]; kp++)
472*45326Sbostic kp->k_index = 0;
473*45326Sbostic return (dumpbuf[0]);
474*45326Sbostic }
475*45326Sbostic
476*45326Sbostic return(c);
477*45326Sbostic }
478*45326Sbostic
479*45326Sbostic #endif
480*45326Sbostic
481*45326Sbostic #if defined(SYSV2) || defined(SYSV3)
482*45326Sbostic
initkbd()483*45326Sbostic initkbd()
484*45326Sbostic {
485*45326Sbostic keypad(stdscr, TRUE);
486*45326Sbostic }
487*45326Sbostic
488*45326Sbostic void
kbd_again()489*45326Sbostic kbd_again()
490*45326Sbostic {
491*45326Sbostic keypad(stdscr, TRUE);
492*45326Sbostic }
493*45326Sbostic
494*45326Sbostic void
resetkbd()495*45326Sbostic resetkbd()
496*45326Sbostic {
497*45326Sbostic keypad(stdscr, FALSE);
498*45326Sbostic }
499*45326Sbostic
nmgetch()500*45326Sbostic nmgetch()
501*45326Sbostic {
502*45326Sbostic register int c;
503*45326Sbostic
504*45326Sbostic c = getch();
505*45326Sbostic switch (c) {
506*45326Sbostic case KEY_LEFT: c = ctl('b'); break;
507*45326Sbostic case KEY_RIGHT: c = ctl('f'); break;
508*45326Sbostic case KEY_UP: c = ctl('p'); break;
509*45326Sbostic case KEY_DOWN: c = ctl('n'); break;
510*45326Sbostic #ifdef KEY_C1
511*45326Sbostic /* This stuff works for a wyse wy75 in ANSI mode under 5.3. Good luck. */
512*45326Sbostic /* It is supposed to map the curses keypad back to the numeric equiv. */
513*45326Sbostic case KEY_C1: c = '0'; break;
514*45326Sbostic case KEY_A1: c = '1'; break;
515*45326Sbostic case KEY_B2: c = '2'; break;
516*45326Sbostic case KEY_A3: c = '3'; break;
517*45326Sbostic case KEY_F(5): c = '4'; break;
518*45326Sbostic case KEY_F(6): c = '5'; break;
519*45326Sbostic case KEY_F(7): c = '6'; break;
520*45326Sbostic case KEY_F(9): c = '7'; break;
521*45326Sbostic case KEY_F(10): c = '8'; break;
522*45326Sbostic case KEY_F0: c = '9'; break;
523*45326Sbostic case KEY_C3: c = '.'; break;
524*45326Sbostic case KEY_ENTER: c = ctl('m'); break;
525*45326Sbostic #endif
526*45326Sbostic default: c = toascii(c);
527*45326Sbostic break;
528*45326Sbostic }
529*45326Sbostic return (c);
530*45326Sbostic }
531*45326Sbostic
532*45326Sbostic #endif /* SYSV2 || SYSV3 */
533*45326Sbostic
534*45326Sbostic #endif /* SIMPLE */
535*45326Sbostic
536*45326Sbostic #ifdef SIGVOID
537*45326Sbostic void
538*45326Sbostic #endif
time_out(signo)539*45326Sbostic time_out(signo)
540*45326Sbostic int signo;
541*45326Sbostic {
542*45326Sbostic #ifdef IEEE_MATH
543*45326Sbostic (void)fpsetsticky((fp_except)0); /* Clear exception */
544*45326Sbostic #endif /* IEEE_MATH */
545*45326Sbostic longjmp(wakeup, -1);
546*45326Sbostic }
547*45326Sbostic
548*45326Sbostic #ifdef SIGVOID
549*45326Sbostic void
550*45326Sbostic #endif
fpe_trap(signo)551*45326Sbostic fpe_trap(signo)
552*45326Sbostic int signo;
553*45326Sbostic {
554*45326Sbostic longjmp(fpe_buf, 1);
555*45326Sbostic }
556*45326Sbostic
557*45326Sbostic /*
558*45326Sbostic * This converts a floating point number of the form
559*45326Sbostic * [s]ddd[.d*][esd*] where s can be a + or - and e is E or e.
560*45326Sbostic * to floating point.
561*45326Sbostic * p is advanced.
562*45326Sbostic */
563*45326Sbostic
564*45326Sbostic char *
strtof(p,res)565*45326Sbostic strtof(p, res)
566*45326Sbostic register char *p;
567*45326Sbostic double *res;
568*45326Sbostic {
569*45326Sbostic double acc;
570*45326Sbostic int sign;
571*45326Sbostic double fpos;
572*45326Sbostic int exp;
573*45326Sbostic int exps;
574*45326Sbostic #ifdef SIGVOID
575*45326Sbostic void (*sig_save)();
576*45326Sbostic #else
577*45326Sbostic int (*sig_save)();
578*45326Sbostic #endif
579*45326Sbostic
580*45326Sbostic sig_save = signal(SIGFPE, fpe_trap);
581*45326Sbostic if (setjmp(fpe_buf)) {
582*45326Sbostic error("Floating point exception\n");
583*45326Sbostic *res = 0.0;
584*45326Sbostic (void) signal(SIGFPE, sig_save);
585*45326Sbostic return(p);
586*45326Sbostic }
587*45326Sbostic acc = 0.0;
588*45326Sbostic sign = 1;
589*45326Sbostic exp = 0;
590*45326Sbostic exps = 1;
591*45326Sbostic if (*p == '+')
592*45326Sbostic p++;
593*45326Sbostic else if (*p == '-') {
594*45326Sbostic p++;
595*45326Sbostic sign = -1;
596*45326Sbostic }
597*45326Sbostic while (isdigit(*p)) {
598*45326Sbostic acc = acc * 10.0 + (double)(*p - '0');
599*45326Sbostic p++;
600*45326Sbostic }
601*45326Sbostic if (*p == 'e' || *p == 'E') {
602*45326Sbostic p++;
603*45326Sbostic if (*p == '+')
604*45326Sbostic p++;
605*45326Sbostic else if (*p == '-') {
606*45326Sbostic p++;
607*45326Sbostic exps = -1;
608*45326Sbostic }
609*45326Sbostic while(isdigit(*p)) {
610*45326Sbostic exp = exp * 10 + (*p - '0');
611*45326Sbostic p++;
612*45326Sbostic }
613*45326Sbostic }
614*45326Sbostic if (*p == '.') {
615*45326Sbostic fpos = 1.0/10.0;
616*45326Sbostic p++;
617*45326Sbostic while(isdigit(*p)) {
618*45326Sbostic acc += (*p - '0') * fpos;
619*45326Sbostic fpos *= 1.0/10.0;
620*45326Sbostic p++;
621*45326Sbostic }
622*45326Sbostic }
623*45326Sbostic if (*p == 'e' || *p == 'E') {
624*45326Sbostic exp = 0;
625*45326Sbostic exps = 1;
626*45326Sbostic p++;
627*45326Sbostic if (*p == '+')
628*45326Sbostic p++;
629*45326Sbostic else if (*p == '-') {
630*45326Sbostic p++;
631*45326Sbostic exps = -1;
632*45326Sbostic }
633*45326Sbostic while(isdigit(*p)) {
634*45326Sbostic exp = exp * 10 + (*p - '0');
635*45326Sbostic p++;
636*45326Sbostic }
637*45326Sbostic }
638*45326Sbostic if (exp) {
639*45326Sbostic if (exps > 0)
640*45326Sbostic while (exp--)
641*45326Sbostic acc *= 10.0;
642*45326Sbostic else
643*45326Sbostic while (exp--)
644*45326Sbostic acc *= 1.0/10.0;
645*45326Sbostic }
646*45326Sbostic if (sign > 0)
647*45326Sbostic *res = acc;
648*45326Sbostic else
649*45326Sbostic *res = -acc;
650*45326Sbostic
651*45326Sbostic (void) signal(SIGFPE, sig_save);
652*45326Sbostic return(p);
653*45326Sbostic }
654