xref: /csrg-svn/usr.bin/tn3270/ascii/map3270.c (revision 31135)
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 #define	LETS_SEE_ASCII
5831055Sminshall #include "m4.out"
5931055Sminshall 
6031055Sminshall #include "state.h"
6131055Sminshall 
6231055Sminshall #include "../system/globals.h"
6331055Sminshall #include "map3270.ext"
6431055Sminshall 
6531055Sminshall /* this is the list of types returned by the lex processor */
6631055Sminshall #define	LEX_CHAR	TC_HIGHEST		/* plain unadorned character */
6731055Sminshall #define	LEX_ESCAPED	LEX_CHAR+1		/* escaped with \ */
6831055Sminshall #define	LEX_CARETED	LEX_ESCAPED+1		/* escaped with ^ */
6931055Sminshall #define	LEX_END_OF_FILE LEX_CARETED+1		/* end of file encountered */
7031055Sminshall #define	LEX_ILLEGAL	LEX_END_OF_FILE+1	/* trailing escape character */
7131055Sminshall 
7231055Sminshall /* the following is part of our character set dependancy... */
7331055Sminshall #define	ESCAPE		0x1b
7431055Sminshall #define	TAB		0x09
7531055Sminshall #define	NEWLINE 	0x0a
7631055Sminshall #define	CARRIAGE_RETURN 0x0d
7731055Sminshall 
7831055Sminshall typedef struct {
7931055Sminshall     int type;		/* LEX_* - type of character */
8031055Sminshall     int value;		/* character this was */
8131055Sminshall } lexicon;
8231055Sminshall 
8331055Sminshall typedef struct {
8431055Sminshall     int		length;		/* length of character string */
8531055Sminshall     char	array[500];	/* character string */
8631055Sminshall } stringWithLength;
8731055Sminshall 
8831055Sminshall #define	panic(s)	{ fprintf(stderr, s); exit(1); }
8931055Sminshall 
9031055Sminshall static state firstentry = { 0, TC_NULL, 0, 0 };
9131055Sminshall static state *headOfQueue = &firstentry;
9231055Sminshall 
9331055Sminshall /* the following is a primitive adm3a table, to be used when nothing
9431055Sminshall  * else seems to be avaliable.
9531055Sminshall  */
9631055Sminshall 
9731055Sminshall #ifdef	DEBUG
9831055Sminshall static int debug = 0;		/* debug flag (for debuggin tables) */
9931055Sminshall #endif	/* DEBUG */
10031055Sminshall 
10131055Sminshall static int doPaste = 1;			/* should we have side effects */
10231055Sminshall static int picky = 0;			/* do we complain of unknown TC's? */
10331055Sminshall static char usePointer = 0;		/* use pointer, or file */
10431055Sminshall static FILE *ourFile= 0;
10531055Sminshall static char *environPointer = 0;	/* if non-zero, point to input
10631055Sminshall 					 * string in core.
10731055Sminshall 					 */
108*31135Sminshall static char **whichkey = 0;
109*31135Sminshall static char *keysgeneric[] = {
11031055Sminshall #include "default.map"		/* Define the default default */
111*31135Sminshall 
112*31135Sminshall 	0,			/* Terminate list of entries */
113*31135Sminshall };
11431055Sminshall 			;
11531055Sminshall 
11631055Sminshall static	int	Empty = 1,		/* is the unget lifo empty? */
11731055Sminshall 		Full = 0;		/* is the unget lifo full? */
11831100Sminshall static	lexicon	lifo[200] = { 0 };	/* character stack for parser */
11931055Sminshall static	int	rp = 0,			/* read pointer into lifo */
12031055Sminshall 		wp = 0;			/* write pointer into lifo */
12131055Sminshall 
12231055Sminshall static int
12331055Sminshall GetC()
12431055Sminshall {
12531055Sminshall     int character;
12631055Sminshall 
12731055Sminshall     if (usePointer) {
128*31135Sminshall 	if ((*environPointer) == 0) {
129*31135Sminshall 	    /*
130*31135Sminshall 	     * If we have reached the end of this string, go on to
131*31135Sminshall 	     * the next (if there is a next).
132*31135Sminshall 	     */
133*31135Sminshall 	    if (whichkey == 0) {
134*31135Sminshall 		static char suffix = 'A';	/* From environment */
135*31135Sminshall 		char envname[9];
136*31135Sminshall 		extern char *getenv();
13731055Sminshall 
138*31135Sminshall 		(void) sprintf(envname, "MAP3270%c", suffix++);
139*31135Sminshall 		environPointer = getenv(envname);
14031055Sminshall 	    } else {
141*31135Sminshall 		whichkey++;			/* default map */
142*31135Sminshall 		environPointer = *whichkey;
14331055Sminshall 	    }
14431055Sminshall 	}
145*31135Sminshall 	if (*environPointer) {
146*31135Sminshall 	   character = 0xff&*environPointer++;
147*31135Sminshall 	} else {
148*31135Sminshall 	   character = EOF;
149*31135Sminshall 	}
15031055Sminshall     } else {
15131055Sminshall 	character = getc(ourFile);
15231055Sminshall     }
15331055Sminshall     return(character);
15431055Sminshall }
15531055Sminshall 
15631055Sminshall static lexicon
15731055Sminshall Get()
15831055Sminshall {
15931055Sminshall     lexicon c;
16031055Sminshall     register lexicon *pC = &c;
16131055Sminshall     register int character;
16231055Sminshall 
16331055Sminshall     if (!Empty) {
16431055Sminshall 	*pC = lifo[rp];
16531055Sminshall 	rp++;
16631055Sminshall 	if (rp == sizeof lifo/sizeof (lexicon)) {
16731055Sminshall 	    rp = 0;
16831055Sminshall 	}
16931055Sminshall 	if (rp == wp) {
17031055Sminshall 	    Empty = 1;
17131055Sminshall 	}
17231055Sminshall 	Full = 0;
17331055Sminshall     } else {
17431055Sminshall 	character = GetC();
17531055Sminshall 	switch (character) {
17631055Sminshall 	case EOF:
17731055Sminshall 	    pC->type = LEX_END_OF_FILE;
17831055Sminshall 	    break;
17931055Sminshall 	case '^':
18031055Sminshall 	    character = GetC();
18131055Sminshall 	    if (!IsPrint(character)) {
18231055Sminshall 		pC->type = LEX_ILLEGAL;
18331055Sminshall 	    } else {
18431055Sminshall 		pC->type = LEX_CARETED;
18531055Sminshall 		if (character == '?') {
18631055Sminshall 		    character |= 0x40;	/* rubout */
18731055Sminshall 		} else {
18831055Sminshall 		    character &= 0x1f;
18931055Sminshall 		}
19031055Sminshall 	    }
19131055Sminshall 	    break;
19231055Sminshall 	case '\\':
19331055Sminshall 	    character = GetC();
19431055Sminshall 	    if (!IsPrint(character)) {
19531055Sminshall 		pC->type = LEX_ILLEGAL;
19631055Sminshall 	    } else {
19731055Sminshall 		pC->type = LEX_ESCAPED;
19831055Sminshall 		switch (character) {
19931055Sminshall 		case 'E': case 'e':
20031055Sminshall 		    character = ESCAPE;
20131055Sminshall 		    break;
20231055Sminshall 		case 't':
20331055Sminshall 		    character = TAB;
20431055Sminshall 		    break;
20531055Sminshall 		case 'n':
20631055Sminshall 		    character = NEWLINE;
20731055Sminshall 		    break;
20831055Sminshall 		case 'r':
20931055Sminshall 		    character = CARRIAGE_RETURN;
21031055Sminshall 		    break;
21131055Sminshall 		default:
21231055Sminshall 		    pC->type = LEX_ILLEGAL;
21331055Sminshall 		    break;
21431055Sminshall 		}
21531055Sminshall 	    }
21631055Sminshall 	    break;
21731055Sminshall 	default:
21831055Sminshall 	    if ((IsPrint(character)) || isspace(character)) {
21931055Sminshall 		pC->type = LEX_CHAR;
22031055Sminshall 	    } else {
22131055Sminshall 		pC->type = LEX_ILLEGAL;
22231055Sminshall 	    }
22331055Sminshall 	    break;
22431055Sminshall 	}
22531055Sminshall 	pC->value = character;
22631055Sminshall     }
22731055Sminshall     return(*pC);
22831055Sminshall }
22931055Sminshall 
23031055Sminshall static void
23131055Sminshall UnGet(c)
23231055Sminshall lexicon c;			/* character to unget */
23331055Sminshall {
23431055Sminshall     if (Full) {
23531055Sminshall 	fprintf(stderr, "attempt to put too many characters in lifo\n");
23631055Sminshall 	panic("map3270");
23731055Sminshall 	/* NOTREACHED */
23831055Sminshall     } else {
23931055Sminshall 	lifo[wp] = c;
24031055Sminshall 	wp++;
24131055Sminshall 	if (wp == sizeof lifo/sizeof (lexicon)) {
24231055Sminshall 	    wp = 0;
24331055Sminshall 	}
24431055Sminshall 	if (wp == rp) {
24531055Sminshall 	    Full = 1;
24631055Sminshall 	}
24731055Sminshall 	Empty = 0;
24831055Sminshall     }
24931055Sminshall }
25031055Sminshall 
25131100Sminshall /*
25231100Sminshall  * Construct a control character sequence
25331100Sminshall  * for a special character.
25431100Sminshall  */
25531100Sminshall char *
25631100Sminshall uncontrol(c)
25731100Sminshall 	register int c;
25831100Sminshall {
25931100Sminshall 	static char buf[3];
26031100Sminshall 
26131100Sminshall 	if (c == 0x7f)
26231100Sminshall 		return ("^?");
26331100Sminshall 	if (c == '\377') {
26431100Sminshall 		return "-1";
26531100Sminshall 	}
26631100Sminshall 	if (c >= 0x20) {
26731100Sminshall 		buf[0] = c;
26831100Sminshall 		buf[1] = 0;
26931100Sminshall 	} else {
27031100Sminshall 		buf[0] = '^';
27131100Sminshall 		buf[1] = '@'+c;
27231100Sminshall 		buf[2] = 0;
27331100Sminshall 	}
27431100Sminshall 	return (buf);
27531100Sminshall }
27631100Sminshall 
27731055Sminshall /* compare two strings, ignoring case */
27831055Sminshall 
27931055Sminshall ustrcmp(string1, string2)
28031055Sminshall register char *string1;
28131055Sminshall register char *string2;
28231055Sminshall {
28331055Sminshall     register int c1, c2;
28431055Sminshall 
28531055Sminshall     while ((c1 = (unsigned char) *string1++) != 0) {
28631055Sminshall 	if (isupper(c1)) {
28731055Sminshall 	    c1 = tolower(c1);
28831055Sminshall 	}
28931055Sminshall 	if (isupper(c2 = (unsigned char) *string2++)) {
29031055Sminshall 	    c2 = tolower(c2);
29131055Sminshall 	}
29231055Sminshall 	if (c1 < c2) {
29331055Sminshall 	    return(-1);
29431055Sminshall 	} else if (c1 > c2) {
29531055Sminshall 	    return(1);
29631055Sminshall 	}
29731055Sminshall     }
29831055Sminshall     if (*string2) {
29931055Sminshall 	return(-1);
30031055Sminshall     } else {
30131055Sminshall 	return(0);
30231055Sminshall     }
30331055Sminshall }
30431055Sminshall 
30531055Sminshall 
30631055Sminshall static stringWithLength *
30731055Sminshall GetQuotedString()
30831055Sminshall {
30931055Sminshall     lexicon lex;
31031055Sminshall     static stringWithLength output = { 0 };	/* where return value is held */
31131055Sminshall     char *pointer = output.array;
31231055Sminshall 
31331055Sminshall     lex = Get();
31431055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != '\'')) {
31531055Sminshall 	UnGet(lex);
31631055Sminshall 	return(0);
31731055Sminshall     }
31831055Sminshall     while (1) {
31931055Sminshall 	lex = Get();
32031055Sminshall 	if ((lex.type == LEX_CHAR) && (lex.value == '\'')) {
32131055Sminshall 	    break;
32231055Sminshall 	}
32331055Sminshall 	if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) {
32431055Sminshall 	    UnGet(lex);
32531055Sminshall 	    return(0);		/* illegal character in quoted string */
32631055Sminshall 	}
32731055Sminshall 	if (pointer >= output.array+sizeof output.array) {
32831055Sminshall 	    return(0);		/* too long */
32931055Sminshall 	}
33031055Sminshall 	*pointer++ = lex.value;
33131055Sminshall     }
33231055Sminshall     output.length = pointer-output.array;
33331055Sminshall     return(&output);
33431055Sminshall }
33531055Sminshall 
33631055Sminshall #ifdef	NOTUSED
33731055Sminshall static stringWithLength *
33831055Sminshall GetCharString()
33931055Sminshall {
34031055Sminshall     lexicon lex;
34131055Sminshall     static stringWithLength output;
34231055Sminshall     char *pointer = output.array;
34331055Sminshall 
34431055Sminshall     lex = Get();
34531055Sminshall 
34631055Sminshall     while ((lex.type == LEX_CHAR) &&
34731055Sminshall 			!isspace(lex.value) && (lex.value != '=')) {
34831055Sminshall 	*pointer++ = lex.value;
34931055Sminshall 	lex = Get();
35031055Sminshall 	if (pointer >= output.array + sizeof output.array) {
35131055Sminshall 	    return(0);		/* too long */
35231055Sminshall 	}
35331055Sminshall     }
35431055Sminshall     UnGet(lex);
35531055Sminshall     output.length = pointer-output.array;
35631055Sminshall     return(&output);
35731055Sminshall }
35831055Sminshall #endif	/* NOTUSED */
35931055Sminshall 
36031055Sminshall static
36131055Sminshall GetCharacter(character)
36231055Sminshall int	character;		/* desired character */
36331055Sminshall {
36431055Sminshall     lexicon lex;
36531055Sminshall 
36631055Sminshall     lex = Get();
36731055Sminshall 
36831055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != character)) {
36931055Sminshall 	UnGet(lex);
37031055Sminshall 	return(0);
37131055Sminshall     }
37231055Sminshall     return(1);
37331055Sminshall }
37431055Sminshall 
37531055Sminshall #ifdef	NOTUSED
37631055Sminshall static
37731055Sminshall GetString(string)
37831055Sminshall char	*string;		/* string to get */
37931055Sminshall {
38031055Sminshall     lexicon lex;
38131055Sminshall 
38231055Sminshall     while (*string) {
38331055Sminshall 	lex = Get();
38431055Sminshall 	if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) {
38531055Sminshall 	    UnGet(lex);
38631055Sminshall 	    return(0);		/* XXX restore to state on entry */
38731055Sminshall 	}
38831055Sminshall 	string++;
38931055Sminshall     }
39031055Sminshall     return(1);
39131055Sminshall }
39231055Sminshall #endif	/* NOTUSED */
39331055Sminshall 
39431055Sminshall 
39531055Sminshall static stringWithLength *
39631055Sminshall GetAlphaMericString()
39731055Sminshall {
39831055Sminshall     lexicon lex;
39931055Sminshall     static stringWithLength output = { 0 };
40031055Sminshall     char *pointer = output.array;
40131055Sminshall #   define	IsAlnum(c)	(isalnum(c) || (c == '_') \
40231055Sminshall 					|| (c == '-') || (c == '.'))
40331055Sminshall 
40431055Sminshall     lex = Get();
40531055Sminshall 
40631055Sminshall     if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) {
40731055Sminshall 	UnGet(lex);
40831055Sminshall 	return(0);
40931055Sminshall     }
41031055Sminshall 
41131055Sminshall     while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) {
41231055Sminshall 	*pointer++ = lex.value;
41331055Sminshall 	lex = Get();
41431055Sminshall     }
41531055Sminshall     UnGet(lex);
41631055Sminshall     *pointer = 0;
41731055Sminshall     output.length = pointer-output.array;
41831055Sminshall     return(&output);
41931055Sminshall }
42031055Sminshall 
42131055Sminshall 
42231055Sminshall /* eat up characters until a new line, or end of file.  returns terminating
42331055Sminshall 	character.
42431055Sminshall  */
42531055Sminshall 
42631055Sminshall static lexicon
42731055Sminshall EatToNL()
42831055Sminshall {
42931055Sminshall     lexicon lex;
43031055Sminshall 
43131055Sminshall     lex = Get();
43231055Sminshall 
43331055Sminshall     while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) &&
43431055Sminshall 		(lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) {
43531055Sminshall 	lex = Get();
43631055Sminshall     }
43731055Sminshall     if (lex.type != LEX_END_OF_FILE) {
43831055Sminshall 	return(Get());
43931055Sminshall     } else {
44031055Sminshall 	return(lex);
44131055Sminshall     }
44231055Sminshall }
44331055Sminshall 
44431055Sminshall 
44531055Sminshall static void
44631055Sminshall GetWS()
44731055Sminshall {
44831055Sminshall     lexicon lex;
44931055Sminshall 
45031055Sminshall     lex = Get();
45131055Sminshall 
45231055Sminshall     while ((lex.type == LEX_CHAR) &&
45331055Sminshall 			(isspace(lex.value) || (lex.value == '#'))) {
45431055Sminshall 	if (lex.value == '#') {
45531055Sminshall 	    lex = EatToNL();
45631055Sminshall 	} else {
45731055Sminshall 	    lex = Get();
45831055Sminshall 	}
45931055Sminshall     }
46031055Sminshall     UnGet(lex);
46131055Sminshall }
46231055Sminshall 
46331055Sminshall static void
46431055Sminshall FreeState(pState)
46531055Sminshall state *pState;
46631055Sminshall {
46731055Sminshall     extern void free();
46831055Sminshall 
46931055Sminshall     free((char *)pState);
47031055Sminshall }
47131055Sminshall 
47231055Sminshall 
47331055Sminshall static state *
47431055Sminshall GetState()
47531055Sminshall {
47631055Sminshall     state *pState;
47731055Sminshall     extern char *malloc();
47831055Sminshall 
47931055Sminshall     pState = (state *) malloc(sizeof (state));
48031055Sminshall 
48131055Sminshall     pState->result = TC_NULL;
48231055Sminshall     pState->next = 0;
48331055Sminshall 
48431055Sminshall     return(pState);
48531055Sminshall }
48631055Sminshall 
48731055Sminshall 
48831055Sminshall static state *
48931055Sminshall FindMatchAtThisLevel(pState, character)
49031055Sminshall state	*pState;
49131055Sminshall int	character;
49231055Sminshall {
49331055Sminshall     while (pState) {
49431055Sminshall 	if (pState->match == character) {
49531055Sminshall 	    return(pState);
49631055Sminshall 	}
49731055Sminshall 	pState = pState->next;
49831055Sminshall     }
49931055Sminshall     return(0);
50031055Sminshall }
50131055Sminshall 
50231055Sminshall 
50331055Sminshall static state *
50431055Sminshall PasteEntry(head, string, count, identifier)
50531055Sminshall state			*head;		/* points to who should point here... */
50631055Sminshall char			*string;	/* which characters to paste */
50731055Sminshall int			count;		/* number of character to do */
50831055Sminshall char			*identifier;	/* for error messages */
50931055Sminshall {
51031055Sminshall     state *pState, *other;
51131055Sminshall 
51231055Sminshall     if (!doPaste) {		/* flag to not have any side effects */
51331055Sminshall 	return((state *)1);
51431055Sminshall     }
51531055Sminshall     if (!count) {
51631055Sminshall 	return(head);	/* return pointer to the parent */
51731055Sminshall     }
51831055Sminshall     if ((head->result != TC_NULL) && (head->result != TC_GOTO)) {
51931055Sminshall 	/* this means that a previously defined sequence is an initial
52031055Sminshall 	 * part of this one.
52131055Sminshall 	 */
52231055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
52331055Sminshall 		identifier);
52431055Sminshall 	return(0);
52531055Sminshall     }
52631055Sminshall #   ifdef	DEBUG
52731055Sminshall 	if (debug) {
52831100Sminshall 	    fprintf(stderr, "%s", uncontrol(*string));
52931055Sminshall 	}
53031055Sminshall #   endif	/* DEBUG */
53131055Sminshall     pState = GetState();
53231055Sminshall     pState->match = *string;
53331055Sminshall     if (head->result == TC_NULL) {
53431055Sminshall 	head->result = TC_GOTO;
53531055Sminshall 	head->address = pState;
53631055Sminshall 	other = pState;
53731055Sminshall     } else {		/* search for same character */
53831055Sminshall 	if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) {
53931055Sminshall 	    FreeState(pState);
54031055Sminshall 	} else {
54131055Sminshall 	    pState->next = head->address;
54231055Sminshall 	    head->address = pState;
54331055Sminshall 	    other = pState;
54431055Sminshall 	}
54531055Sminshall     }
54631055Sminshall     return(PasteEntry(other, string+1, count-1, identifier));
54731055Sminshall }
54831055Sminshall 
54931055Sminshall static
55031055Sminshall GetInput(tc, identifier)
55131055Sminshall int tc;
55231055Sminshall char *identifier;		/* entry being parsed (for error messages) */
55331055Sminshall {
55431055Sminshall     stringWithLength *outputString;
55531055Sminshall     state *head;
55631055Sminshall     state fakeQueue;
55731055Sminshall 
55831055Sminshall     if (doPaste) {
55931055Sminshall 	head = headOfQueue;	/* always points to level above this one */
56031055Sminshall     } else {
56131055Sminshall 	head = &fakeQueue;	/* don't have any side effects... */
56231055Sminshall     }
56331055Sminshall 
56431055Sminshall     if ((outputString = GetQuotedString()) == 0) {
56531055Sminshall 	return(0);
56631055Sminshall     } else if (IsPrint(outputString->array[0])) {
56731055Sminshall 	fprintf(stderr,
56831055Sminshall 	 "first character of sequence for %s is not a control type character\n",
56931055Sminshall 		identifier);
57031055Sminshall 	return(0);
57131055Sminshall     } else {
57231055Sminshall 	if ((head = PasteEntry(head, outputString->array,
57331055Sminshall 				outputString->length, identifier)) == 0) {
57431055Sminshall 	    return(0);
57531055Sminshall 	}
57631055Sminshall 	GetWS();
57731055Sminshall 	while ((outputString = GetQuotedString()) != 0) {
57831055Sminshall 	    if ((head = PasteEntry(head, outputString->array,
57931055Sminshall 				outputString->length, identifier)) == 0) {
58031055Sminshall 		return(0);
58131055Sminshall 	    }
58231055Sminshall 	    GetWS();
58331055Sminshall 	}
58431055Sminshall     }
58531055Sminshall     if (!doPaste) {
58631055Sminshall 	return(1);
58731055Sminshall     }
58831055Sminshall     if ((head->result != TC_NULL) && (head->result != tc)) {
58931055Sminshall 	/* this means that this sequence is an initial part
59031055Sminshall 	 * of a previously defined one.
59131055Sminshall 	 */
59231055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
59331055Sminshall 		identifier);
59431055Sminshall 	return(0);
59531055Sminshall     } else {
59631055Sminshall 	head->result = tc;
59731055Sminshall 	return(1);		/* done */
59831055Sminshall     }
59931055Sminshall }
60031055Sminshall 
60131055Sminshall static
60231055Sminshall GetTc(string)
60331055Sminshall char *string;
60431055Sminshall {
60531055Sminshall     register TC_Ascii_t *Tc;
60631055Sminshall 
60731055Sminshall     for (Tc = TC_Ascii;
60831055Sminshall 		Tc < TC_Ascii+sizeof TC_Ascii/sizeof (TC_Ascii_t); Tc++) {
60931055Sminshall 	if (!ustrcmp(string, Tc->tc_name)) {
61031055Sminshall #	    ifdef	DEBUG
61131055Sminshall 		if (debug) {
61231055Sminshall 		    fprintf(stderr, "%s = ", Tc->tc_name);
61331055Sminshall 		}
61431055Sminshall #	    endif	/* DEBUG */
61531055Sminshall 	    return(Tc->tc_value&0xff);
61631055Sminshall 	}
61731055Sminshall     }
61831055Sminshall     return(0);
61931055Sminshall }
62031055Sminshall static
62131055Sminshall GetDefinition()
62231055Sminshall {
62331055Sminshall     stringWithLength *string;
62431055Sminshall     int Tc;
62531055Sminshall 
62631055Sminshall     GetWS();
62731055Sminshall     if ((string = GetAlphaMericString()) == 0) {
62831055Sminshall 	return(0);
62931055Sminshall     }
63031055Sminshall     string->array[string->length] = 0;
63131055Sminshall     if (doPaste) {
63231055Sminshall 	if ((Tc = GetTc(string->array)) == 0) {
63331055Sminshall 	    if (picky) {
63431055Sminshall 		fprintf(stderr, "%s: unknown 3270 key identifier\n",
63531055Sminshall 							string->array);
63631055Sminshall 	    }
63731055Sminshall 	    Tc = TC_NULL;
63831055Sminshall 	} else if (Tc < TC_LOWEST_USER) {
63931055Sminshall 	    fprintf(stderr, "%s is not allowed to be specified by a user.\n",
64031055Sminshall 			string->array);
64131055Sminshall 	    return(0);
64231055Sminshall 	}
64331055Sminshall     } else {
64431055Sminshall 	Tc = TC_LOWEST_USER;
64531055Sminshall     }
64631055Sminshall     GetWS();
64731055Sminshall     if (!GetCharacter('=')) {
64831055Sminshall 	fprintf(stderr,
64931055Sminshall 		"Required equal sign after 3270 key identifier %s missing\n",
65031055Sminshall 			string->array);
65131055Sminshall 	return(0);
65231055Sminshall     }
65331055Sminshall     GetWS();
65431055Sminshall     if (!GetInput(Tc, string->array)) {
65531055Sminshall 	fprintf(stderr, "Missing definition part for 3270 key %s\n",
65631055Sminshall 				string->array);
65731055Sminshall 	return(0);
65831055Sminshall     } else {
65931055Sminshall 	GetWS();
66031055Sminshall 	while (GetCharacter('|')) {
66131055Sminshall #	    ifdef	DEBUG
66231055Sminshall 		if (debug) {
66331055Sminshall 		    fprintf(stderr, " or ");
66431055Sminshall 		}
66531055Sminshall #	    endif	/* DEBUG */
66631055Sminshall 	    GetWS();
66731055Sminshall 	    if (!GetInput(Tc, string->array)) {
66831055Sminshall 		fprintf(stderr, "Missing definition part for 3270 key %s\n",
66931055Sminshall 					string->array);
67031055Sminshall 		return(0);
67131055Sminshall 	    }
67231055Sminshall 	    GetWS();
67331055Sminshall 	}
67431055Sminshall     }
67531055Sminshall     GetWS();
67631055Sminshall     if (!GetCharacter(';')) {
67731055Sminshall 	fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array);
67831055Sminshall 	return(0);
67931055Sminshall     }
68031055Sminshall #   ifdef	DEBUG
68131055Sminshall 	if (debug) {
68231055Sminshall 	    fprintf(stderr, ";\n");
68331055Sminshall 	}
68431055Sminshall #   endif	/* DEBUG */
68531055Sminshall     return(1);
68631055Sminshall }
68731055Sminshall 
68831055Sminshall 
68931055Sminshall static
69031055Sminshall GetDefinitions()
69131055Sminshall {
69231055Sminshall     if (!GetDefinition()) {
69331055Sminshall 	return(0);
69431055Sminshall     } else {
69531055Sminshall 	while (GetDefinition()) {
69631055Sminshall 	    ;
69731055Sminshall 	}
69831055Sminshall     }
69931055Sminshall     return(1);
70031055Sminshall }
70131055Sminshall 
70231055Sminshall static
70331055Sminshall GetBegin()
70431055Sminshall {
70531055Sminshall     GetWS();
70631055Sminshall     if (!GetCharacter('{')) {
70731055Sminshall 	return(0);
70831055Sminshall     }
70931055Sminshall     return(1);
71031055Sminshall }
71131055Sminshall 
71231055Sminshall static
71331055Sminshall GetEnd()
71431055Sminshall {
71531055Sminshall     GetWS();
71631055Sminshall     if (!GetCharacter('}')) {
71731055Sminshall 	return(0);
71831055Sminshall     }
71931055Sminshall     return(1);
72031055Sminshall }
72131055Sminshall 
72231055Sminshall static
72331055Sminshall GetName()
72431055Sminshall {
72531055Sminshall     if (!GetAlphaMericString()) {
72631055Sminshall 	return(0);
72731055Sminshall     }
72831055Sminshall     GetWS();
72931055Sminshall     while (GetAlphaMericString()) {
73031055Sminshall 	GetWS();
73131055Sminshall     }
73231055Sminshall     return(1);
73331055Sminshall }
73431055Sminshall 
73531055Sminshall static
73631055Sminshall GetNames()
73731055Sminshall {
73831055Sminshall     GetWS();
73931055Sminshall     if (!GetName()) {
74031055Sminshall 	return(0);
74131055Sminshall     } else {
74231055Sminshall 	GetWS();
74331055Sminshall 	while (GetCharacter('|')) {
74431055Sminshall 	    GetWS();
74531055Sminshall 	    if (!GetName()) {
74631055Sminshall 		return(0);
74731055Sminshall 	    }
74831055Sminshall 	}
74931055Sminshall     }
75031055Sminshall     return(1);
75131055Sminshall }
75231055Sminshall 
75331055Sminshall static
75431055Sminshall GetEntry0()
75531055Sminshall {
75631055Sminshall     if (!GetBegin()) {
75731055Sminshall 	fprintf(stderr, "no '{'\n");
75831055Sminshall 	return(0);
75931055Sminshall     } else if (!GetDefinitions()) {
76031055Sminshall 	fprintf(stderr, "unable to parse the definitions\n");
76131055Sminshall 	return(0);
76231055Sminshall     } else if (!GetEnd()) {
76331055Sminshall 	fprintf(stderr, "No '}' or scanning stopped early due to error.\n");
76431055Sminshall 	return(0);
76531055Sminshall     } else {
76631055Sminshall 	/* done */
76731055Sminshall 	return(1);
76831055Sminshall     }
76931055Sminshall }
77031055Sminshall 
77131055Sminshall 
77231055Sminshall static
77331055Sminshall GetEntry()
77431055Sminshall {
77531055Sminshall     if (!GetNames()) {
77631055Sminshall 	fprintf(stderr, "Invalid name field in entry.\n");
77731055Sminshall 	return(0);
77831055Sminshall     } else {
77931055Sminshall 	return(GetEntry0());
78031055Sminshall     }
78131055Sminshall }
78231055Sminshall 
78331055Sminshall /* position ourselves within a given filename to the entry for the current
78431055Sminshall  *	KEYBD (or TERM) variable
78531055Sminshall  */
78631055Sminshall 
78731055Sminshall Position(filename, keybdPointer)
78831055Sminshall char *filename;
78931055Sminshall char *keybdPointer;
79031055Sminshall {
79131055Sminshall     lexicon lex;
79231055Sminshall     stringWithLength *name = 0;
79331055Sminshall     stringWithLength *oldName;
79431055Sminshall #   define	Return(x) {doPaste = 1; return(x);}
79531055Sminshall 
79631055Sminshall     doPaste = 0;
79731055Sminshall 
79831055Sminshall     if ((ourFile = fopen(filename, "r")) == NULL) {
79931100Sminshall #   if !defined(MSDOS)
80031055Sminshall 	fprintf(stderr, "Unable to open file %s\n", filename);
80131100Sminshall #   endif /* !defined(MSDOS) */
80231055Sminshall 	Return(0);
80331055Sminshall     }
80431055Sminshall     lex = Get();
80531055Sminshall     while (lex.type != LEX_END_OF_FILE) {
80631055Sminshall 	UnGet(lex);
80731055Sminshall 	/* now, find an entry that is our type. */
80831055Sminshall 	GetWS();
80931055Sminshall 	oldName = name;
81031055Sminshall 	if ((name = GetAlphaMericString()) != 0) {
81131055Sminshall 	    if (!ustrcmp(name->array, keybdPointer)) {
81231055Sminshall 		/* need to make sure there is a name here... */
81331055Sminshall 		lex.type = LEX_CHAR;
81431055Sminshall 		lex.value = 'a';
81531055Sminshall 		UnGet(lex);
81631055Sminshall 		Return(1);
81731055Sminshall 	    }
81831055Sminshall 	} else if (GetCharacter('|')) {
81931055Sminshall 	    ;		/* more names coming */
82031055Sminshall 	} else {
82131055Sminshall 	    lex = Get();
82231055Sminshall 	    UnGet(lex);
82331055Sminshall 	    if (lex.type != LEX_END_OF_FILE) {
82431055Sminshall 		    if (!GetEntry0()) {	/* start of an entry */
82531055Sminshall 			fprintf(stderr,
82631055Sminshall 			    "error was in entry for %s in file %s\n",
82731055Sminshall 			    (oldName)? oldName->array:"(unknown)", filename);
82831055Sminshall 		    Return(0);
82931055Sminshall 		}
83031055Sminshall 	    }
83131055Sminshall 	}
83231055Sminshall 	lex = Get();
83331055Sminshall     }
83431100Sminshall #if !defined(MSDOS)
83531055Sminshall     fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer,
83631055Sminshall 		    filename);
83731100Sminshall #endif	/* !defined(MSDOS) */
83831055Sminshall     Return(0);
83931055Sminshall }
84031055Sminshall 
84131055Sminshall char *
84231055Sminshall strsave(string)
84331055Sminshall char *string;
84431055Sminshall {
84531055Sminshall     char *p;
84631055Sminshall     extern char *malloc();
84731055Sminshall 
84831055Sminshall     p = malloc(strlen(string)+1);
84931055Sminshall     if (p != 0) {
85031055Sminshall 	strcpy(p, string);
85131055Sminshall     }
85231055Sminshall     return(p);
85331055Sminshall }
85431055Sminshall 
85531055Sminshall 
85631055Sminshall /*
85731055Sminshall  * InitControl - our interface to the outside.  What we should
85831055Sminshall  *  do is figure out keyboard (or terminal) type, set up file pointer
85931055Sminshall  *  (or string pointer), etc.
86031055Sminshall  */
86131055Sminshall 
86231055Sminshall state *
86331055Sminshall InitControl(keybdPointer, pickyarg)
86431055Sminshall char	*keybdPointer;
86531055Sminshall int	pickyarg;		/* Should we be picky? */
86631055Sminshall {
86731055Sminshall     extern char *getenv();
86831055Sminshall     int GotIt;
86931055Sminshall 
87031055Sminshall     picky = pickyarg;
87131055Sminshall 
87231055Sminshall     if (keybdPointer == 0) {
87331055Sminshall         keybdPointer = getenv("KEYBD");
87431055Sminshall     }
87531055Sminshall     if (keybdPointer == 0) {
87631055Sminshall        keybdPointer = getenv("TERM");
87731055Sminshall     }
87831055Sminshall 
87931055Sminshall 		    /*
88031055Sminshall 		     * Some environments have getenv() return
88131055Sminshall 		     * out of a static area.  So, save the keyboard name.
88231055Sminshall 		     */
88331055Sminshall     if (keybdPointer) {
88431055Sminshall         keybdPointer = strsave(keybdPointer);
88531055Sminshall     }
88631055Sminshall     environPointer = getenv("MAP3270");
88731055Sminshall     if (environPointer
88831055Sminshall 	    && (environPointer[0] != '/')
88931100Sminshall #if	defined(MSDOS)
89031055Sminshall 	    && (environPointer[0] != '\\')
89131100Sminshall #endif	/* defined(MSDOS) */
89231055Sminshall 	    && (strncmp(keybdPointer, environPointer,
89331055Sminshall 			strlen(keybdPointer) != 0)
89431055Sminshall 		|| (environPointer[strlen(keybdPointer)] != '{'))) /* } */
89531055Sminshall     {
89631055Sminshall 	environPointer = 0;
89731055Sminshall     }
89831055Sminshall 
89931055Sminshall     if ((!environPointer)
90031100Sminshall #if	defined(MSDOS)
90131055Sminshall 		|| (*environPointer == '\\')
90231100Sminshall #endif	/* defined(MSDOS) */
90331055Sminshall 		|| (*environPointer == '/')) {
90431055Sminshall 	usePointer = 0;
90531055Sminshall 	GotIt = 0;
90631055Sminshall 	if (!keybdPointer) {
90731100Sminshall #if !defined(MSDOS)
90831055Sminshall 	    fprintf(stderr, "%s%s%s%s",
90931055Sminshall 		"Neither the KEYBD environment variable nor the TERM ",
91031055Sminshall 		"environment variable\n(one of which is needed to determine ",
91131055Sminshall 		"the type of keyboard you are using)\n",
91231055Sminshall 		"is set.  To set it, say 'setenv KEYBD <type>'\n");
91331100Sminshall #endif	/* !defined(MSDOS) */
91431055Sminshall 	} else {
91531055Sminshall 	    if (environPointer) {
91631055Sminshall 		GotIt = Position(environPointer, keybdPointer);
91731055Sminshall 	    }
91831055Sminshall 	    if (!GotIt) {
91931055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
92031055Sminshall 	    }
92131055Sminshall 	}
92231055Sminshall 	if (!GotIt) {
92331055Sminshall 	    if (environPointer) {
92431055Sminshall 		GotIt = Position(environPointer, "unknown");
92531055Sminshall 	    }
92631055Sminshall 	    if (!GotIt) {
92731055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
92831055Sminshall 	    }
92931055Sminshall 	}
93031055Sminshall 	if (!GotIt) {
93131100Sminshall #if !defined(MSDOS)
93231055Sminshall 	    fprintf(stderr, "Using default key mappings.\n");
93331100Sminshall #endif	/* !defined(MSDOS) */
93431055Sminshall 	    usePointer = 1;		/* flag use of non-file */
935*31135Sminshall 	    whichkey = keysgeneric;
936*31135Sminshall 	    environPointer = *whichkey;	/* use default table */
93731055Sminshall 	}
93831055Sminshall     } else {
93931055Sminshall 	usePointer = 1;
94031055Sminshall     }
94131055Sminshall     (void) GetEntry();
94231055Sminshall     return(firstentry.address);
94331055Sminshall }
944