xref: /csrg-svn/usr.bin/tn3270/ascii/map3270.c (revision 48755)
1*48755Sbostic /*-
2*48755Sbostic  * Copyright (c) 1988 The Regents of the University of California.
333817Sbostic  * All rights reserved.
431055Sminshall  *
5*48755Sbostic  * %sccs.include.redist.c%
631055Sminshall  */
731055Sminshall 
833817Sbostic #ifndef lint
9*48755Sbostic static char sccsid[] = "@(#)map3270.c	4.2 (Berkeley) 04/26/91";
1033817Sbostic #endif /* not lint */
1131055Sminshall 
1231055Sminshall /*	This program reads a description file, somewhat like /etc/termcap,
1331055Sminshall     that describes the mapping between the current terminal's keyboard and
1431055Sminshall     a 3270 keyboard.
1531055Sminshall  */
1631055Sminshall #ifdef DOCUMENTATION_ONLY
1731055Sminshall /* here is a sample (very small) entry...
1831055Sminshall 
1931055Sminshall 	# this table is sensitive to position on a line.  In particular,
2031055Sminshall 	# a terminal definition for a terminal is terminated whenever a
2131055Sminshall 	# (non-comment) line beginning in column one is found.
2231055Sminshall 	#
2331055Sminshall 	# this is an entry to map tvi924 to 3270 keys...
2431055Sminshall 	v8|tvi924|924|televideo model 924 {
2531055Sminshall 		pfk1 =	'\E1';
2631055Sminshall 		pfk2 =	'\E2';
2731055Sminshall 		clear = '^z';		# clear the screen
2831055Sminshall 	}
2931055Sminshall  */
3031055Sminshall #endif /* DOCUMENTATION_ONLY */
3131055Sminshall 
3231055Sminshall #include <stdio.h>
3331055Sminshall #include <ctype.h>
3431100Sminshall #if	defined(unix)
3531055Sminshall #include <strings.h>
3631100Sminshall #else	/* defined(unix) */
3731100Sminshall #include <string.h>
3831100Sminshall #endif	/* defined(unix) */
3931055Sminshall 
4031055Sminshall #define	IsPrint(c)	((isprint(c) && !isspace(c)) || ((c) == ' '))
4131055Sminshall 
4231055Sminshall #include "state.h"
4335419Sminshall #include "map3270.h"
4431055Sminshall 
4531176Sminshall #include "../general/globals.h"
4631055Sminshall 
4731055Sminshall /* this is the list of types returned by the lex processor */
4831245Sminshall #define	LEX_CHAR	400			/* plain unadorned character */
4931055Sminshall #define	LEX_ESCAPED	LEX_CHAR+1		/* escaped with \ */
5031055Sminshall #define	LEX_CARETED	LEX_ESCAPED+1		/* escaped with ^ */
5131055Sminshall #define	LEX_END_OF_FILE LEX_CARETED+1		/* end of file encountered */
5231055Sminshall #define	LEX_ILLEGAL	LEX_END_OF_FILE+1	/* trailing escape character */
5331055Sminshall 
5431055Sminshall /* the following is part of our character set dependancy... */
5531055Sminshall #define	ESCAPE		0x1b
5631055Sminshall #define	TAB		0x09
5731055Sminshall #define	NEWLINE 	0x0a
5831055Sminshall #define	CARRIAGE_RETURN 0x0d
5931055Sminshall 
6031055Sminshall typedef struct {
6131055Sminshall     int type;		/* LEX_* - type of character */
6231055Sminshall     int value;		/* character this was */
6331055Sminshall } lexicon;
6431055Sminshall 
6531055Sminshall typedef struct {
6631055Sminshall     int		length;		/* length of character string */
6731055Sminshall     char	array[500];	/* character string */
6831055Sminshall } stringWithLength;
6931055Sminshall 
7031055Sminshall #define	panic(s)	{ fprintf(stderr, s); exit(1); }
7131055Sminshall 
7231245Sminshall static state firstentry = { 0, STATE_NULL, 0, 0 };
7331055Sminshall static state *headOfQueue = &firstentry;
7431055Sminshall 
7531055Sminshall /* the following is a primitive adm3a table, to be used when nothing
7631055Sminshall  * else seems to be avaliable.
7731055Sminshall  */
7831055Sminshall 
7931055Sminshall #ifdef	DEBUG
8031055Sminshall static int debug = 0;		/* debug flag (for debuggin tables) */
8131055Sminshall #endif	/* DEBUG */
8231055Sminshall 
8331245Sminshall static int (*GetTc)();
8431245Sminshall static int doPaste = 1;		/* should we have side effects */
8531245Sminshall static int picky = 0;		/* do we complain of unknown functions? */
8631245Sminshall static char usePointer = 0;	/* use pointer, or file */
8731055Sminshall static FILE *ourFile= 0;
8831245Sminshall static char *environPointer = 0;/* if non-zero, point to input
8931245Sminshall 				 * string in core.
9031245Sminshall 				 */
9131135Sminshall static char **whichkey = 0;
9231135Sminshall static char *keysgeneric[] = {
9331055Sminshall #include "default.map"		/* Define the default default */
9431135Sminshall 
9531135Sminshall 	0,			/* Terminate list of entries */
9631135Sminshall };
9731055Sminshall 			;
9831055Sminshall 
9931055Sminshall static	int	Empty = 1,		/* is the unget lifo empty? */
10031055Sminshall 		Full = 0;		/* is the unget lifo full? */
10131100Sminshall static	lexicon	lifo[200] = { 0 };	/* character stack for parser */
10231055Sminshall static	int	rp = 0,			/* read pointer into lifo */
10331055Sminshall 		wp = 0;			/* write pointer into lifo */
10431055Sminshall 
10531055Sminshall static int
10631055Sminshall GetC()
10731055Sminshall {
10831055Sminshall     int character;
10931055Sminshall 
11031055Sminshall     if (usePointer) {
11131135Sminshall 	if ((*environPointer) == 0) {
11231135Sminshall 	    /*
11331135Sminshall 	     * If we have reached the end of this string, go on to
11431135Sminshall 	     * the next (if there is a next).
11531135Sminshall 	     */
11631135Sminshall 	    if (whichkey == 0) {
11731135Sminshall 		static char suffix = 'A';	/* From environment */
11831135Sminshall 		char envname[9];
11931135Sminshall 		extern char *getenv();
12031055Sminshall 
12131135Sminshall 		(void) sprintf(envname, "MAP3270%c", suffix++);
12231135Sminshall 		environPointer = getenv(envname);
12331055Sminshall 	    } else {
12431135Sminshall 		whichkey++;			/* default map */
12531135Sminshall 		environPointer = *whichkey;
12631055Sminshall 	    }
12731055Sminshall 	}
12831135Sminshall 	if (*environPointer) {
12931135Sminshall 	   character = 0xff&*environPointer++;
13031135Sminshall 	} else {
13131135Sminshall 	   character = EOF;
13231135Sminshall 	}
13331055Sminshall     } else {
13431055Sminshall 	character = getc(ourFile);
13531055Sminshall     }
13631055Sminshall     return(character);
13731055Sminshall }
13831055Sminshall 
13931055Sminshall static lexicon
14031055Sminshall Get()
14131055Sminshall {
14231055Sminshall     lexicon c;
14331055Sminshall     register lexicon *pC = &c;
14431055Sminshall     register int character;
14531055Sminshall 
14631055Sminshall     if (!Empty) {
14731055Sminshall 	*pC = lifo[rp];
14831055Sminshall 	rp++;
14931055Sminshall 	if (rp == sizeof lifo/sizeof (lexicon)) {
15031055Sminshall 	    rp = 0;
15131055Sminshall 	}
15231055Sminshall 	if (rp == wp) {
15331055Sminshall 	    Empty = 1;
15431055Sminshall 	}
15531055Sminshall 	Full = 0;
15631055Sminshall     } else {
15731055Sminshall 	character = GetC();
15831055Sminshall 	switch (character) {
15931055Sminshall 	case EOF:
16031055Sminshall 	    pC->type = LEX_END_OF_FILE;
16131055Sminshall 	    break;
16231055Sminshall 	case '^':
16331055Sminshall 	    character = GetC();
16431055Sminshall 	    if (!IsPrint(character)) {
16531055Sminshall 		pC->type = LEX_ILLEGAL;
16631055Sminshall 	    } else {
16731055Sminshall 		pC->type = LEX_CARETED;
16831055Sminshall 		if (character == '?') {
16931055Sminshall 		    character |= 0x40;	/* rubout */
17031055Sminshall 		} else {
17131055Sminshall 		    character &= 0x1f;
17231055Sminshall 		}
17331055Sminshall 	    }
17431055Sminshall 	    break;
17531055Sminshall 	case '\\':
17631055Sminshall 	    character = GetC();
17731055Sminshall 	    if (!IsPrint(character)) {
17831055Sminshall 		pC->type = LEX_ILLEGAL;
17931055Sminshall 	    } else {
18031055Sminshall 		pC->type = LEX_ESCAPED;
18131055Sminshall 		switch (character) {
18231055Sminshall 		case 'E': case 'e':
18331055Sminshall 		    character = ESCAPE;
18431055Sminshall 		    break;
18531055Sminshall 		case 't':
18631055Sminshall 		    character = TAB;
18731055Sminshall 		    break;
18831055Sminshall 		case 'n':
18931055Sminshall 		    character = NEWLINE;
19031055Sminshall 		    break;
19131055Sminshall 		case 'r':
19231055Sminshall 		    character = CARRIAGE_RETURN;
19331055Sminshall 		    break;
19431055Sminshall 		default:
19531055Sminshall 		    pC->type = LEX_ILLEGAL;
19631055Sminshall 		    break;
19731055Sminshall 		}
19831055Sminshall 	    }
19931055Sminshall 	    break;
20031055Sminshall 	default:
20131055Sminshall 	    if ((IsPrint(character)) || isspace(character)) {
20231055Sminshall 		pC->type = LEX_CHAR;
20331055Sminshall 	    } else {
20431055Sminshall 		pC->type = LEX_ILLEGAL;
20531055Sminshall 	    }
20631055Sminshall 	    break;
20731055Sminshall 	}
20831055Sminshall 	pC->value = character;
20931055Sminshall     }
21031055Sminshall     return(*pC);
21131055Sminshall }
21231055Sminshall 
21331055Sminshall static void
21431055Sminshall UnGet(c)
21531055Sminshall lexicon c;			/* character to unget */
21631055Sminshall {
21731055Sminshall     if (Full) {
21831055Sminshall 	fprintf(stderr, "attempt to put too many characters in lifo\n");
21931055Sminshall 	panic("map3270");
22031055Sminshall 	/* NOTREACHED */
22131055Sminshall     } else {
22231055Sminshall 	lifo[wp] = c;
22331055Sminshall 	wp++;
22431055Sminshall 	if (wp == sizeof lifo/sizeof (lexicon)) {
22531055Sminshall 	    wp = 0;
22631055Sminshall 	}
22731055Sminshall 	if (wp == rp) {
22831055Sminshall 	    Full = 1;
22931055Sminshall 	}
23031055Sminshall 	Empty = 0;
23131055Sminshall     }
23231055Sminshall }
23331055Sminshall 
23431100Sminshall /*
23531100Sminshall  * Construct a control character sequence
23631100Sminshall  * for a special character.
23731100Sminshall  */
23831100Sminshall char *
23931100Sminshall uncontrol(c)
24031100Sminshall 	register int c;
24131100Sminshall {
24231100Sminshall 	static char buf[3];
24331100Sminshall 
24431100Sminshall 	if (c == 0x7f)
24531100Sminshall 		return ("^?");
24631100Sminshall 	if (c == '\377') {
24731100Sminshall 		return "-1";
24831100Sminshall 	}
24931100Sminshall 	if (c >= 0x20) {
25031100Sminshall 		buf[0] = c;
25131100Sminshall 		buf[1] = 0;
25231100Sminshall 	} else {
25331100Sminshall 		buf[0] = '^';
25431100Sminshall 		buf[1] = '@'+c;
25531100Sminshall 		buf[2] = 0;
25631100Sminshall 	}
25731100Sminshall 	return (buf);
25831100Sminshall }
25931100Sminshall 
26031055Sminshall /* compare two strings, ignoring case */
26131055Sminshall 
26231055Sminshall ustrcmp(string1, string2)
26331055Sminshall register char *string1;
26431055Sminshall register char *string2;
26531055Sminshall {
26631055Sminshall     register int c1, c2;
26731055Sminshall 
26831055Sminshall     while ((c1 = (unsigned char) *string1++) != 0) {
26931055Sminshall 	if (isupper(c1)) {
27031055Sminshall 	    c1 = tolower(c1);
27131055Sminshall 	}
27231055Sminshall 	if (isupper(c2 = (unsigned char) *string2++)) {
27331055Sminshall 	    c2 = tolower(c2);
27431055Sminshall 	}
27531055Sminshall 	if (c1 < c2) {
27631055Sminshall 	    return(-1);
27731055Sminshall 	} else if (c1 > c2) {
27831055Sminshall 	    return(1);
27931055Sminshall 	}
28031055Sminshall     }
28131055Sminshall     if (*string2) {
28231055Sminshall 	return(-1);
28331055Sminshall     } else {
28431055Sminshall 	return(0);
28531055Sminshall     }
28631055Sminshall }
28731055Sminshall 
28831055Sminshall 
28931055Sminshall static stringWithLength *
29031055Sminshall GetQuotedString()
29131055Sminshall {
29231055Sminshall     lexicon lex;
29331055Sminshall     static stringWithLength output = { 0 };	/* where return value is held */
29431055Sminshall     char *pointer = output.array;
29531055Sminshall 
29631055Sminshall     lex = Get();
29731055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != '\'')) {
29831055Sminshall 	UnGet(lex);
29931055Sminshall 	return(0);
30031055Sminshall     }
30131055Sminshall     while (1) {
30231055Sminshall 	lex = Get();
30331055Sminshall 	if ((lex.type == LEX_CHAR) && (lex.value == '\'')) {
30431055Sminshall 	    break;
30531055Sminshall 	}
30631055Sminshall 	if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) {
30731055Sminshall 	    UnGet(lex);
30831055Sminshall 	    return(0);		/* illegal character in quoted string */
30931055Sminshall 	}
31031055Sminshall 	if (pointer >= output.array+sizeof output.array) {
31131055Sminshall 	    return(0);		/* too long */
31231055Sminshall 	}
31331055Sminshall 	*pointer++ = lex.value;
31431055Sminshall     }
31531055Sminshall     output.length = pointer-output.array;
31631055Sminshall     return(&output);
31731055Sminshall }
31831055Sminshall 
31931055Sminshall #ifdef	NOTUSED
32031055Sminshall static stringWithLength *
32131055Sminshall GetCharString()
32231055Sminshall {
32331055Sminshall     lexicon lex;
32431055Sminshall     static stringWithLength output;
32531055Sminshall     char *pointer = output.array;
32631055Sminshall 
32731055Sminshall     lex = Get();
32831055Sminshall 
32931055Sminshall     while ((lex.type == LEX_CHAR) &&
33031055Sminshall 			!isspace(lex.value) && (lex.value != '=')) {
33131055Sminshall 	*pointer++ = lex.value;
33231055Sminshall 	lex = Get();
33331055Sminshall 	if (pointer >= output.array + sizeof output.array) {
33431055Sminshall 	    return(0);		/* too long */
33531055Sminshall 	}
33631055Sminshall     }
33731055Sminshall     UnGet(lex);
33831055Sminshall     output.length = pointer-output.array;
33931055Sminshall     return(&output);
34031055Sminshall }
34131055Sminshall #endif	/* NOTUSED */
34231055Sminshall 
34331055Sminshall static
34431055Sminshall GetCharacter(character)
34531055Sminshall int	character;		/* desired character */
34631055Sminshall {
34731055Sminshall     lexicon lex;
34831055Sminshall 
34931055Sminshall     lex = Get();
35031055Sminshall 
35131055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != character)) {
35231055Sminshall 	UnGet(lex);
35331055Sminshall 	return(0);
35431055Sminshall     }
35531055Sminshall     return(1);
35631055Sminshall }
35731055Sminshall 
35831055Sminshall #ifdef	NOTUSED
35931055Sminshall static
36031055Sminshall GetString(string)
36131055Sminshall char	*string;		/* string to get */
36231055Sminshall {
36331055Sminshall     lexicon lex;
36431055Sminshall 
36531055Sminshall     while (*string) {
36631055Sminshall 	lex = Get();
36731055Sminshall 	if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) {
36831055Sminshall 	    UnGet(lex);
36931055Sminshall 	    return(0);		/* XXX restore to state on entry */
37031055Sminshall 	}
37131055Sminshall 	string++;
37231055Sminshall     }
37331055Sminshall     return(1);
37431055Sminshall }
37531055Sminshall #endif	/* NOTUSED */
37631055Sminshall 
37731055Sminshall 
37831055Sminshall static stringWithLength *
37931055Sminshall GetAlphaMericString()
38031055Sminshall {
38131055Sminshall     lexicon lex;
38231055Sminshall     static stringWithLength output = { 0 };
38331055Sminshall     char *pointer = output.array;
38431055Sminshall #   define	IsAlnum(c)	(isalnum(c) || (c == '_') \
38531055Sminshall 					|| (c == '-') || (c == '.'))
38631055Sminshall 
38731055Sminshall     lex = Get();
38831055Sminshall 
38931055Sminshall     if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) {
39031055Sminshall 	UnGet(lex);
39131055Sminshall 	return(0);
39231055Sminshall     }
39331055Sminshall 
39431055Sminshall     while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) {
39531055Sminshall 	*pointer++ = lex.value;
39631055Sminshall 	lex = Get();
39731055Sminshall     }
39831055Sminshall     UnGet(lex);
39931055Sminshall     *pointer = 0;
40031055Sminshall     output.length = pointer-output.array;
40131055Sminshall     return(&output);
40231055Sminshall }
40331055Sminshall 
40431055Sminshall 
40531055Sminshall /* eat up characters until a new line, or end of file.  returns terminating
40631055Sminshall 	character.
40731055Sminshall  */
40831055Sminshall 
40931055Sminshall static lexicon
41031055Sminshall EatToNL()
41131055Sminshall {
41231055Sminshall     lexicon lex;
41331055Sminshall 
41431055Sminshall     lex = Get();
41531055Sminshall 
41631055Sminshall     while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) &&
41731055Sminshall 		(lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) {
41831055Sminshall 	lex = Get();
41931055Sminshall     }
42031055Sminshall     if (lex.type != LEX_END_OF_FILE) {
42131055Sminshall 	return(Get());
42231055Sminshall     } else {
42331055Sminshall 	return(lex);
42431055Sminshall     }
42531055Sminshall }
42631055Sminshall 
42731055Sminshall 
42831055Sminshall static void
42931055Sminshall GetWS()
43031055Sminshall {
43131055Sminshall     lexicon lex;
43231055Sminshall 
43331055Sminshall     lex = Get();
43431055Sminshall 
43531055Sminshall     while ((lex.type == LEX_CHAR) &&
43631055Sminshall 			(isspace(lex.value) || (lex.value == '#'))) {
43731055Sminshall 	if (lex.value == '#') {
43831055Sminshall 	    lex = EatToNL();
43931055Sminshall 	} else {
44031055Sminshall 	    lex = Get();
44131055Sminshall 	}
44231055Sminshall     }
44331055Sminshall     UnGet(lex);
44431055Sminshall }
44531055Sminshall 
44631055Sminshall static void
44731055Sminshall FreeState(pState)
44831055Sminshall state *pState;
44931055Sminshall {
45035419Sminshall     extern int free();
45131055Sminshall 
45231055Sminshall     free((char *)pState);
45331055Sminshall }
45431055Sminshall 
45531055Sminshall 
45631055Sminshall static state *
45731055Sminshall GetState()
45831055Sminshall {
45931055Sminshall     state *pState;
46031055Sminshall     extern char *malloc();
46131055Sminshall 
46231055Sminshall     pState = (state *) malloc(sizeof (state));
46331055Sminshall 
46431245Sminshall     pState->result = STATE_NULL;
46531055Sminshall     pState->next = 0;
46631055Sminshall 
46731055Sminshall     return(pState);
46831055Sminshall }
46931055Sminshall 
47031055Sminshall 
47131055Sminshall static state *
47231055Sminshall FindMatchAtThisLevel(pState, character)
47331055Sminshall state	*pState;
47431055Sminshall int	character;
47531055Sminshall {
47631055Sminshall     while (pState) {
47731055Sminshall 	if (pState->match == character) {
47831055Sminshall 	    return(pState);
47931055Sminshall 	}
48031055Sminshall 	pState = pState->next;
48131055Sminshall     }
48231055Sminshall     return(0);
48331055Sminshall }
48431055Sminshall 
48531055Sminshall 
48631055Sminshall static state *
48731055Sminshall PasteEntry(head, string, count, identifier)
48831055Sminshall state			*head;		/* points to who should point here... */
48931055Sminshall char			*string;	/* which characters to paste */
49031055Sminshall int			count;		/* number of character to do */
49131055Sminshall char			*identifier;	/* for error messages */
49231055Sminshall {
49331055Sminshall     state *pState, *other;
49431055Sminshall 
49531055Sminshall     if (!doPaste) {		/* flag to not have any side effects */
49631055Sminshall 	return((state *)1);
49731055Sminshall     }
49831055Sminshall     if (!count) {
49931055Sminshall 	return(head);	/* return pointer to the parent */
50031055Sminshall     }
50131245Sminshall     if ((head->result != STATE_NULL) && (head->result != STATE_GOTO)) {
50231055Sminshall 	/* this means that a previously defined sequence is an initial
50331055Sminshall 	 * part of this one.
50431055Sminshall 	 */
50531055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
50631055Sminshall 		identifier);
50731055Sminshall 	return(0);
50831055Sminshall     }
50931055Sminshall #   ifdef	DEBUG
51031055Sminshall 	if (debug) {
51131100Sminshall 	    fprintf(stderr, "%s", uncontrol(*string));
51231055Sminshall 	}
51331055Sminshall #   endif	/* DEBUG */
51431055Sminshall     pState = GetState();
51531055Sminshall     pState->match = *string;
51631245Sminshall     if (head->result == STATE_NULL) {
51731245Sminshall 	head->result = STATE_GOTO;
51831055Sminshall 	head->address = pState;
51931055Sminshall 	other = pState;
52031055Sminshall     } else {		/* search for same character */
52131055Sminshall 	if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) {
52231055Sminshall 	    FreeState(pState);
52331055Sminshall 	} else {
52431055Sminshall 	    pState->next = head->address;
52531055Sminshall 	    head->address = pState;
52631055Sminshall 	    other = pState;
52731055Sminshall 	}
52831055Sminshall     }
52931055Sminshall     return(PasteEntry(other, string+1, count-1, identifier));
53031055Sminshall }
53131055Sminshall 
53231055Sminshall static
53331055Sminshall GetInput(tc, identifier)
53431055Sminshall int tc;
53531055Sminshall char *identifier;		/* entry being parsed (for error messages) */
53631055Sminshall {
53731055Sminshall     stringWithLength *outputString;
53831055Sminshall     state *head;
53931055Sminshall     state fakeQueue;
54031055Sminshall 
54131055Sminshall     if (doPaste) {
54231055Sminshall 	head = headOfQueue;	/* always points to level above this one */
54331055Sminshall     } else {
54431055Sminshall 	head = &fakeQueue;	/* don't have any side effects... */
54531055Sminshall     }
54631055Sminshall 
54731055Sminshall     if ((outputString = GetQuotedString()) == 0) {
54831055Sminshall 	return(0);
54931055Sminshall     } else if (IsPrint(outputString->array[0])) {
55031055Sminshall 	fprintf(stderr,
55131055Sminshall 	 "first character of sequence for %s is not a control type character\n",
55231055Sminshall 		identifier);
55331055Sminshall 	return(0);
55431055Sminshall     } else {
55531055Sminshall 	if ((head = PasteEntry(head, outputString->array,
55631055Sminshall 				outputString->length, identifier)) == 0) {
55731055Sminshall 	    return(0);
55831055Sminshall 	}
55931055Sminshall 	GetWS();
56031055Sminshall 	while ((outputString = GetQuotedString()) != 0) {
56131055Sminshall 	    if ((head = PasteEntry(head, outputString->array,
56231055Sminshall 				outputString->length, identifier)) == 0) {
56331055Sminshall 		return(0);
56431055Sminshall 	    }
56531055Sminshall 	    GetWS();
56631055Sminshall 	}
56731055Sminshall     }
56831055Sminshall     if (!doPaste) {
56931055Sminshall 	return(1);
57031055Sminshall     }
57131245Sminshall     if ((head->result != STATE_NULL) && (head->result != tc)) {
57231055Sminshall 	/* this means that this sequence is an initial part
57331055Sminshall 	 * of a previously defined one.
57431055Sminshall 	 */
57531055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
57631055Sminshall 		identifier);
57731055Sminshall 	return(0);
57831055Sminshall     } else {
57931055Sminshall 	head->result = tc;
58031055Sminshall 	return(1);		/* done */
58131055Sminshall     }
58231055Sminshall }
58331055Sminshall 
58431055Sminshall static
58531055Sminshall GetDefinition()
58631055Sminshall {
58731055Sminshall     stringWithLength *string;
58831055Sminshall     int Tc;
58931055Sminshall 
59031055Sminshall     GetWS();
59131055Sminshall     if ((string = GetAlphaMericString()) == 0) {
59231055Sminshall 	return(0);
59331055Sminshall     }
59431055Sminshall     string->array[string->length] = 0;
59531055Sminshall     if (doPaste) {
59631609Sminshall 	if ((Tc = (*GetTc)(string->array)) == -1) {
59731055Sminshall 	    if (picky) {
59831055Sminshall 		fprintf(stderr, "%s: unknown 3270 key identifier\n",
59931055Sminshall 							string->array);
60031055Sminshall 	    }
60131245Sminshall 	    Tc = STATE_NULL;
60231055Sminshall 	}
60331055Sminshall     } else {
60431245Sminshall 	Tc = STATE_NULL;		/* XXX ? */
60531055Sminshall     }
60631055Sminshall     GetWS();
60731055Sminshall     if (!GetCharacter('=')) {
60831055Sminshall 	fprintf(stderr,
60931055Sminshall 		"Required equal sign after 3270 key identifier %s missing\n",
61031055Sminshall 			string->array);
61131055Sminshall 	return(0);
61231055Sminshall     }
61331055Sminshall     GetWS();
61431055Sminshall     if (!GetInput(Tc, string->array)) {
61531055Sminshall 	fprintf(stderr, "Missing definition part for 3270 key %s\n",
61631055Sminshall 				string->array);
61731055Sminshall 	return(0);
61831055Sminshall     } else {
61931055Sminshall 	GetWS();
62031055Sminshall 	while (GetCharacter('|')) {
62131055Sminshall #	    ifdef	DEBUG
62231055Sminshall 		if (debug) {
62331055Sminshall 		    fprintf(stderr, " or ");
62431055Sminshall 		}
62531055Sminshall #	    endif	/* DEBUG */
62631055Sminshall 	    GetWS();
62731055Sminshall 	    if (!GetInput(Tc, string->array)) {
62831055Sminshall 		fprintf(stderr, "Missing definition part for 3270 key %s\n",
62931055Sminshall 					string->array);
63031055Sminshall 		return(0);
63131055Sminshall 	    }
63231055Sminshall 	    GetWS();
63331055Sminshall 	}
63431055Sminshall     }
63531055Sminshall     GetWS();
63631055Sminshall     if (!GetCharacter(';')) {
63731055Sminshall 	fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array);
63831055Sminshall 	return(0);
63931055Sminshall     }
64031055Sminshall #   ifdef	DEBUG
64131055Sminshall 	if (debug) {
64231055Sminshall 	    fprintf(stderr, ";\n");
64331055Sminshall 	}
64431055Sminshall #   endif	/* DEBUG */
64531055Sminshall     return(1);
64631055Sminshall }
64731055Sminshall 
64831055Sminshall 
64931055Sminshall static
65031055Sminshall GetDefinitions()
65131055Sminshall {
65231055Sminshall     if (!GetDefinition()) {
65331055Sminshall 	return(0);
65431055Sminshall     } else {
65531055Sminshall 	while (GetDefinition()) {
65631055Sminshall 	    ;
65731055Sminshall 	}
65831055Sminshall     }
65931055Sminshall     return(1);
66031055Sminshall }
66131055Sminshall 
66231055Sminshall static
66331055Sminshall GetBegin()
66431055Sminshall {
66531055Sminshall     GetWS();
66631055Sminshall     if (!GetCharacter('{')) {
66731055Sminshall 	return(0);
66831055Sminshall     }
66931055Sminshall     return(1);
67031055Sminshall }
67131055Sminshall 
67231055Sminshall static
67331055Sminshall GetEnd()
67431055Sminshall {
67531055Sminshall     GetWS();
67631055Sminshall     if (!GetCharacter('}')) {
67731055Sminshall 	return(0);
67831055Sminshall     }
67931055Sminshall     return(1);
68031055Sminshall }
68131055Sminshall 
68231055Sminshall static
68331055Sminshall GetName()
68431055Sminshall {
68531055Sminshall     if (!GetAlphaMericString()) {
68631055Sminshall 	return(0);
68731055Sminshall     }
68831055Sminshall     GetWS();
68931055Sminshall     while (GetAlphaMericString()) {
69031055Sminshall 	GetWS();
69131055Sminshall     }
69231055Sminshall     return(1);
69331055Sminshall }
69431055Sminshall 
69531055Sminshall static
69631055Sminshall GetNames()
69731055Sminshall {
69831055Sminshall     GetWS();
69931055Sminshall     if (!GetName()) {
70031055Sminshall 	return(0);
70131055Sminshall     } else {
70231055Sminshall 	GetWS();
70331055Sminshall 	while (GetCharacter('|')) {
70431055Sminshall 	    GetWS();
70531055Sminshall 	    if (!GetName()) {
70631055Sminshall 		return(0);
70731055Sminshall 	    }
70831055Sminshall 	}
70931055Sminshall     }
71031055Sminshall     return(1);
71131055Sminshall }
71231055Sminshall 
71331055Sminshall static
71431055Sminshall GetEntry0()
71531055Sminshall {
71631055Sminshall     if (!GetBegin()) {
71731055Sminshall 	fprintf(stderr, "no '{'\n");
71831055Sminshall 	return(0);
71931055Sminshall     } else if (!GetDefinitions()) {
72031055Sminshall 	fprintf(stderr, "unable to parse the definitions\n");
72131055Sminshall 	return(0);
72231055Sminshall     } else if (!GetEnd()) {
72331055Sminshall 	fprintf(stderr, "No '}' or scanning stopped early due to error.\n");
72431055Sminshall 	return(0);
72531055Sminshall     } else {
72631055Sminshall 	/* done */
72731055Sminshall 	return(1);
72831055Sminshall     }
72931055Sminshall }
73031055Sminshall 
73131055Sminshall 
73231055Sminshall static
73331055Sminshall GetEntry()
73431055Sminshall {
73531055Sminshall     if (!GetNames()) {
73631055Sminshall 	fprintf(stderr, "Invalid name field in entry.\n");
73731055Sminshall 	return(0);
73831055Sminshall     } else {
73931055Sminshall 	return(GetEntry0());
74031055Sminshall     }
74131055Sminshall }
74231055Sminshall 
74331055Sminshall /* position ourselves within a given filename to the entry for the current
74431055Sminshall  *	KEYBD (or TERM) variable
74531055Sminshall  */
74631055Sminshall 
74731055Sminshall Position(filename, keybdPointer)
74831055Sminshall char *filename;
74931055Sminshall char *keybdPointer;
75031055Sminshall {
75131055Sminshall     lexicon lex;
75231055Sminshall     stringWithLength *name = 0;
75331055Sminshall     stringWithLength *oldName;
75431055Sminshall #   define	Return(x) {doPaste = 1; return(x);}
75531055Sminshall 
75631055Sminshall     doPaste = 0;
75731055Sminshall 
75831055Sminshall     if ((ourFile = fopen(filename, "r")) == NULL) {
75931100Sminshall #   if !defined(MSDOS)
76031055Sminshall 	fprintf(stderr, "Unable to open file %s\n", filename);
76131100Sminshall #   endif /* !defined(MSDOS) */
76231055Sminshall 	Return(0);
76331055Sminshall     }
76431055Sminshall     lex = Get();
76531055Sminshall     while (lex.type != LEX_END_OF_FILE) {
76631055Sminshall 	UnGet(lex);
76731055Sminshall 	/* now, find an entry that is our type. */
76831055Sminshall 	GetWS();
76931055Sminshall 	oldName = name;
77031055Sminshall 	if ((name = GetAlphaMericString()) != 0) {
77131055Sminshall 	    if (!ustrcmp(name->array, keybdPointer)) {
77231055Sminshall 		/* need to make sure there is a name here... */
77331055Sminshall 		lex.type = LEX_CHAR;
77431055Sminshall 		lex.value = 'a';
77531055Sminshall 		UnGet(lex);
77631055Sminshall 		Return(1);
77731055Sminshall 	    }
77831055Sminshall 	} else if (GetCharacter('|')) {
77931055Sminshall 	    ;		/* more names coming */
78031055Sminshall 	} else {
78131055Sminshall 	    lex = Get();
78231055Sminshall 	    UnGet(lex);
78331055Sminshall 	    if (lex.type != LEX_END_OF_FILE) {
78431055Sminshall 		    if (!GetEntry0()) {	/* start of an entry */
78531055Sminshall 			fprintf(stderr,
78631055Sminshall 			    "error was in entry for %s in file %s\n",
78731055Sminshall 			    (oldName)? oldName->array:"(unknown)", filename);
78831055Sminshall 		    Return(0);
78931055Sminshall 		}
79031055Sminshall 	    }
79131055Sminshall 	}
79231055Sminshall 	lex = Get();
79331055Sminshall     }
79431100Sminshall #if !defined(MSDOS)
79531055Sminshall     fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer,
79631055Sminshall 		    filename);
79731100Sminshall #endif	/* !defined(MSDOS) */
79831055Sminshall     Return(0);
79931055Sminshall }
80031055Sminshall 
80131055Sminshall char *
80231055Sminshall strsave(string)
80331055Sminshall char *string;
80431055Sminshall {
80531055Sminshall     char *p;
80631055Sminshall     extern char *malloc();
80731055Sminshall 
80835419Sminshall     p = malloc((unsigned int)strlen(string)+1);
80931055Sminshall     if (p != 0) {
81031055Sminshall 	strcpy(p, string);
81131055Sminshall     }
81231055Sminshall     return(p);
81331055Sminshall }
81431055Sminshall 
81531055Sminshall 
81631055Sminshall /*
81731055Sminshall  * InitControl - our interface to the outside.  What we should
81831055Sminshall  *  do is figure out keyboard (or terminal) type, set up file pointer
81931055Sminshall  *  (or string pointer), etc.
82031055Sminshall  */
82131055Sminshall 
82231055Sminshall state *
82331245Sminshall InitControl(keybdPointer, pickyarg, translator)
82431055Sminshall char	*keybdPointer;
82531055Sminshall int	pickyarg;		/* Should we be picky? */
82631245Sminshall int	(*translator)();	/* Translates ascii string to integer */
82731055Sminshall {
82831055Sminshall     extern char *getenv();
82931055Sminshall     int GotIt;
83031055Sminshall 
83131055Sminshall     picky = pickyarg;
83231245Sminshall     GetTc = translator;
83331055Sminshall 
83431055Sminshall     if (keybdPointer == 0) {
83531055Sminshall         keybdPointer = getenv("KEYBD");
83631055Sminshall     }
83731055Sminshall     if (keybdPointer == 0) {
83831055Sminshall        keybdPointer = getenv("TERM");
83931055Sminshall     }
84031055Sminshall 
84131055Sminshall 		    /*
84231055Sminshall 		     * Some environments have getenv() return
84331055Sminshall 		     * out of a static area.  So, save the keyboard name.
84431055Sminshall 		     */
84531055Sminshall     if (keybdPointer) {
84631055Sminshall         keybdPointer = strsave(keybdPointer);
84731055Sminshall     }
84831055Sminshall     environPointer = getenv("MAP3270");
84931055Sminshall     if (environPointer
85031055Sminshall 	    && (environPointer[0] != '/')
85131100Sminshall #if	defined(MSDOS)
85231055Sminshall 	    && (environPointer[0] != '\\')
85331100Sminshall #endif	/* defined(MSDOS) */
85431055Sminshall 	    && (strncmp(keybdPointer, environPointer,
85531055Sminshall 			strlen(keybdPointer) != 0)
85631055Sminshall 		|| (environPointer[strlen(keybdPointer)] != '{'))) /* } */
85731055Sminshall     {
85831055Sminshall 	environPointer = 0;
85931055Sminshall     }
86031055Sminshall 
86131055Sminshall     if ((!environPointer)
86231100Sminshall #if	defined(MSDOS)
86331055Sminshall 		|| (*environPointer == '\\')
86431100Sminshall #endif	/* defined(MSDOS) */
86531055Sminshall 		|| (*environPointer == '/')) {
86631055Sminshall 	usePointer = 0;
86731055Sminshall 	GotIt = 0;
86831055Sminshall 	if (!keybdPointer) {
86931100Sminshall #if !defined(MSDOS)
87031055Sminshall 	    fprintf(stderr, "%s%s%s%s",
87131055Sminshall 		"Neither the KEYBD environment variable nor the TERM ",
87231055Sminshall 		"environment variable\n(one of which is needed to determine ",
87331055Sminshall 		"the type of keyboard you are using)\n",
87431055Sminshall 		"is set.  To set it, say 'setenv KEYBD <type>'\n");
87531100Sminshall #endif	/* !defined(MSDOS) */
87631055Sminshall 	} else {
87731055Sminshall 	    if (environPointer) {
87831055Sminshall 		GotIt = Position(environPointer, keybdPointer);
87931055Sminshall 	    }
88031055Sminshall 	    if (!GotIt) {
88131055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
88231055Sminshall 	    }
88331055Sminshall 	}
88431055Sminshall 	if (!GotIt) {
88531055Sminshall 	    if (environPointer) {
88631055Sminshall 		GotIt = Position(environPointer, "unknown");
88731055Sminshall 	    }
88831055Sminshall 	    if (!GotIt) {
88931055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
89031055Sminshall 	    }
89131055Sminshall 	}
89231055Sminshall 	if (!GotIt) {
89331100Sminshall #if !defined(MSDOS)
89431055Sminshall 	    fprintf(stderr, "Using default key mappings.\n");
89531100Sminshall #endif	/* !defined(MSDOS) */
89631055Sminshall 	    usePointer = 1;		/* flag use of non-file */
89731135Sminshall 	    whichkey = keysgeneric;
89831135Sminshall 	    environPointer = *whichkey;	/* use default table */
89931055Sminshall 	}
90031055Sminshall     } else {
90131055Sminshall 	usePointer = 1;
90231055Sminshall     }
90331055Sminshall     (void) GetEntry();
90431055Sminshall     return(firstentry.address);
90531055Sminshall }
906