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