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