xref: /csrg-svn/contrib/sc/lex.c (revision 45326)
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