xref: /csrg-svn/usr.bin/tn3270/ascii/map3270.c (revision 31609)
131055Sminshall /*
231055Sminshall  *	Copyright (c) 1984, 1985, 1986 by the Regents of the
331055Sminshall  *	University of California and by Gregory Glenn Minshall.
431055Sminshall  *
531055Sminshall  *	Permission to use, copy, modify, and distribute these
631055Sminshall  *	programs and their documentation for any purpose and
731055Sminshall  *	without fee is hereby granted, provided that this
831055Sminshall  *	copyright and permission appear on all copies and
931055Sminshall  *	supporting documentation, the name of the Regents of
1031055Sminshall  *	the University of California not be used in advertising
1131055Sminshall  *	or publicity pertaining to distribution of the programs
1231055Sminshall  *	without specific prior permission, and notice be given in
1331055Sminshall  *	supporting documentation that copying and distribution is
1431055Sminshall  *	by permission of the Regents of the University of California
1531055Sminshall  *	and by Gregory Glenn Minshall.  Neither the Regents of the
1631055Sminshall  *	University of California nor Gregory Glenn Minshall make
1731055Sminshall  *	representations about the suitability of this software
1831055Sminshall  *	for any purpose.  It is provided "as is" without
1931055Sminshall  *	express or implied warranty.
2031055Sminshall  */
2131055Sminshall 
2231055Sminshall #ifndef	lint
2331055Sminshall static	char	sccsid[] = "@(#)map3270.c	3.1  10/29/86";
2431055Sminshall #endif	/* ndef lint */
2531055Sminshall 
2631055Sminshall 
2731055Sminshall /*	This program reads a description file, somewhat like /etc/termcap,
2831055Sminshall     that describes the mapping between the current terminal's keyboard and
2931055Sminshall     a 3270 keyboard.
3031055Sminshall  */
3131055Sminshall #ifdef DOCUMENTATION_ONLY
3231055Sminshall /* here is a sample (very small) entry...
3331055Sminshall 
3431055Sminshall 	# this table is sensitive to position on a line.  In particular,
3531055Sminshall 	# a terminal definition for a terminal is terminated whenever a
3631055Sminshall 	# (non-comment) line beginning in column one is found.
3731055Sminshall 	#
3831055Sminshall 	# this is an entry to map tvi924 to 3270 keys...
3931055Sminshall 	v8|tvi924|924|televideo model 924 {
4031055Sminshall 		pfk1 =	'\E1';
4131055Sminshall 		pfk2 =	'\E2';
4231055Sminshall 		clear = '^z';		# clear the screen
4331055Sminshall 	}
4431055Sminshall  */
4531055Sminshall #endif /* DOCUMENTATION_ONLY */
4631055Sminshall 
4731055Sminshall #include <stdio.h>
4831055Sminshall #include <ctype.h>
4931100Sminshall #if	defined(unix)
5031055Sminshall #include <strings.h>
5131100Sminshall #else	/* defined(unix) */
5231100Sminshall #include <string.h>
5331100Sminshall #endif	/* defined(unix) */
5431055Sminshall 
5531055Sminshall #define	IsPrint(c)	((isprint(c) && !isspace(c)) || ((c) == ' '))
5631055Sminshall 
5731055Sminshall #include "state.h"
5831055Sminshall 
5931176Sminshall #include "../general/globals.h"
6031055Sminshall #include "map3270.ext"
6131055Sminshall 
6231055Sminshall /* this is the list of types returned by the lex processor */
6331245Sminshall #define	LEX_CHAR	400			/* plain unadorned character */
6431055Sminshall #define	LEX_ESCAPED	LEX_CHAR+1		/* escaped with \ */
6531055Sminshall #define	LEX_CARETED	LEX_ESCAPED+1		/* escaped with ^ */
6631055Sminshall #define	LEX_END_OF_FILE LEX_CARETED+1		/* end of file encountered */
6731055Sminshall #define	LEX_ILLEGAL	LEX_END_OF_FILE+1	/* trailing escape character */
6831055Sminshall 
6931055Sminshall /* the following is part of our character set dependancy... */
7031055Sminshall #define	ESCAPE		0x1b
7131055Sminshall #define	TAB		0x09
7231055Sminshall #define	NEWLINE 	0x0a
7331055Sminshall #define	CARRIAGE_RETURN 0x0d
7431055Sminshall 
7531055Sminshall typedef struct {
7631055Sminshall     int type;		/* LEX_* - type of character */
7731055Sminshall     int value;		/* character this was */
7831055Sminshall } lexicon;
7931055Sminshall 
8031055Sminshall typedef struct {
8131055Sminshall     int		length;		/* length of character string */
8231055Sminshall     char	array[500];	/* character string */
8331055Sminshall } stringWithLength;
8431055Sminshall 
8531055Sminshall #define	panic(s)	{ fprintf(stderr, s); exit(1); }
8631055Sminshall 
8731245Sminshall static state firstentry = { 0, STATE_NULL, 0, 0 };
8831055Sminshall static state *headOfQueue = &firstentry;
8931055Sminshall 
9031055Sminshall /* the following is a primitive adm3a table, to be used when nothing
9131055Sminshall  * else seems to be avaliable.
9231055Sminshall  */
9331055Sminshall 
9431055Sminshall #ifdef	DEBUG
9531055Sminshall static int debug = 0;		/* debug flag (for debuggin tables) */
9631055Sminshall #endif	/* DEBUG */
9731055Sminshall 
9831245Sminshall static int (*GetTc)();
9931245Sminshall static int doPaste = 1;		/* should we have side effects */
10031245Sminshall static int picky = 0;		/* do we complain of unknown functions? */
10131245Sminshall static char usePointer = 0;	/* use pointer, or file */
10231055Sminshall static FILE *ourFile= 0;
10331245Sminshall static char *environPointer = 0;/* if non-zero, point to input
10431245Sminshall 				 * string in core.
10531245Sminshall 				 */
10631135Sminshall static char **whichkey = 0;
10731135Sminshall static char *keysgeneric[] = {
10831055Sminshall #include "default.map"		/* Define the default default */
10931135Sminshall 
11031135Sminshall 	0,			/* Terminate list of entries */
11131135Sminshall };
11231055Sminshall 			;
11331055Sminshall 
11431055Sminshall static	int	Empty = 1,		/* is the unget lifo empty? */
11531055Sminshall 		Full = 0;		/* is the unget lifo full? */
11631100Sminshall static	lexicon	lifo[200] = { 0 };	/* character stack for parser */
11731055Sminshall static	int	rp = 0,			/* read pointer into lifo */
11831055Sminshall 		wp = 0;			/* write pointer into lifo */
11931055Sminshall 
12031055Sminshall static int
12131055Sminshall GetC()
12231055Sminshall {
12331055Sminshall     int character;
12431055Sminshall 
12531055Sminshall     if (usePointer) {
12631135Sminshall 	if ((*environPointer) == 0) {
12731135Sminshall 	    /*
12831135Sminshall 	     * If we have reached the end of this string, go on to
12931135Sminshall 	     * the next (if there is a next).
13031135Sminshall 	     */
13131135Sminshall 	    if (whichkey == 0) {
13231135Sminshall 		static char suffix = 'A';	/* From environment */
13331135Sminshall 		char envname[9];
13431135Sminshall 		extern char *getenv();
13531055Sminshall 
13631135Sminshall 		(void) sprintf(envname, "MAP3270%c", suffix++);
13731135Sminshall 		environPointer = getenv(envname);
13831055Sminshall 	    } else {
13931135Sminshall 		whichkey++;			/* default map */
14031135Sminshall 		environPointer = *whichkey;
14131055Sminshall 	    }
14231055Sminshall 	}
14331135Sminshall 	if (*environPointer) {
14431135Sminshall 	   character = 0xff&*environPointer++;
14531135Sminshall 	} else {
14631135Sminshall 	   character = EOF;
14731135Sminshall 	}
14831055Sminshall     } else {
14931055Sminshall 	character = getc(ourFile);
15031055Sminshall     }
15131055Sminshall     return(character);
15231055Sminshall }
15331055Sminshall 
15431055Sminshall static lexicon
15531055Sminshall Get()
15631055Sminshall {
15731055Sminshall     lexicon c;
15831055Sminshall     register lexicon *pC = &c;
15931055Sminshall     register int character;
16031055Sminshall 
16131055Sminshall     if (!Empty) {
16231055Sminshall 	*pC = lifo[rp];
16331055Sminshall 	rp++;
16431055Sminshall 	if (rp == sizeof lifo/sizeof (lexicon)) {
16531055Sminshall 	    rp = 0;
16631055Sminshall 	}
16731055Sminshall 	if (rp == wp) {
16831055Sminshall 	    Empty = 1;
16931055Sminshall 	}
17031055Sminshall 	Full = 0;
17131055Sminshall     } else {
17231055Sminshall 	character = GetC();
17331055Sminshall 	switch (character) {
17431055Sminshall 	case EOF:
17531055Sminshall 	    pC->type = LEX_END_OF_FILE;
17631055Sminshall 	    break;
17731055Sminshall 	case '^':
17831055Sminshall 	    character = GetC();
17931055Sminshall 	    if (!IsPrint(character)) {
18031055Sminshall 		pC->type = LEX_ILLEGAL;
18131055Sminshall 	    } else {
18231055Sminshall 		pC->type = LEX_CARETED;
18331055Sminshall 		if (character == '?') {
18431055Sminshall 		    character |= 0x40;	/* rubout */
18531055Sminshall 		} else {
18631055Sminshall 		    character &= 0x1f;
18731055Sminshall 		}
18831055Sminshall 	    }
18931055Sminshall 	    break;
19031055Sminshall 	case '\\':
19131055Sminshall 	    character = GetC();
19231055Sminshall 	    if (!IsPrint(character)) {
19331055Sminshall 		pC->type = LEX_ILLEGAL;
19431055Sminshall 	    } else {
19531055Sminshall 		pC->type = LEX_ESCAPED;
19631055Sminshall 		switch (character) {
19731055Sminshall 		case 'E': case 'e':
19831055Sminshall 		    character = ESCAPE;
19931055Sminshall 		    break;
20031055Sminshall 		case 't':
20131055Sminshall 		    character = TAB;
20231055Sminshall 		    break;
20331055Sminshall 		case 'n':
20431055Sminshall 		    character = NEWLINE;
20531055Sminshall 		    break;
20631055Sminshall 		case 'r':
20731055Sminshall 		    character = CARRIAGE_RETURN;
20831055Sminshall 		    break;
20931055Sminshall 		default:
21031055Sminshall 		    pC->type = LEX_ILLEGAL;
21131055Sminshall 		    break;
21231055Sminshall 		}
21331055Sminshall 	    }
21431055Sminshall 	    break;
21531055Sminshall 	default:
21631055Sminshall 	    if ((IsPrint(character)) || isspace(character)) {
21731055Sminshall 		pC->type = LEX_CHAR;
21831055Sminshall 	    } else {
21931055Sminshall 		pC->type = LEX_ILLEGAL;
22031055Sminshall 	    }
22131055Sminshall 	    break;
22231055Sminshall 	}
22331055Sminshall 	pC->value = character;
22431055Sminshall     }
22531055Sminshall     return(*pC);
22631055Sminshall }
22731055Sminshall 
22831055Sminshall static void
22931055Sminshall UnGet(c)
23031055Sminshall lexicon c;			/* character to unget */
23131055Sminshall {
23231055Sminshall     if (Full) {
23331055Sminshall 	fprintf(stderr, "attempt to put too many characters in lifo\n");
23431055Sminshall 	panic("map3270");
23531055Sminshall 	/* NOTREACHED */
23631055Sminshall     } else {
23731055Sminshall 	lifo[wp] = c;
23831055Sminshall 	wp++;
23931055Sminshall 	if (wp == sizeof lifo/sizeof (lexicon)) {
24031055Sminshall 	    wp = 0;
24131055Sminshall 	}
24231055Sminshall 	if (wp == rp) {
24331055Sminshall 	    Full = 1;
24431055Sminshall 	}
24531055Sminshall 	Empty = 0;
24631055Sminshall     }
24731055Sminshall }
24831055Sminshall 
24931100Sminshall /*
25031100Sminshall  * Construct a control character sequence
25131100Sminshall  * for a special character.
25231100Sminshall  */
25331100Sminshall char *
25431100Sminshall uncontrol(c)
25531100Sminshall 	register int c;
25631100Sminshall {
25731100Sminshall 	static char buf[3];
25831100Sminshall 
25931100Sminshall 	if (c == 0x7f)
26031100Sminshall 		return ("^?");
26131100Sminshall 	if (c == '\377') {
26231100Sminshall 		return "-1";
26331100Sminshall 	}
26431100Sminshall 	if (c >= 0x20) {
26531100Sminshall 		buf[0] = c;
26631100Sminshall 		buf[1] = 0;
26731100Sminshall 	} else {
26831100Sminshall 		buf[0] = '^';
26931100Sminshall 		buf[1] = '@'+c;
27031100Sminshall 		buf[2] = 0;
27131100Sminshall 	}
27231100Sminshall 	return (buf);
27331100Sminshall }
27431100Sminshall 
27531055Sminshall /* compare two strings, ignoring case */
27631055Sminshall 
27731055Sminshall ustrcmp(string1, string2)
27831055Sminshall register char *string1;
27931055Sminshall register char *string2;
28031055Sminshall {
28131055Sminshall     register int c1, c2;
28231055Sminshall 
28331055Sminshall     while ((c1 = (unsigned char) *string1++) != 0) {
28431055Sminshall 	if (isupper(c1)) {
28531055Sminshall 	    c1 = tolower(c1);
28631055Sminshall 	}
28731055Sminshall 	if (isupper(c2 = (unsigned char) *string2++)) {
28831055Sminshall 	    c2 = tolower(c2);
28931055Sminshall 	}
29031055Sminshall 	if (c1 < c2) {
29131055Sminshall 	    return(-1);
29231055Sminshall 	} else if (c1 > c2) {
29331055Sminshall 	    return(1);
29431055Sminshall 	}
29531055Sminshall     }
29631055Sminshall     if (*string2) {
29731055Sminshall 	return(-1);
29831055Sminshall     } else {
29931055Sminshall 	return(0);
30031055Sminshall     }
30131055Sminshall }
30231055Sminshall 
30331055Sminshall 
30431055Sminshall static stringWithLength *
30531055Sminshall GetQuotedString()
30631055Sminshall {
30731055Sminshall     lexicon lex;
30831055Sminshall     static stringWithLength output = { 0 };	/* where return value is held */
30931055Sminshall     char *pointer = output.array;
31031055Sminshall 
31131055Sminshall     lex = Get();
31231055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != '\'')) {
31331055Sminshall 	UnGet(lex);
31431055Sminshall 	return(0);
31531055Sminshall     }
31631055Sminshall     while (1) {
31731055Sminshall 	lex = Get();
31831055Sminshall 	if ((lex.type == LEX_CHAR) && (lex.value == '\'')) {
31931055Sminshall 	    break;
32031055Sminshall 	}
32131055Sminshall 	if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) {
32231055Sminshall 	    UnGet(lex);
32331055Sminshall 	    return(0);		/* illegal character in quoted string */
32431055Sminshall 	}
32531055Sminshall 	if (pointer >= output.array+sizeof output.array) {
32631055Sminshall 	    return(0);		/* too long */
32731055Sminshall 	}
32831055Sminshall 	*pointer++ = lex.value;
32931055Sminshall     }
33031055Sminshall     output.length = pointer-output.array;
33131055Sminshall     return(&output);
33231055Sminshall }
33331055Sminshall 
33431055Sminshall #ifdef	NOTUSED
33531055Sminshall static stringWithLength *
33631055Sminshall GetCharString()
33731055Sminshall {
33831055Sminshall     lexicon lex;
33931055Sminshall     static stringWithLength output;
34031055Sminshall     char *pointer = output.array;
34131055Sminshall 
34231055Sminshall     lex = Get();
34331055Sminshall 
34431055Sminshall     while ((lex.type == LEX_CHAR) &&
34531055Sminshall 			!isspace(lex.value) && (lex.value != '=')) {
34631055Sminshall 	*pointer++ = lex.value;
34731055Sminshall 	lex = Get();
34831055Sminshall 	if (pointer >= output.array + sizeof output.array) {
34931055Sminshall 	    return(0);		/* too long */
35031055Sminshall 	}
35131055Sminshall     }
35231055Sminshall     UnGet(lex);
35331055Sminshall     output.length = pointer-output.array;
35431055Sminshall     return(&output);
35531055Sminshall }
35631055Sminshall #endif	/* NOTUSED */
35731055Sminshall 
35831055Sminshall static
35931055Sminshall GetCharacter(character)
36031055Sminshall int	character;		/* desired character */
36131055Sminshall {
36231055Sminshall     lexicon lex;
36331055Sminshall 
36431055Sminshall     lex = Get();
36531055Sminshall 
36631055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != character)) {
36731055Sminshall 	UnGet(lex);
36831055Sminshall 	return(0);
36931055Sminshall     }
37031055Sminshall     return(1);
37131055Sminshall }
37231055Sminshall 
37331055Sminshall #ifdef	NOTUSED
37431055Sminshall static
37531055Sminshall GetString(string)
37631055Sminshall char	*string;		/* string to get */
37731055Sminshall {
37831055Sminshall     lexicon lex;
37931055Sminshall 
38031055Sminshall     while (*string) {
38131055Sminshall 	lex = Get();
38231055Sminshall 	if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) {
38331055Sminshall 	    UnGet(lex);
38431055Sminshall 	    return(0);		/* XXX restore to state on entry */
38531055Sminshall 	}
38631055Sminshall 	string++;
38731055Sminshall     }
38831055Sminshall     return(1);
38931055Sminshall }
39031055Sminshall #endif	/* NOTUSED */
39131055Sminshall 
39231055Sminshall 
39331055Sminshall static stringWithLength *
39431055Sminshall GetAlphaMericString()
39531055Sminshall {
39631055Sminshall     lexicon lex;
39731055Sminshall     static stringWithLength output = { 0 };
39831055Sminshall     char *pointer = output.array;
39931055Sminshall #   define	IsAlnum(c)	(isalnum(c) || (c == '_') \
40031055Sminshall 					|| (c == '-') || (c == '.'))
40131055Sminshall 
40231055Sminshall     lex = Get();
40331055Sminshall 
40431055Sminshall     if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) {
40531055Sminshall 	UnGet(lex);
40631055Sminshall 	return(0);
40731055Sminshall     }
40831055Sminshall 
40931055Sminshall     while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) {
41031055Sminshall 	*pointer++ = lex.value;
41131055Sminshall 	lex = Get();
41231055Sminshall     }
41331055Sminshall     UnGet(lex);
41431055Sminshall     *pointer = 0;
41531055Sminshall     output.length = pointer-output.array;
41631055Sminshall     return(&output);
41731055Sminshall }
41831055Sminshall 
41931055Sminshall 
42031055Sminshall /* eat up characters until a new line, or end of file.  returns terminating
42131055Sminshall 	character.
42231055Sminshall  */
42331055Sminshall 
42431055Sminshall static lexicon
42531055Sminshall EatToNL()
42631055Sminshall {
42731055Sminshall     lexicon lex;
42831055Sminshall 
42931055Sminshall     lex = Get();
43031055Sminshall 
43131055Sminshall     while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) &&
43231055Sminshall 		(lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) {
43331055Sminshall 	lex = Get();
43431055Sminshall     }
43531055Sminshall     if (lex.type != LEX_END_OF_FILE) {
43631055Sminshall 	return(Get());
43731055Sminshall     } else {
43831055Sminshall 	return(lex);
43931055Sminshall     }
44031055Sminshall }
44131055Sminshall 
44231055Sminshall 
44331055Sminshall static void
44431055Sminshall GetWS()
44531055Sminshall {
44631055Sminshall     lexicon lex;
44731055Sminshall 
44831055Sminshall     lex = Get();
44931055Sminshall 
45031055Sminshall     while ((lex.type == LEX_CHAR) &&
45131055Sminshall 			(isspace(lex.value) || (lex.value == '#'))) {
45231055Sminshall 	if (lex.value == '#') {
45331055Sminshall 	    lex = EatToNL();
45431055Sminshall 	} else {
45531055Sminshall 	    lex = Get();
45631055Sminshall 	}
45731055Sminshall     }
45831055Sminshall     UnGet(lex);
45931055Sminshall }
46031055Sminshall 
46131055Sminshall static void
46231055Sminshall FreeState(pState)
46331055Sminshall state *pState;
46431055Sminshall {
46531055Sminshall     extern void free();
46631055Sminshall 
46731055Sminshall     free((char *)pState);
46831055Sminshall }
46931055Sminshall 
47031055Sminshall 
47131055Sminshall static state *
47231055Sminshall GetState()
47331055Sminshall {
47431055Sminshall     state *pState;
47531055Sminshall     extern char *malloc();
47631055Sminshall 
47731055Sminshall     pState = (state *) malloc(sizeof (state));
47831055Sminshall 
47931245Sminshall     pState->result = STATE_NULL;
48031055Sminshall     pState->next = 0;
48131055Sminshall 
48231055Sminshall     return(pState);
48331055Sminshall }
48431055Sminshall 
48531055Sminshall 
48631055Sminshall static state *
48731055Sminshall FindMatchAtThisLevel(pState, character)
48831055Sminshall state	*pState;
48931055Sminshall int	character;
49031055Sminshall {
49131055Sminshall     while (pState) {
49231055Sminshall 	if (pState->match == character) {
49331055Sminshall 	    return(pState);
49431055Sminshall 	}
49531055Sminshall 	pState = pState->next;
49631055Sminshall     }
49731055Sminshall     return(0);
49831055Sminshall }
49931055Sminshall 
50031055Sminshall 
50131055Sminshall static state *
50231055Sminshall PasteEntry(head, string, count, identifier)
50331055Sminshall state			*head;		/* points to who should point here... */
50431055Sminshall char			*string;	/* which characters to paste */
50531055Sminshall int			count;		/* number of character to do */
50631055Sminshall char			*identifier;	/* for error messages */
50731055Sminshall {
50831055Sminshall     state *pState, *other;
50931055Sminshall 
51031055Sminshall     if (!doPaste) {		/* flag to not have any side effects */
51131055Sminshall 	return((state *)1);
51231055Sminshall     }
51331055Sminshall     if (!count) {
51431055Sminshall 	return(head);	/* return pointer to the parent */
51531055Sminshall     }
51631245Sminshall     if ((head->result != STATE_NULL) && (head->result != STATE_GOTO)) {
51731055Sminshall 	/* this means that a previously defined sequence is an initial
51831055Sminshall 	 * part of this one.
51931055Sminshall 	 */
52031055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
52131055Sminshall 		identifier);
52231055Sminshall 	return(0);
52331055Sminshall     }
52431055Sminshall #   ifdef	DEBUG
52531055Sminshall 	if (debug) {
52631100Sminshall 	    fprintf(stderr, "%s", uncontrol(*string));
52731055Sminshall 	}
52831055Sminshall #   endif	/* DEBUG */
52931055Sminshall     pState = GetState();
53031055Sminshall     pState->match = *string;
53131245Sminshall     if (head->result == STATE_NULL) {
53231245Sminshall 	head->result = STATE_GOTO;
53331055Sminshall 	head->address = pState;
53431055Sminshall 	other = pState;
53531055Sminshall     } else {		/* search for same character */
53631055Sminshall 	if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) {
53731055Sminshall 	    FreeState(pState);
53831055Sminshall 	} else {
53931055Sminshall 	    pState->next = head->address;
54031055Sminshall 	    head->address = pState;
54131055Sminshall 	    other = pState;
54231055Sminshall 	}
54331055Sminshall     }
54431055Sminshall     return(PasteEntry(other, string+1, count-1, identifier));
54531055Sminshall }
54631055Sminshall 
54731055Sminshall static
54831055Sminshall GetInput(tc, identifier)
54931055Sminshall int tc;
55031055Sminshall char *identifier;		/* entry being parsed (for error messages) */
55131055Sminshall {
55231055Sminshall     stringWithLength *outputString;
55331055Sminshall     state *head;
55431055Sminshall     state fakeQueue;
55531055Sminshall 
55631055Sminshall     if (doPaste) {
55731055Sminshall 	head = headOfQueue;	/* always points to level above this one */
55831055Sminshall     } else {
55931055Sminshall 	head = &fakeQueue;	/* don't have any side effects... */
56031055Sminshall     }
56131055Sminshall 
56231055Sminshall     if ((outputString = GetQuotedString()) == 0) {
56331055Sminshall 	return(0);
56431055Sminshall     } else if (IsPrint(outputString->array[0])) {
56531055Sminshall 	fprintf(stderr,
56631055Sminshall 	 "first character of sequence for %s is not a control type character\n",
56731055Sminshall 		identifier);
56831055Sminshall 	return(0);
56931055Sminshall     } else {
57031055Sminshall 	if ((head = PasteEntry(head, outputString->array,
57131055Sminshall 				outputString->length, identifier)) == 0) {
57231055Sminshall 	    return(0);
57331055Sminshall 	}
57431055Sminshall 	GetWS();
57531055Sminshall 	while ((outputString = GetQuotedString()) != 0) {
57631055Sminshall 	    if ((head = PasteEntry(head, outputString->array,
57731055Sminshall 				outputString->length, identifier)) == 0) {
57831055Sminshall 		return(0);
57931055Sminshall 	    }
58031055Sminshall 	    GetWS();
58131055Sminshall 	}
58231055Sminshall     }
58331055Sminshall     if (!doPaste) {
58431055Sminshall 	return(1);
58531055Sminshall     }
58631245Sminshall     if ((head->result != STATE_NULL) && (head->result != tc)) {
58731055Sminshall 	/* this means that this sequence is an initial part
58831055Sminshall 	 * of a previously defined one.
58931055Sminshall 	 */
59031055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
59131055Sminshall 		identifier);
59231055Sminshall 	return(0);
59331055Sminshall     } else {
59431055Sminshall 	head->result = tc;
59531055Sminshall 	return(1);		/* done */
59631055Sminshall     }
59731055Sminshall }
59831055Sminshall 
59931055Sminshall static
60031055Sminshall GetDefinition()
60131055Sminshall {
60231055Sminshall     stringWithLength *string;
60331055Sminshall     int Tc;
60431055Sminshall 
60531055Sminshall     GetWS();
60631055Sminshall     if ((string = GetAlphaMericString()) == 0) {
60731055Sminshall 	return(0);
60831055Sminshall     }
60931055Sminshall     string->array[string->length] = 0;
61031055Sminshall     if (doPaste) {
611*31609Sminshall 	if ((Tc = (*GetTc)(string->array)) == -1) {
61231055Sminshall 	    if (picky) {
61331055Sminshall 		fprintf(stderr, "%s: unknown 3270 key identifier\n",
61431055Sminshall 							string->array);
61531055Sminshall 	    }
61631245Sminshall 	    Tc = STATE_NULL;
61731055Sminshall 	}
61831055Sminshall     } else {
61931245Sminshall 	Tc = STATE_NULL;		/* XXX ? */
62031055Sminshall     }
62131055Sminshall     GetWS();
62231055Sminshall     if (!GetCharacter('=')) {
62331055Sminshall 	fprintf(stderr,
62431055Sminshall 		"Required equal sign after 3270 key identifier %s missing\n",
62531055Sminshall 			string->array);
62631055Sminshall 	return(0);
62731055Sminshall     }
62831055Sminshall     GetWS();
62931055Sminshall     if (!GetInput(Tc, string->array)) {
63031055Sminshall 	fprintf(stderr, "Missing definition part for 3270 key %s\n",
63131055Sminshall 				string->array);
63231055Sminshall 	return(0);
63331055Sminshall     } else {
63431055Sminshall 	GetWS();
63531055Sminshall 	while (GetCharacter('|')) {
63631055Sminshall #	    ifdef	DEBUG
63731055Sminshall 		if (debug) {
63831055Sminshall 		    fprintf(stderr, " or ");
63931055Sminshall 		}
64031055Sminshall #	    endif	/* DEBUG */
64131055Sminshall 	    GetWS();
64231055Sminshall 	    if (!GetInput(Tc, string->array)) {
64331055Sminshall 		fprintf(stderr, "Missing definition part for 3270 key %s\n",
64431055Sminshall 					string->array);
64531055Sminshall 		return(0);
64631055Sminshall 	    }
64731055Sminshall 	    GetWS();
64831055Sminshall 	}
64931055Sminshall     }
65031055Sminshall     GetWS();
65131055Sminshall     if (!GetCharacter(';')) {
65231055Sminshall 	fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array);
65331055Sminshall 	return(0);
65431055Sminshall     }
65531055Sminshall #   ifdef	DEBUG
65631055Sminshall 	if (debug) {
65731055Sminshall 	    fprintf(stderr, ";\n");
65831055Sminshall 	}
65931055Sminshall #   endif	/* DEBUG */
66031055Sminshall     return(1);
66131055Sminshall }
66231055Sminshall 
66331055Sminshall 
66431055Sminshall static
66531055Sminshall GetDefinitions()
66631055Sminshall {
66731055Sminshall     if (!GetDefinition()) {
66831055Sminshall 	return(0);
66931055Sminshall     } else {
67031055Sminshall 	while (GetDefinition()) {
67131055Sminshall 	    ;
67231055Sminshall 	}
67331055Sminshall     }
67431055Sminshall     return(1);
67531055Sminshall }
67631055Sminshall 
67731055Sminshall static
67831055Sminshall GetBegin()
67931055Sminshall {
68031055Sminshall     GetWS();
68131055Sminshall     if (!GetCharacter('{')) {
68231055Sminshall 	return(0);
68331055Sminshall     }
68431055Sminshall     return(1);
68531055Sminshall }
68631055Sminshall 
68731055Sminshall static
68831055Sminshall GetEnd()
68931055Sminshall {
69031055Sminshall     GetWS();
69131055Sminshall     if (!GetCharacter('}')) {
69231055Sminshall 	return(0);
69331055Sminshall     }
69431055Sminshall     return(1);
69531055Sminshall }
69631055Sminshall 
69731055Sminshall static
69831055Sminshall GetName()
69931055Sminshall {
70031055Sminshall     if (!GetAlphaMericString()) {
70131055Sminshall 	return(0);
70231055Sminshall     }
70331055Sminshall     GetWS();
70431055Sminshall     while (GetAlphaMericString()) {
70531055Sminshall 	GetWS();
70631055Sminshall     }
70731055Sminshall     return(1);
70831055Sminshall }
70931055Sminshall 
71031055Sminshall static
71131055Sminshall GetNames()
71231055Sminshall {
71331055Sminshall     GetWS();
71431055Sminshall     if (!GetName()) {
71531055Sminshall 	return(0);
71631055Sminshall     } else {
71731055Sminshall 	GetWS();
71831055Sminshall 	while (GetCharacter('|')) {
71931055Sminshall 	    GetWS();
72031055Sminshall 	    if (!GetName()) {
72131055Sminshall 		return(0);
72231055Sminshall 	    }
72331055Sminshall 	}
72431055Sminshall     }
72531055Sminshall     return(1);
72631055Sminshall }
72731055Sminshall 
72831055Sminshall static
72931055Sminshall GetEntry0()
73031055Sminshall {
73131055Sminshall     if (!GetBegin()) {
73231055Sminshall 	fprintf(stderr, "no '{'\n");
73331055Sminshall 	return(0);
73431055Sminshall     } else if (!GetDefinitions()) {
73531055Sminshall 	fprintf(stderr, "unable to parse the definitions\n");
73631055Sminshall 	return(0);
73731055Sminshall     } else if (!GetEnd()) {
73831055Sminshall 	fprintf(stderr, "No '}' or scanning stopped early due to error.\n");
73931055Sminshall 	return(0);
74031055Sminshall     } else {
74131055Sminshall 	/* done */
74231055Sminshall 	return(1);
74331055Sminshall     }
74431055Sminshall }
74531055Sminshall 
74631055Sminshall 
74731055Sminshall static
74831055Sminshall GetEntry()
74931055Sminshall {
75031055Sminshall     if (!GetNames()) {
75131055Sminshall 	fprintf(stderr, "Invalid name field in entry.\n");
75231055Sminshall 	return(0);
75331055Sminshall     } else {
75431055Sminshall 	return(GetEntry0());
75531055Sminshall     }
75631055Sminshall }
75731055Sminshall 
75831055Sminshall /* position ourselves within a given filename to the entry for the current
75931055Sminshall  *	KEYBD (or TERM) variable
76031055Sminshall  */
76131055Sminshall 
76231055Sminshall Position(filename, keybdPointer)
76331055Sminshall char *filename;
76431055Sminshall char *keybdPointer;
76531055Sminshall {
76631055Sminshall     lexicon lex;
76731055Sminshall     stringWithLength *name = 0;
76831055Sminshall     stringWithLength *oldName;
76931055Sminshall #   define	Return(x) {doPaste = 1; return(x);}
77031055Sminshall 
77131055Sminshall     doPaste = 0;
77231055Sminshall 
77331055Sminshall     if ((ourFile = fopen(filename, "r")) == NULL) {
77431100Sminshall #   if !defined(MSDOS)
77531055Sminshall 	fprintf(stderr, "Unable to open file %s\n", filename);
77631100Sminshall #   endif /* !defined(MSDOS) */
77731055Sminshall 	Return(0);
77831055Sminshall     }
77931055Sminshall     lex = Get();
78031055Sminshall     while (lex.type != LEX_END_OF_FILE) {
78131055Sminshall 	UnGet(lex);
78231055Sminshall 	/* now, find an entry that is our type. */
78331055Sminshall 	GetWS();
78431055Sminshall 	oldName = name;
78531055Sminshall 	if ((name = GetAlphaMericString()) != 0) {
78631055Sminshall 	    if (!ustrcmp(name->array, keybdPointer)) {
78731055Sminshall 		/* need to make sure there is a name here... */
78831055Sminshall 		lex.type = LEX_CHAR;
78931055Sminshall 		lex.value = 'a';
79031055Sminshall 		UnGet(lex);
79131055Sminshall 		Return(1);
79231055Sminshall 	    }
79331055Sminshall 	} else if (GetCharacter('|')) {
79431055Sminshall 	    ;		/* more names coming */
79531055Sminshall 	} else {
79631055Sminshall 	    lex = Get();
79731055Sminshall 	    UnGet(lex);
79831055Sminshall 	    if (lex.type != LEX_END_OF_FILE) {
79931055Sminshall 		    if (!GetEntry0()) {	/* start of an entry */
80031055Sminshall 			fprintf(stderr,
80131055Sminshall 			    "error was in entry for %s in file %s\n",
80231055Sminshall 			    (oldName)? oldName->array:"(unknown)", filename);
80331055Sminshall 		    Return(0);
80431055Sminshall 		}
80531055Sminshall 	    }
80631055Sminshall 	}
80731055Sminshall 	lex = Get();
80831055Sminshall     }
80931100Sminshall #if !defined(MSDOS)
81031055Sminshall     fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer,
81131055Sminshall 		    filename);
81231100Sminshall #endif	/* !defined(MSDOS) */
81331055Sminshall     Return(0);
81431055Sminshall }
81531055Sminshall 
81631055Sminshall char *
81731055Sminshall strsave(string)
81831055Sminshall char *string;
81931055Sminshall {
82031055Sminshall     char *p;
82131055Sminshall     extern char *malloc();
82231055Sminshall 
82331055Sminshall     p = malloc(strlen(string)+1);
82431055Sminshall     if (p != 0) {
82531055Sminshall 	strcpy(p, string);
82631055Sminshall     }
82731055Sminshall     return(p);
82831055Sminshall }
82931055Sminshall 
83031055Sminshall 
83131055Sminshall /*
83231055Sminshall  * InitControl - our interface to the outside.  What we should
83331055Sminshall  *  do is figure out keyboard (or terminal) type, set up file pointer
83431055Sminshall  *  (or string pointer), etc.
83531055Sminshall  */
83631055Sminshall 
83731055Sminshall state *
83831245Sminshall InitControl(keybdPointer, pickyarg, translator)
83931055Sminshall char	*keybdPointer;
84031055Sminshall int	pickyarg;		/* Should we be picky? */
84131245Sminshall int	(*translator)();	/* Translates ascii string to integer */
84231055Sminshall {
84331055Sminshall     extern char *getenv();
84431055Sminshall     int GotIt;
84531055Sminshall 
84631055Sminshall     picky = pickyarg;
84731245Sminshall     GetTc = translator;
84831055Sminshall 
84931055Sminshall     if (keybdPointer == 0) {
85031055Sminshall         keybdPointer = getenv("KEYBD");
85131055Sminshall     }
85231055Sminshall     if (keybdPointer == 0) {
85331055Sminshall        keybdPointer = getenv("TERM");
85431055Sminshall     }
85531055Sminshall 
85631055Sminshall 		    /*
85731055Sminshall 		     * Some environments have getenv() return
85831055Sminshall 		     * out of a static area.  So, save the keyboard name.
85931055Sminshall 		     */
86031055Sminshall     if (keybdPointer) {
86131055Sminshall         keybdPointer = strsave(keybdPointer);
86231055Sminshall     }
86331055Sminshall     environPointer = getenv("MAP3270");
86431055Sminshall     if (environPointer
86531055Sminshall 	    && (environPointer[0] != '/')
86631100Sminshall #if	defined(MSDOS)
86731055Sminshall 	    && (environPointer[0] != '\\')
86831100Sminshall #endif	/* defined(MSDOS) */
86931055Sminshall 	    && (strncmp(keybdPointer, environPointer,
87031055Sminshall 			strlen(keybdPointer) != 0)
87131055Sminshall 		|| (environPointer[strlen(keybdPointer)] != '{'))) /* } */
87231055Sminshall     {
87331055Sminshall 	environPointer = 0;
87431055Sminshall     }
87531055Sminshall 
87631055Sminshall     if ((!environPointer)
87731100Sminshall #if	defined(MSDOS)
87831055Sminshall 		|| (*environPointer == '\\')
87931100Sminshall #endif	/* defined(MSDOS) */
88031055Sminshall 		|| (*environPointer == '/')) {
88131055Sminshall 	usePointer = 0;
88231055Sminshall 	GotIt = 0;
88331055Sminshall 	if (!keybdPointer) {
88431100Sminshall #if !defined(MSDOS)
88531055Sminshall 	    fprintf(stderr, "%s%s%s%s",
88631055Sminshall 		"Neither the KEYBD environment variable nor the TERM ",
88731055Sminshall 		"environment variable\n(one of which is needed to determine ",
88831055Sminshall 		"the type of keyboard you are using)\n",
88931055Sminshall 		"is set.  To set it, say 'setenv KEYBD <type>'\n");
89031100Sminshall #endif	/* !defined(MSDOS) */
89131055Sminshall 	} else {
89231055Sminshall 	    if (environPointer) {
89331055Sminshall 		GotIt = Position(environPointer, keybdPointer);
89431055Sminshall 	    }
89531055Sminshall 	    if (!GotIt) {
89631055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
89731055Sminshall 	    }
89831055Sminshall 	}
89931055Sminshall 	if (!GotIt) {
90031055Sminshall 	    if (environPointer) {
90131055Sminshall 		GotIt = Position(environPointer, "unknown");
90231055Sminshall 	    }
90331055Sminshall 	    if (!GotIt) {
90431055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
90531055Sminshall 	    }
90631055Sminshall 	}
90731055Sminshall 	if (!GotIt) {
90831100Sminshall #if !defined(MSDOS)
90931055Sminshall 	    fprintf(stderr, "Using default key mappings.\n");
91031100Sminshall #endif	/* !defined(MSDOS) */
91131055Sminshall 	    usePointer = 1;		/* flag use of non-file */
91231135Sminshall 	    whichkey = keysgeneric;
91331135Sminshall 	    environPointer = *whichkey;	/* use default table */
91431055Sminshall 	}
91531055Sminshall     } else {
91631055Sminshall 	usePointer = 1;
91731055Sminshall     }
91831055Sminshall     (void) GetEntry();
91931055Sminshall     return(firstentry.address);
92031055Sminshall }
921