xref: /csrg-svn/usr.bin/tn3270/ascii/map3270.c (revision 31055)
1*31055Sminshall /*
2*31055Sminshall  *	Copyright (c) 1984, 1985, 1986 by the Regents of the
3*31055Sminshall  *	University of California and by Gregory Glenn Minshall.
4*31055Sminshall  *
5*31055Sminshall  *	Permission to use, copy, modify, and distribute these
6*31055Sminshall  *	programs and their documentation for any purpose and
7*31055Sminshall  *	without fee is hereby granted, provided that this
8*31055Sminshall  *	copyright and permission appear on all copies and
9*31055Sminshall  *	supporting documentation, the name of the Regents of
10*31055Sminshall  *	the University of California not be used in advertising
11*31055Sminshall  *	or publicity pertaining to distribution of the programs
12*31055Sminshall  *	without specific prior permission, and notice be given in
13*31055Sminshall  *	supporting documentation that copying and distribution is
14*31055Sminshall  *	by permission of the Regents of the University of California
15*31055Sminshall  *	and by Gregory Glenn Minshall.  Neither the Regents of the
16*31055Sminshall  *	University of California nor Gregory Glenn Minshall make
17*31055Sminshall  *	representations about the suitability of this software
18*31055Sminshall  *	for any purpose.  It is provided "as is" without
19*31055Sminshall  *	express or implied warranty.
20*31055Sminshall  */
21*31055Sminshall 
22*31055Sminshall #ifndef	lint
23*31055Sminshall static	char	sccsid[] = "@(#)map3270.c	3.1  10/29/86";
24*31055Sminshall #endif	/* ndef lint */
25*31055Sminshall 
26*31055Sminshall 
27*31055Sminshall /*	This program reads a description file, somewhat like /etc/termcap,
28*31055Sminshall     that describes the mapping between the current terminal's keyboard and
29*31055Sminshall     a 3270 keyboard.
30*31055Sminshall  */
31*31055Sminshall #ifdef DOCUMENTATION_ONLY
32*31055Sminshall /* here is a sample (very small) entry...
33*31055Sminshall 
34*31055Sminshall 	# this table is sensitive to position on a line.  In particular,
35*31055Sminshall 	# a terminal definition for a terminal is terminated whenever a
36*31055Sminshall 	# (non-comment) line beginning in column one is found.
37*31055Sminshall 	#
38*31055Sminshall 	# this is an entry to map tvi924 to 3270 keys...
39*31055Sminshall 	v8|tvi924|924|televideo model 924 {
40*31055Sminshall 		pfk1 =	'\E1';
41*31055Sminshall 		pfk2 =	'\E2';
42*31055Sminshall 		clear = '^z';		# clear the screen
43*31055Sminshall 	}
44*31055Sminshall  */
45*31055Sminshall #endif /* DOCUMENTATION_ONLY */
46*31055Sminshall 
47*31055Sminshall #include <stdio.h>
48*31055Sminshall #include <ctype.h>
49*31055Sminshall #include <curses.h>
50*31055Sminshall #include <strings.h>
51*31055Sminshall 
52*31055Sminshall #define	IsPrint(c)	((isprint(c) && !isspace(c)) || ((c) == ' '))
53*31055Sminshall 
54*31055Sminshall #define	LETS_SEE_ASCII
55*31055Sminshall #include "m4.out"
56*31055Sminshall 
57*31055Sminshall #include "state.h"
58*31055Sminshall 
59*31055Sminshall #include "../system/globals.h"
60*31055Sminshall #include "map3270.ext"
61*31055Sminshall 
62*31055Sminshall /* this is the list of types returned by the lex processor */
63*31055Sminshall #define	LEX_CHAR	TC_HIGHEST		/* plain unadorned character */
64*31055Sminshall #define	LEX_ESCAPED	LEX_CHAR+1		/* escaped with \ */
65*31055Sminshall #define	LEX_CARETED	LEX_ESCAPED+1		/* escaped with ^ */
66*31055Sminshall #define	LEX_END_OF_FILE LEX_CARETED+1		/* end of file encountered */
67*31055Sminshall #define	LEX_ILLEGAL	LEX_END_OF_FILE+1	/* trailing escape character */
68*31055Sminshall 
69*31055Sminshall /* the following is part of our character set dependancy... */
70*31055Sminshall #define	ESCAPE		0x1b
71*31055Sminshall #define	TAB		0x09
72*31055Sminshall #define	NEWLINE 	0x0a
73*31055Sminshall #define	CARRIAGE_RETURN 0x0d
74*31055Sminshall 
75*31055Sminshall typedef struct {
76*31055Sminshall     int type;		/* LEX_* - type of character */
77*31055Sminshall     int value;		/* character this was */
78*31055Sminshall } lexicon;
79*31055Sminshall 
80*31055Sminshall typedef struct {
81*31055Sminshall     int		length;		/* length of character string */
82*31055Sminshall     char	array[500];	/* character string */
83*31055Sminshall } stringWithLength;
84*31055Sminshall 
85*31055Sminshall #define	panic(s)	{ fprintf(stderr, s); exit(1); }
86*31055Sminshall 
87*31055Sminshall static state firstentry = { 0, TC_NULL, 0, 0 };
88*31055Sminshall static state *headOfQueue = &firstentry;
89*31055Sminshall 
90*31055Sminshall /* the following is a primitive adm3a table, to be used when nothing
91*31055Sminshall  * else seems to be avaliable.
92*31055Sminshall  */
93*31055Sminshall 
94*31055Sminshall #ifdef	DEBUG
95*31055Sminshall static int debug = 0;		/* debug flag (for debuggin tables) */
96*31055Sminshall #endif	/* DEBUG */
97*31055Sminshall 
98*31055Sminshall static int doPaste = 1;			/* should we have side effects */
99*31055Sminshall static int picky = 0;			/* do we complain of unknown TC's? */
100*31055Sminshall static char usePointer = 0;		/* use pointer, or file */
101*31055Sminshall static FILE *ourFile= 0;
102*31055Sminshall static char *environPointer = 0;	/* if non-zero, point to input
103*31055Sminshall 					 * string in core.
104*31055Sminshall 					 */
105*31055Sminshall static char keys3a[] =
106*31055Sminshall #include "default.map"		/* Define the default default */
107*31055Sminshall 			;
108*31055Sminshall 
109*31055Sminshall static	int	Empty = 1,		/* is the unget lifo empty? */
110*31055Sminshall 		Full = 0;		/* is the unget lifo full? */
111*31055Sminshall static	lexicon	lifo[200] = 0;		/* character stack for parser */
112*31055Sminshall static	int	rp = 0,			/* read pointer into lifo */
113*31055Sminshall 		wp = 0;			/* write pointer into lifo */
114*31055Sminshall 
115*31055Sminshall static int
116*31055Sminshall GetC()
117*31055Sminshall {
118*31055Sminshall     int character;
119*31055Sminshall 
120*31055Sminshall     if (usePointer) {
121*31055Sminshall 	if (*environPointer) {
122*31055Sminshall 	    character = 0xff&*environPointer++;
123*31055Sminshall 	} else {
124*31055Sminshall 	    static char suffix = 'A';
125*31055Sminshall 	    char envname[9];
126*31055Sminshall 	    extern char *getenv();
127*31055Sminshall 
128*31055Sminshall 	    (void) sprintf(envname, "MAP3270%c", suffix++);
129*31055Sminshall 	    environPointer = getenv(envname);
130*31055Sminshall 	    if (*environPointer) {
131*31055Sminshall 	       character = 0xff&*environPointer++;
132*31055Sminshall 	    } else {
133*31055Sminshall 	       character = EOF;
134*31055Sminshall 	    }
135*31055Sminshall 	}
136*31055Sminshall     } else {
137*31055Sminshall 	character = getc(ourFile);
138*31055Sminshall     }
139*31055Sminshall     return(character);
140*31055Sminshall }
141*31055Sminshall 
142*31055Sminshall static lexicon
143*31055Sminshall Get()
144*31055Sminshall {
145*31055Sminshall     lexicon c;
146*31055Sminshall     register lexicon *pC = &c;
147*31055Sminshall     register int character;
148*31055Sminshall 
149*31055Sminshall     if (!Empty) {
150*31055Sminshall 	*pC = lifo[rp];
151*31055Sminshall 	rp++;
152*31055Sminshall 	if (rp == sizeof lifo/sizeof (lexicon)) {
153*31055Sminshall 	    rp = 0;
154*31055Sminshall 	}
155*31055Sminshall 	if (rp == wp) {
156*31055Sminshall 	    Empty = 1;
157*31055Sminshall 	}
158*31055Sminshall 	Full = 0;
159*31055Sminshall     } else {
160*31055Sminshall 	character = GetC();
161*31055Sminshall 	switch (character) {
162*31055Sminshall 	case EOF:
163*31055Sminshall 	    pC->type = LEX_END_OF_FILE;
164*31055Sminshall 	    break;
165*31055Sminshall 	case '^':
166*31055Sminshall 	    character = GetC();
167*31055Sminshall 	    if (!IsPrint(character)) {
168*31055Sminshall 		pC->type = LEX_ILLEGAL;
169*31055Sminshall 	    } else {
170*31055Sminshall 		pC->type = LEX_CARETED;
171*31055Sminshall 		if (character == '?') {
172*31055Sminshall 		    character |= 0x40;	/* rubout */
173*31055Sminshall 		} else {
174*31055Sminshall 		    character &= 0x1f;
175*31055Sminshall 		}
176*31055Sminshall 	    }
177*31055Sminshall 	    break;
178*31055Sminshall 	case '\\':
179*31055Sminshall 	    character = GetC();
180*31055Sminshall 	    if (!IsPrint(character)) {
181*31055Sminshall 		pC->type = LEX_ILLEGAL;
182*31055Sminshall 	    } else {
183*31055Sminshall 		pC->type = LEX_ESCAPED;
184*31055Sminshall 		switch (character) {
185*31055Sminshall 		case 'E': case 'e':
186*31055Sminshall 		    character = ESCAPE;
187*31055Sminshall 		    break;
188*31055Sminshall 		case 't':
189*31055Sminshall 		    character = TAB;
190*31055Sminshall 		    break;
191*31055Sminshall 		case 'n':
192*31055Sminshall 		    character = NEWLINE;
193*31055Sminshall 		    break;
194*31055Sminshall 		case 'r':
195*31055Sminshall 		    character = CARRIAGE_RETURN;
196*31055Sminshall 		    break;
197*31055Sminshall 		default:
198*31055Sminshall 		    pC->type = LEX_ILLEGAL;
199*31055Sminshall 		    break;
200*31055Sminshall 		}
201*31055Sminshall 	    }
202*31055Sminshall 	    break;
203*31055Sminshall 	default:
204*31055Sminshall 	    if ((IsPrint(character)) || isspace(character)) {
205*31055Sminshall 		pC->type = LEX_CHAR;
206*31055Sminshall 	    } else {
207*31055Sminshall 		pC->type = LEX_ILLEGAL;
208*31055Sminshall 	    }
209*31055Sminshall 	    break;
210*31055Sminshall 	}
211*31055Sminshall 	pC->value = character;
212*31055Sminshall     }
213*31055Sminshall     return(*pC);
214*31055Sminshall }
215*31055Sminshall 
216*31055Sminshall static void
217*31055Sminshall UnGet(c)
218*31055Sminshall lexicon c;			/* character to unget */
219*31055Sminshall {
220*31055Sminshall     if (Full) {
221*31055Sminshall 	fprintf(stderr, "attempt to put too many characters in lifo\n");
222*31055Sminshall 	panic("map3270");
223*31055Sminshall 	/* NOTREACHED */
224*31055Sminshall     } else {
225*31055Sminshall 	lifo[wp] = c;
226*31055Sminshall 	wp++;
227*31055Sminshall 	if (wp == sizeof lifo/sizeof (lexicon)) {
228*31055Sminshall 	    wp = 0;
229*31055Sminshall 	}
230*31055Sminshall 	if (wp == rp) {
231*31055Sminshall 	    Full = 1;
232*31055Sminshall 	}
233*31055Sminshall 	Empty = 0;
234*31055Sminshall     }
235*31055Sminshall }
236*31055Sminshall 
237*31055Sminshall /* compare two strings, ignoring case */
238*31055Sminshall 
239*31055Sminshall ustrcmp(string1, string2)
240*31055Sminshall register char *string1;
241*31055Sminshall register char *string2;
242*31055Sminshall {
243*31055Sminshall     register int c1, c2;
244*31055Sminshall 
245*31055Sminshall     while ((c1 = (unsigned char) *string1++) != 0) {
246*31055Sminshall 	if (isupper(c1)) {
247*31055Sminshall 	    c1 = tolower(c1);
248*31055Sminshall 	}
249*31055Sminshall 	if (isupper(c2 = (unsigned char) *string2++)) {
250*31055Sminshall 	    c2 = tolower(c2);
251*31055Sminshall 	}
252*31055Sminshall 	if (c1 < c2) {
253*31055Sminshall 	    return(-1);
254*31055Sminshall 	} else if (c1 > c2) {
255*31055Sminshall 	    return(1);
256*31055Sminshall 	}
257*31055Sminshall     }
258*31055Sminshall     if (*string2) {
259*31055Sminshall 	return(-1);
260*31055Sminshall     } else {
261*31055Sminshall 	return(0);
262*31055Sminshall     }
263*31055Sminshall }
264*31055Sminshall 
265*31055Sminshall 
266*31055Sminshall static stringWithLength *
267*31055Sminshall GetQuotedString()
268*31055Sminshall {
269*31055Sminshall     lexicon lex;
270*31055Sminshall     static stringWithLength output = { 0 };	/* where return value is held */
271*31055Sminshall     char *pointer = output.array;
272*31055Sminshall 
273*31055Sminshall     lex = Get();
274*31055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != '\'')) {
275*31055Sminshall 	UnGet(lex);
276*31055Sminshall 	return(0);
277*31055Sminshall     }
278*31055Sminshall     while (1) {
279*31055Sminshall 	lex = Get();
280*31055Sminshall 	if ((lex.type == LEX_CHAR) && (lex.value == '\'')) {
281*31055Sminshall 	    break;
282*31055Sminshall 	}
283*31055Sminshall 	if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) {
284*31055Sminshall 	    UnGet(lex);
285*31055Sminshall 	    return(0);		/* illegal character in quoted string */
286*31055Sminshall 	}
287*31055Sminshall 	if (pointer >= output.array+sizeof output.array) {
288*31055Sminshall 	    return(0);		/* too long */
289*31055Sminshall 	}
290*31055Sminshall 	*pointer++ = lex.value;
291*31055Sminshall     }
292*31055Sminshall     output.length = pointer-output.array;
293*31055Sminshall     return(&output);
294*31055Sminshall }
295*31055Sminshall 
296*31055Sminshall #ifdef	NOTUSED
297*31055Sminshall static stringWithLength *
298*31055Sminshall GetCharString()
299*31055Sminshall {
300*31055Sminshall     lexicon lex;
301*31055Sminshall     static stringWithLength output;
302*31055Sminshall     char *pointer = output.array;
303*31055Sminshall 
304*31055Sminshall     lex = Get();
305*31055Sminshall 
306*31055Sminshall     while ((lex.type == LEX_CHAR) &&
307*31055Sminshall 			!isspace(lex.value) && (lex.value != '=')) {
308*31055Sminshall 	*pointer++ = lex.value;
309*31055Sminshall 	lex = Get();
310*31055Sminshall 	if (pointer >= output.array + sizeof output.array) {
311*31055Sminshall 	    return(0);		/* too long */
312*31055Sminshall 	}
313*31055Sminshall     }
314*31055Sminshall     UnGet(lex);
315*31055Sminshall     output.length = pointer-output.array;
316*31055Sminshall     return(&output);
317*31055Sminshall }
318*31055Sminshall #endif	/* NOTUSED */
319*31055Sminshall 
320*31055Sminshall static
321*31055Sminshall GetCharacter(character)
322*31055Sminshall int	character;		/* desired character */
323*31055Sminshall {
324*31055Sminshall     lexicon lex;
325*31055Sminshall 
326*31055Sminshall     lex = Get();
327*31055Sminshall 
328*31055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != character)) {
329*31055Sminshall 	UnGet(lex);
330*31055Sminshall 	return(0);
331*31055Sminshall     }
332*31055Sminshall     return(1);
333*31055Sminshall }
334*31055Sminshall 
335*31055Sminshall #ifdef	NOTUSED
336*31055Sminshall static
337*31055Sminshall GetString(string)
338*31055Sminshall char	*string;		/* string to get */
339*31055Sminshall {
340*31055Sminshall     lexicon lex;
341*31055Sminshall 
342*31055Sminshall     while (*string) {
343*31055Sminshall 	lex = Get();
344*31055Sminshall 	if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) {
345*31055Sminshall 	    UnGet(lex);
346*31055Sminshall 	    return(0);		/* XXX restore to state on entry */
347*31055Sminshall 	}
348*31055Sminshall 	string++;
349*31055Sminshall     }
350*31055Sminshall     return(1);
351*31055Sminshall }
352*31055Sminshall #endif	/* NOTUSED */
353*31055Sminshall 
354*31055Sminshall 
355*31055Sminshall static stringWithLength *
356*31055Sminshall GetAlphaMericString()
357*31055Sminshall {
358*31055Sminshall     lexicon lex;
359*31055Sminshall     static stringWithLength output = { 0 };
360*31055Sminshall     char *pointer = output.array;
361*31055Sminshall #   define	IsAlnum(c)	(isalnum(c) || (c == '_') \
362*31055Sminshall 					|| (c == '-') || (c == '.'))
363*31055Sminshall 
364*31055Sminshall     lex = Get();
365*31055Sminshall 
366*31055Sminshall     if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) {
367*31055Sminshall 	UnGet(lex);
368*31055Sminshall 	return(0);
369*31055Sminshall     }
370*31055Sminshall 
371*31055Sminshall     while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) {
372*31055Sminshall 	*pointer++ = lex.value;
373*31055Sminshall 	lex = Get();
374*31055Sminshall     }
375*31055Sminshall     UnGet(lex);
376*31055Sminshall     *pointer = 0;
377*31055Sminshall     output.length = pointer-output.array;
378*31055Sminshall     return(&output);
379*31055Sminshall }
380*31055Sminshall 
381*31055Sminshall 
382*31055Sminshall /* eat up characters until a new line, or end of file.  returns terminating
383*31055Sminshall 	character.
384*31055Sminshall  */
385*31055Sminshall 
386*31055Sminshall static lexicon
387*31055Sminshall EatToNL()
388*31055Sminshall {
389*31055Sminshall     lexicon lex;
390*31055Sminshall 
391*31055Sminshall     lex = Get();
392*31055Sminshall 
393*31055Sminshall     while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) &&
394*31055Sminshall 		(lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) {
395*31055Sminshall 	lex = Get();
396*31055Sminshall     }
397*31055Sminshall     if (lex.type != LEX_END_OF_FILE) {
398*31055Sminshall 	return(Get());
399*31055Sminshall     } else {
400*31055Sminshall 	return(lex);
401*31055Sminshall     }
402*31055Sminshall }
403*31055Sminshall 
404*31055Sminshall 
405*31055Sminshall static void
406*31055Sminshall GetWS()
407*31055Sminshall {
408*31055Sminshall     lexicon lex;
409*31055Sminshall 
410*31055Sminshall     lex = Get();
411*31055Sminshall 
412*31055Sminshall     while ((lex.type == LEX_CHAR) &&
413*31055Sminshall 			(isspace(lex.value) || (lex.value == '#'))) {
414*31055Sminshall 	if (lex.value == '#') {
415*31055Sminshall 	    lex = EatToNL();
416*31055Sminshall 	} else {
417*31055Sminshall 	    lex = Get();
418*31055Sminshall 	}
419*31055Sminshall     }
420*31055Sminshall     UnGet(lex);
421*31055Sminshall }
422*31055Sminshall 
423*31055Sminshall static void
424*31055Sminshall FreeState(pState)
425*31055Sminshall state *pState;
426*31055Sminshall {
427*31055Sminshall     extern void free();
428*31055Sminshall 
429*31055Sminshall     free((char *)pState);
430*31055Sminshall }
431*31055Sminshall 
432*31055Sminshall 
433*31055Sminshall static state *
434*31055Sminshall GetState()
435*31055Sminshall {
436*31055Sminshall     state *pState;
437*31055Sminshall     extern char *malloc();
438*31055Sminshall 
439*31055Sminshall     pState = (state *) malloc(sizeof (state));
440*31055Sminshall 
441*31055Sminshall     pState->result = TC_NULL;
442*31055Sminshall     pState->next = 0;
443*31055Sminshall 
444*31055Sminshall     return(pState);
445*31055Sminshall }
446*31055Sminshall 
447*31055Sminshall 
448*31055Sminshall static state *
449*31055Sminshall FindMatchAtThisLevel(pState, character)
450*31055Sminshall state	*pState;
451*31055Sminshall int	character;
452*31055Sminshall {
453*31055Sminshall     while (pState) {
454*31055Sminshall 	if (pState->match == character) {
455*31055Sminshall 	    return(pState);
456*31055Sminshall 	}
457*31055Sminshall 	pState = pState->next;
458*31055Sminshall     }
459*31055Sminshall     return(0);
460*31055Sminshall }
461*31055Sminshall 
462*31055Sminshall 
463*31055Sminshall static state *
464*31055Sminshall PasteEntry(head, string, count, identifier)
465*31055Sminshall state			*head;		/* points to who should point here... */
466*31055Sminshall char			*string;	/* which characters to paste */
467*31055Sminshall int			count;		/* number of character to do */
468*31055Sminshall char			*identifier;	/* for error messages */
469*31055Sminshall {
470*31055Sminshall     state *pState, *other;
471*31055Sminshall 
472*31055Sminshall     if (!doPaste) {		/* flag to not have any side effects */
473*31055Sminshall 	return((state *)1);
474*31055Sminshall     }
475*31055Sminshall     if (!count) {
476*31055Sminshall 	return(head);	/* return pointer to the parent */
477*31055Sminshall     }
478*31055Sminshall     if ((head->result != TC_NULL) && (head->result != TC_GOTO)) {
479*31055Sminshall 	/* this means that a previously defined sequence is an initial
480*31055Sminshall 	 * part of this one.
481*31055Sminshall 	 */
482*31055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
483*31055Sminshall 		identifier);
484*31055Sminshall 	return(0);
485*31055Sminshall     }
486*31055Sminshall #   ifdef	DEBUG
487*31055Sminshall 	if (debug) {
488*31055Sminshall 	    fprintf(stderr, "%s", unctrl(*string));
489*31055Sminshall 	}
490*31055Sminshall #   endif	/* DEBUG */
491*31055Sminshall     pState = GetState();
492*31055Sminshall     pState->match = *string;
493*31055Sminshall     if (head->result == TC_NULL) {
494*31055Sminshall 	head->result = TC_GOTO;
495*31055Sminshall 	head->address = pState;
496*31055Sminshall 	other = pState;
497*31055Sminshall     } else {		/* search for same character */
498*31055Sminshall 	if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) {
499*31055Sminshall 	    FreeState(pState);
500*31055Sminshall 	} else {
501*31055Sminshall 	    pState->next = head->address;
502*31055Sminshall 	    head->address = pState;
503*31055Sminshall 	    other = pState;
504*31055Sminshall 	}
505*31055Sminshall     }
506*31055Sminshall     return(PasteEntry(other, string+1, count-1, identifier));
507*31055Sminshall }
508*31055Sminshall 
509*31055Sminshall static
510*31055Sminshall GetInput(tc, identifier)
511*31055Sminshall int tc;
512*31055Sminshall char *identifier;		/* entry being parsed (for error messages) */
513*31055Sminshall {
514*31055Sminshall     stringWithLength *outputString;
515*31055Sminshall     state *head;
516*31055Sminshall     state fakeQueue;
517*31055Sminshall 
518*31055Sminshall     if (doPaste) {
519*31055Sminshall 	head = headOfQueue;	/* always points to level above this one */
520*31055Sminshall     } else {
521*31055Sminshall 	head = &fakeQueue;	/* don't have any side effects... */
522*31055Sminshall     }
523*31055Sminshall 
524*31055Sminshall     if ((outputString = GetQuotedString()) == 0) {
525*31055Sminshall 	return(0);
526*31055Sminshall     } else if (IsPrint(outputString->array[0])) {
527*31055Sminshall 	fprintf(stderr,
528*31055Sminshall 	 "first character of sequence for %s is not a control type character\n",
529*31055Sminshall 		identifier);
530*31055Sminshall 	return(0);
531*31055Sminshall     } else {
532*31055Sminshall 	if ((head = PasteEntry(head, outputString->array,
533*31055Sminshall 				outputString->length, identifier)) == 0) {
534*31055Sminshall 	    return(0);
535*31055Sminshall 	}
536*31055Sminshall 	GetWS();
537*31055Sminshall 	while ((outputString = GetQuotedString()) != 0) {
538*31055Sminshall 	    if ((head = PasteEntry(head, outputString->array,
539*31055Sminshall 				outputString->length, identifier)) == 0) {
540*31055Sminshall 		return(0);
541*31055Sminshall 	    }
542*31055Sminshall 	    GetWS();
543*31055Sminshall 	}
544*31055Sminshall     }
545*31055Sminshall     if (!doPaste) {
546*31055Sminshall 	return(1);
547*31055Sminshall     }
548*31055Sminshall     if ((head->result != TC_NULL) && (head->result != tc)) {
549*31055Sminshall 	/* this means that this sequence is an initial part
550*31055Sminshall 	 * of a previously defined one.
551*31055Sminshall 	 */
552*31055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
553*31055Sminshall 		identifier);
554*31055Sminshall 	return(0);
555*31055Sminshall     } else {
556*31055Sminshall 	head->result = tc;
557*31055Sminshall 	return(1);		/* done */
558*31055Sminshall     }
559*31055Sminshall }
560*31055Sminshall 
561*31055Sminshall static
562*31055Sminshall GetTc(string)
563*31055Sminshall char *string;
564*31055Sminshall {
565*31055Sminshall     register TC_Ascii_t *Tc;
566*31055Sminshall 
567*31055Sminshall     for (Tc = TC_Ascii;
568*31055Sminshall 		Tc < TC_Ascii+sizeof TC_Ascii/sizeof (TC_Ascii_t); Tc++) {
569*31055Sminshall 	if (!ustrcmp(string, Tc->tc_name)) {
570*31055Sminshall #	    ifdef	DEBUG
571*31055Sminshall 		if (debug) {
572*31055Sminshall 		    fprintf(stderr, "%s = ", Tc->tc_name);
573*31055Sminshall 		}
574*31055Sminshall #	    endif	/* DEBUG */
575*31055Sminshall 	    return(Tc->tc_value&0xff);
576*31055Sminshall 	}
577*31055Sminshall     }
578*31055Sminshall     return(0);
579*31055Sminshall }
580*31055Sminshall static
581*31055Sminshall GetDefinition()
582*31055Sminshall {
583*31055Sminshall     stringWithLength *string;
584*31055Sminshall     int Tc;
585*31055Sminshall 
586*31055Sminshall     GetWS();
587*31055Sminshall     if ((string = GetAlphaMericString()) == 0) {
588*31055Sminshall 	return(0);
589*31055Sminshall     }
590*31055Sminshall     string->array[string->length] = 0;
591*31055Sminshall     if (doPaste) {
592*31055Sminshall 	if ((Tc = GetTc(string->array)) == 0) {
593*31055Sminshall 	    if (picky) {
594*31055Sminshall 		fprintf(stderr, "%s: unknown 3270 key identifier\n",
595*31055Sminshall 							string->array);
596*31055Sminshall 	    }
597*31055Sminshall 	    Tc = TC_NULL;
598*31055Sminshall 	} else if (Tc < TC_LOWEST_USER) {
599*31055Sminshall 	    fprintf(stderr, "%s is not allowed to be specified by a user.\n",
600*31055Sminshall 			string->array);
601*31055Sminshall 	    return(0);
602*31055Sminshall 	}
603*31055Sminshall     } else {
604*31055Sminshall 	Tc = TC_LOWEST_USER;
605*31055Sminshall     }
606*31055Sminshall     GetWS();
607*31055Sminshall     if (!GetCharacter('=')) {
608*31055Sminshall 	fprintf(stderr,
609*31055Sminshall 		"Required equal sign after 3270 key identifier %s missing\n",
610*31055Sminshall 			string->array);
611*31055Sminshall 	return(0);
612*31055Sminshall     }
613*31055Sminshall     GetWS();
614*31055Sminshall     if (!GetInput(Tc, string->array)) {
615*31055Sminshall 	fprintf(stderr, "Missing definition part for 3270 key %s\n",
616*31055Sminshall 				string->array);
617*31055Sminshall 	return(0);
618*31055Sminshall     } else {
619*31055Sminshall 	GetWS();
620*31055Sminshall 	while (GetCharacter('|')) {
621*31055Sminshall #	    ifdef	DEBUG
622*31055Sminshall 		if (debug) {
623*31055Sminshall 		    fprintf(stderr, " or ");
624*31055Sminshall 		}
625*31055Sminshall #	    endif	/* DEBUG */
626*31055Sminshall 	    GetWS();
627*31055Sminshall 	    if (!GetInput(Tc, string->array)) {
628*31055Sminshall 		fprintf(stderr, "Missing definition part for 3270 key %s\n",
629*31055Sminshall 					string->array);
630*31055Sminshall 		return(0);
631*31055Sminshall 	    }
632*31055Sminshall 	    GetWS();
633*31055Sminshall 	}
634*31055Sminshall     }
635*31055Sminshall     GetWS();
636*31055Sminshall     if (!GetCharacter(';')) {
637*31055Sminshall 	fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array);
638*31055Sminshall 	return(0);
639*31055Sminshall     }
640*31055Sminshall #   ifdef	DEBUG
641*31055Sminshall 	if (debug) {
642*31055Sminshall 	    fprintf(stderr, ";\n");
643*31055Sminshall 	}
644*31055Sminshall #   endif	/* DEBUG */
645*31055Sminshall     return(1);
646*31055Sminshall }
647*31055Sminshall 
648*31055Sminshall 
649*31055Sminshall static
650*31055Sminshall GetDefinitions()
651*31055Sminshall {
652*31055Sminshall     if (!GetDefinition()) {
653*31055Sminshall 	return(0);
654*31055Sminshall     } else {
655*31055Sminshall 	while (GetDefinition()) {
656*31055Sminshall 	    ;
657*31055Sminshall 	}
658*31055Sminshall     }
659*31055Sminshall     return(1);
660*31055Sminshall }
661*31055Sminshall 
662*31055Sminshall static
663*31055Sminshall GetBegin()
664*31055Sminshall {
665*31055Sminshall     GetWS();
666*31055Sminshall     if (!GetCharacter('{')) {
667*31055Sminshall 	return(0);
668*31055Sminshall     }
669*31055Sminshall     return(1);
670*31055Sminshall }
671*31055Sminshall 
672*31055Sminshall static
673*31055Sminshall GetEnd()
674*31055Sminshall {
675*31055Sminshall     GetWS();
676*31055Sminshall     if (!GetCharacter('}')) {
677*31055Sminshall 	return(0);
678*31055Sminshall     }
679*31055Sminshall     return(1);
680*31055Sminshall }
681*31055Sminshall 
682*31055Sminshall static
683*31055Sminshall GetName()
684*31055Sminshall {
685*31055Sminshall     if (!GetAlphaMericString()) {
686*31055Sminshall 	return(0);
687*31055Sminshall     }
688*31055Sminshall     GetWS();
689*31055Sminshall     while (GetAlphaMericString()) {
690*31055Sminshall 	GetWS();
691*31055Sminshall     }
692*31055Sminshall     return(1);
693*31055Sminshall }
694*31055Sminshall 
695*31055Sminshall static
696*31055Sminshall GetNames()
697*31055Sminshall {
698*31055Sminshall     GetWS();
699*31055Sminshall     if (!GetName()) {
700*31055Sminshall 	return(0);
701*31055Sminshall     } else {
702*31055Sminshall 	GetWS();
703*31055Sminshall 	while (GetCharacter('|')) {
704*31055Sminshall 	    GetWS();
705*31055Sminshall 	    if (!GetName()) {
706*31055Sminshall 		return(0);
707*31055Sminshall 	    }
708*31055Sminshall 	}
709*31055Sminshall     }
710*31055Sminshall     return(1);
711*31055Sminshall }
712*31055Sminshall 
713*31055Sminshall static
714*31055Sminshall GetEntry0()
715*31055Sminshall {
716*31055Sminshall     if (!GetBegin()) {
717*31055Sminshall 	fprintf(stderr, "no '{'\n");
718*31055Sminshall 	return(0);
719*31055Sminshall     } else if (!GetDefinitions()) {
720*31055Sminshall 	fprintf(stderr, "unable to parse the definitions\n");
721*31055Sminshall 	return(0);
722*31055Sminshall     } else if (!GetEnd()) {
723*31055Sminshall 	fprintf(stderr, "No '}' or scanning stopped early due to error.\n");
724*31055Sminshall 	return(0);
725*31055Sminshall     } else {
726*31055Sminshall 	/* done */
727*31055Sminshall 	return(1);
728*31055Sminshall     }
729*31055Sminshall }
730*31055Sminshall 
731*31055Sminshall 
732*31055Sminshall static
733*31055Sminshall GetEntry()
734*31055Sminshall {
735*31055Sminshall     if (!GetNames()) {
736*31055Sminshall 	fprintf(stderr, "Invalid name field in entry.\n");
737*31055Sminshall 	return(0);
738*31055Sminshall     } else {
739*31055Sminshall 	return(GetEntry0());
740*31055Sminshall     }
741*31055Sminshall }
742*31055Sminshall 
743*31055Sminshall /* position ourselves within a given filename to the entry for the current
744*31055Sminshall  *	KEYBD (or TERM) variable
745*31055Sminshall  */
746*31055Sminshall 
747*31055Sminshall Position(filename, keybdPointer)
748*31055Sminshall char *filename;
749*31055Sminshall char *keybdPointer;
750*31055Sminshall {
751*31055Sminshall     lexicon lex;
752*31055Sminshall     stringWithLength *name = 0;
753*31055Sminshall     stringWithLength *oldName;
754*31055Sminshall #   define	Return(x) {doPaste = 1; return(x);}
755*31055Sminshall 
756*31055Sminshall     doPaste = 0;
757*31055Sminshall 
758*31055Sminshall     if ((ourFile = fopen(filename, "r")) == NULL) {
759*31055Sminshall #   if !defined(msdos)
760*31055Sminshall 	fprintf(stderr, "Unable to open file %s\n", filename);
761*31055Sminshall #   endif /* !defined(msdos) */
762*31055Sminshall 	Return(0);
763*31055Sminshall     }
764*31055Sminshall     lex = Get();
765*31055Sminshall     while (lex.type != LEX_END_OF_FILE) {
766*31055Sminshall 	UnGet(lex);
767*31055Sminshall 	/* now, find an entry that is our type. */
768*31055Sminshall 	GetWS();
769*31055Sminshall 	oldName = name;
770*31055Sminshall 	if ((name = GetAlphaMericString()) != 0) {
771*31055Sminshall 	    if (!ustrcmp(name->array, keybdPointer)) {
772*31055Sminshall 		/* need to make sure there is a name here... */
773*31055Sminshall 		lex.type = LEX_CHAR;
774*31055Sminshall 		lex.value = 'a';
775*31055Sminshall 		UnGet(lex);
776*31055Sminshall 		Return(1);
777*31055Sminshall 	    }
778*31055Sminshall 	} else if (GetCharacter('|')) {
779*31055Sminshall 	    ;		/* more names coming */
780*31055Sminshall 	} else {
781*31055Sminshall 	    lex = Get();
782*31055Sminshall 	    UnGet(lex);
783*31055Sminshall 	    if (lex.type != LEX_END_OF_FILE) {
784*31055Sminshall 		    if (!GetEntry0()) {	/* start of an entry */
785*31055Sminshall 			fprintf(stderr,
786*31055Sminshall 			    "error was in entry for %s in file %s\n",
787*31055Sminshall 			    (oldName)? oldName->array:"(unknown)", filename);
788*31055Sminshall 		    Return(0);
789*31055Sminshall 		}
790*31055Sminshall 	    }
791*31055Sminshall 	}
792*31055Sminshall 	lex = Get();
793*31055Sminshall     }
794*31055Sminshall #if !defined(msdos)
795*31055Sminshall     fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer,
796*31055Sminshall 		    filename);
797*31055Sminshall #endif	/* !defined(msdos) */
798*31055Sminshall     Return(0);
799*31055Sminshall }
800*31055Sminshall 
801*31055Sminshall char *
802*31055Sminshall strsave(string)
803*31055Sminshall char *string;
804*31055Sminshall {
805*31055Sminshall     char *p;
806*31055Sminshall     extern char *malloc();
807*31055Sminshall 
808*31055Sminshall     p = malloc(strlen(string)+1);
809*31055Sminshall     if (p != 0) {
810*31055Sminshall 	strcpy(p, string);
811*31055Sminshall     }
812*31055Sminshall     return(p);
813*31055Sminshall }
814*31055Sminshall 
815*31055Sminshall 
816*31055Sminshall /*
817*31055Sminshall  * InitControl - our interface to the outside.  What we should
818*31055Sminshall  *  do is figure out keyboard (or terminal) type, set up file pointer
819*31055Sminshall  *  (or string pointer), etc.
820*31055Sminshall  */
821*31055Sminshall 
822*31055Sminshall state *
823*31055Sminshall InitControl(keybdPointer, pickyarg)
824*31055Sminshall char	*keybdPointer;
825*31055Sminshall int	pickyarg;		/* Should we be picky? */
826*31055Sminshall {
827*31055Sminshall     extern char *getenv();
828*31055Sminshall     int GotIt;
829*31055Sminshall 
830*31055Sminshall     picky = pickyarg;
831*31055Sminshall 
832*31055Sminshall     if (keybdPointer == 0) {
833*31055Sminshall         keybdPointer = getenv("KEYBD");
834*31055Sminshall     }
835*31055Sminshall     if (keybdPointer == 0) {
836*31055Sminshall        keybdPointer = getenv("TERM");
837*31055Sminshall     }
838*31055Sminshall 
839*31055Sminshall 		    /*
840*31055Sminshall 		     * Some environments have getenv() return
841*31055Sminshall 		     * out of a static area.  So, save the keyboard name.
842*31055Sminshall 		     */
843*31055Sminshall     if (keybdPointer) {
844*31055Sminshall         keybdPointer = strsave(keybdPointer);
845*31055Sminshall     }
846*31055Sminshall     environPointer = getenv("MAP3270");
847*31055Sminshall     if (environPointer
848*31055Sminshall 	    && (environPointer[0] != '/')
849*31055Sminshall #if	defined(msdos)
850*31055Sminshall 	    && (environPointer[0] != '\\')
851*31055Sminshall #endif	defined(msdos)
852*31055Sminshall 	    && (strncmp(keybdPointer, environPointer,
853*31055Sminshall 			strlen(keybdPointer) != 0)
854*31055Sminshall 		|| (environPointer[strlen(keybdPointer)] != '{'))) /* } */
855*31055Sminshall     {
856*31055Sminshall 	environPointer = 0;
857*31055Sminshall     }
858*31055Sminshall 
859*31055Sminshall     if ((!environPointer)
860*31055Sminshall #if	defined(msdos)
861*31055Sminshall 		|| (*environPointer == '\\')
862*31055Sminshall #endif	/* defined(msdos) */
863*31055Sminshall 		|| (*environPointer == '/')) {
864*31055Sminshall 	usePointer = 0;
865*31055Sminshall 	GotIt = 0;
866*31055Sminshall 	if (!keybdPointer) {
867*31055Sminshall #if !defined(msdos)
868*31055Sminshall 	    fprintf(stderr, "%s%s%s%s",
869*31055Sminshall 		"Neither the KEYBD environment variable nor the TERM ",
870*31055Sminshall 		"environment variable\n(one of which is needed to determine ",
871*31055Sminshall 		"the type of keyboard you are using)\n",
872*31055Sminshall 		"is set.  To set it, say 'setenv KEYBD <type>'\n");
873*31055Sminshall #endif	/* !defined(msdos) */
874*31055Sminshall 	} else {
875*31055Sminshall 	    if (environPointer) {
876*31055Sminshall 		GotIt = Position(environPointer, keybdPointer);
877*31055Sminshall 	    }
878*31055Sminshall 	    if (!GotIt) {
879*31055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
880*31055Sminshall 	    }
881*31055Sminshall 	}
882*31055Sminshall 	if (!GotIt) {
883*31055Sminshall 	    if (environPointer) {
884*31055Sminshall 		GotIt = Position(environPointer, "unknown");
885*31055Sminshall 	    }
886*31055Sminshall 	    if (!GotIt) {
887*31055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
888*31055Sminshall 	    }
889*31055Sminshall 	}
890*31055Sminshall 	if (!GotIt) {
891*31055Sminshall #if !defined(msdos)
892*31055Sminshall 	    fprintf(stderr, "Using default key mappings.\n");
893*31055Sminshall #endif	/* !defined(msdos) */
894*31055Sminshall 	    environPointer = keys3a;	/* use incore table */
895*31055Sminshall 	    usePointer = 1;		/* flag use of non-file */
896*31055Sminshall 	}
897*31055Sminshall     } else {
898*31055Sminshall 	usePointer = 1;
899*31055Sminshall     }
900*31055Sminshall     (void) GetEntry();
901*31055Sminshall     return(firstentry.address);
902*31055Sminshall }
903