xref: /csrg-svn/usr.bin/tn3270/ascii/map3270.c (revision 31100)
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>
49*31100Sminshall #if	defined(unix)
5031055Sminshall #include <strings.h>
51*31100Sminshall #else	/* defined(unix) */
52*31100Sminshall #include <string.h>
53*31100Sminshall #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 					 */
10831055Sminshall static char keys3a[] =
10931055Sminshall #include "default.map"		/* Define the default default */
11031055Sminshall 			;
11131055Sminshall 
11231055Sminshall static	int	Empty = 1,		/* is the unget lifo empty? */
11331055Sminshall 		Full = 0;		/* is the unget lifo full? */
114*31100Sminshall static	lexicon	lifo[200] = { 0 };	/* character stack for parser */
11531055Sminshall static	int	rp = 0,			/* read pointer into lifo */
11631055Sminshall 		wp = 0;			/* write pointer into lifo */
11731055Sminshall 
11831055Sminshall static int
11931055Sminshall GetC()
12031055Sminshall {
12131055Sminshall     int character;
12231055Sminshall 
12331055Sminshall     if (usePointer) {
12431055Sminshall 	if (*environPointer) {
12531055Sminshall 	    character = 0xff&*environPointer++;
12631055Sminshall 	} else {
12731055Sminshall 	    static char suffix = 'A';
12831055Sminshall 	    char envname[9];
12931055Sminshall 	    extern char *getenv();
13031055Sminshall 
13131055Sminshall 	    (void) sprintf(envname, "MAP3270%c", suffix++);
13231055Sminshall 	    environPointer = getenv(envname);
13331055Sminshall 	    if (*environPointer) {
13431055Sminshall 	       character = 0xff&*environPointer++;
13531055Sminshall 	    } else {
13631055Sminshall 	       character = EOF;
13731055Sminshall 	    }
13831055Sminshall 	}
13931055Sminshall     } else {
14031055Sminshall 	character = getc(ourFile);
14131055Sminshall     }
14231055Sminshall     return(character);
14331055Sminshall }
14431055Sminshall 
14531055Sminshall static lexicon
14631055Sminshall Get()
14731055Sminshall {
14831055Sminshall     lexicon c;
14931055Sminshall     register lexicon *pC = &c;
15031055Sminshall     register int character;
15131055Sminshall 
15231055Sminshall     if (!Empty) {
15331055Sminshall 	*pC = lifo[rp];
15431055Sminshall 	rp++;
15531055Sminshall 	if (rp == sizeof lifo/sizeof (lexicon)) {
15631055Sminshall 	    rp = 0;
15731055Sminshall 	}
15831055Sminshall 	if (rp == wp) {
15931055Sminshall 	    Empty = 1;
16031055Sminshall 	}
16131055Sminshall 	Full = 0;
16231055Sminshall     } else {
16331055Sminshall 	character = GetC();
16431055Sminshall 	switch (character) {
16531055Sminshall 	case EOF:
16631055Sminshall 	    pC->type = LEX_END_OF_FILE;
16731055Sminshall 	    break;
16831055Sminshall 	case '^':
16931055Sminshall 	    character = GetC();
17031055Sminshall 	    if (!IsPrint(character)) {
17131055Sminshall 		pC->type = LEX_ILLEGAL;
17231055Sminshall 	    } else {
17331055Sminshall 		pC->type = LEX_CARETED;
17431055Sminshall 		if (character == '?') {
17531055Sminshall 		    character |= 0x40;	/* rubout */
17631055Sminshall 		} else {
17731055Sminshall 		    character &= 0x1f;
17831055Sminshall 		}
17931055Sminshall 	    }
18031055Sminshall 	    break;
18131055Sminshall 	case '\\':
18231055Sminshall 	    character = GetC();
18331055Sminshall 	    if (!IsPrint(character)) {
18431055Sminshall 		pC->type = LEX_ILLEGAL;
18531055Sminshall 	    } else {
18631055Sminshall 		pC->type = LEX_ESCAPED;
18731055Sminshall 		switch (character) {
18831055Sminshall 		case 'E': case 'e':
18931055Sminshall 		    character = ESCAPE;
19031055Sminshall 		    break;
19131055Sminshall 		case 't':
19231055Sminshall 		    character = TAB;
19331055Sminshall 		    break;
19431055Sminshall 		case 'n':
19531055Sminshall 		    character = NEWLINE;
19631055Sminshall 		    break;
19731055Sminshall 		case 'r':
19831055Sminshall 		    character = CARRIAGE_RETURN;
19931055Sminshall 		    break;
20031055Sminshall 		default:
20131055Sminshall 		    pC->type = LEX_ILLEGAL;
20231055Sminshall 		    break;
20331055Sminshall 		}
20431055Sminshall 	    }
20531055Sminshall 	    break;
20631055Sminshall 	default:
20731055Sminshall 	    if ((IsPrint(character)) || isspace(character)) {
20831055Sminshall 		pC->type = LEX_CHAR;
20931055Sminshall 	    } else {
21031055Sminshall 		pC->type = LEX_ILLEGAL;
21131055Sminshall 	    }
21231055Sminshall 	    break;
21331055Sminshall 	}
21431055Sminshall 	pC->value = character;
21531055Sminshall     }
21631055Sminshall     return(*pC);
21731055Sminshall }
21831055Sminshall 
21931055Sminshall static void
22031055Sminshall UnGet(c)
22131055Sminshall lexicon c;			/* character to unget */
22231055Sminshall {
22331055Sminshall     if (Full) {
22431055Sminshall 	fprintf(stderr, "attempt to put too many characters in lifo\n");
22531055Sminshall 	panic("map3270");
22631055Sminshall 	/* NOTREACHED */
22731055Sminshall     } else {
22831055Sminshall 	lifo[wp] = c;
22931055Sminshall 	wp++;
23031055Sminshall 	if (wp == sizeof lifo/sizeof (lexicon)) {
23131055Sminshall 	    wp = 0;
23231055Sminshall 	}
23331055Sminshall 	if (wp == rp) {
23431055Sminshall 	    Full = 1;
23531055Sminshall 	}
23631055Sminshall 	Empty = 0;
23731055Sminshall     }
23831055Sminshall }
23931055Sminshall 
240*31100Sminshall /*
241*31100Sminshall  * Construct a control character sequence
242*31100Sminshall  * for a special character.
243*31100Sminshall  */
244*31100Sminshall #if	defined(DEBUG)
245*31100Sminshall char *
246*31100Sminshall uncontrol(c)
247*31100Sminshall 	register int c;
248*31100Sminshall {
249*31100Sminshall 	static char buf[3];
250*31100Sminshall 
251*31100Sminshall 	if (c == 0x7f)
252*31100Sminshall 		return ("^?");
253*31100Sminshall 	if (c == '\377') {
254*31100Sminshall 		return "-1";
255*31100Sminshall 	}
256*31100Sminshall 	if (c >= 0x20) {
257*31100Sminshall 		buf[0] = c;
258*31100Sminshall 		buf[1] = 0;
259*31100Sminshall 	} else {
260*31100Sminshall 		buf[0] = '^';
261*31100Sminshall 		buf[1] = '@'+c;
262*31100Sminshall 		buf[2] = 0;
263*31100Sminshall 	}
264*31100Sminshall 	return (buf);
265*31100Sminshall }
266*31100Sminshall #endif	/* defined(DEBUG) */
267*31100Sminshall 
26831055Sminshall /* compare two strings, ignoring case */
26931055Sminshall 
27031055Sminshall ustrcmp(string1, string2)
27131055Sminshall register char *string1;
27231055Sminshall register char *string2;
27331055Sminshall {
27431055Sminshall     register int c1, c2;
27531055Sminshall 
27631055Sminshall     while ((c1 = (unsigned char) *string1++) != 0) {
27731055Sminshall 	if (isupper(c1)) {
27831055Sminshall 	    c1 = tolower(c1);
27931055Sminshall 	}
28031055Sminshall 	if (isupper(c2 = (unsigned char) *string2++)) {
28131055Sminshall 	    c2 = tolower(c2);
28231055Sminshall 	}
28331055Sminshall 	if (c1 < c2) {
28431055Sminshall 	    return(-1);
28531055Sminshall 	} else if (c1 > c2) {
28631055Sminshall 	    return(1);
28731055Sminshall 	}
28831055Sminshall     }
28931055Sminshall     if (*string2) {
29031055Sminshall 	return(-1);
29131055Sminshall     } else {
29231055Sminshall 	return(0);
29331055Sminshall     }
29431055Sminshall }
29531055Sminshall 
29631055Sminshall 
29731055Sminshall static stringWithLength *
29831055Sminshall GetQuotedString()
29931055Sminshall {
30031055Sminshall     lexicon lex;
30131055Sminshall     static stringWithLength output = { 0 };	/* where return value is held */
30231055Sminshall     char *pointer = output.array;
30331055Sminshall 
30431055Sminshall     lex = Get();
30531055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != '\'')) {
30631055Sminshall 	UnGet(lex);
30731055Sminshall 	return(0);
30831055Sminshall     }
30931055Sminshall     while (1) {
31031055Sminshall 	lex = Get();
31131055Sminshall 	if ((lex.type == LEX_CHAR) && (lex.value == '\'')) {
31231055Sminshall 	    break;
31331055Sminshall 	}
31431055Sminshall 	if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) {
31531055Sminshall 	    UnGet(lex);
31631055Sminshall 	    return(0);		/* illegal character in quoted string */
31731055Sminshall 	}
31831055Sminshall 	if (pointer >= output.array+sizeof output.array) {
31931055Sminshall 	    return(0);		/* too long */
32031055Sminshall 	}
32131055Sminshall 	*pointer++ = lex.value;
32231055Sminshall     }
32331055Sminshall     output.length = pointer-output.array;
32431055Sminshall     return(&output);
32531055Sminshall }
32631055Sminshall 
32731055Sminshall #ifdef	NOTUSED
32831055Sminshall static stringWithLength *
32931055Sminshall GetCharString()
33031055Sminshall {
33131055Sminshall     lexicon lex;
33231055Sminshall     static stringWithLength output;
33331055Sminshall     char *pointer = output.array;
33431055Sminshall 
33531055Sminshall     lex = Get();
33631055Sminshall 
33731055Sminshall     while ((lex.type == LEX_CHAR) &&
33831055Sminshall 			!isspace(lex.value) && (lex.value != '=')) {
33931055Sminshall 	*pointer++ = lex.value;
34031055Sminshall 	lex = Get();
34131055Sminshall 	if (pointer >= output.array + sizeof output.array) {
34231055Sminshall 	    return(0);		/* too long */
34331055Sminshall 	}
34431055Sminshall     }
34531055Sminshall     UnGet(lex);
34631055Sminshall     output.length = pointer-output.array;
34731055Sminshall     return(&output);
34831055Sminshall }
34931055Sminshall #endif	/* NOTUSED */
35031055Sminshall 
35131055Sminshall static
35231055Sminshall GetCharacter(character)
35331055Sminshall int	character;		/* desired character */
35431055Sminshall {
35531055Sminshall     lexicon lex;
35631055Sminshall 
35731055Sminshall     lex = Get();
35831055Sminshall 
35931055Sminshall     if ((lex.type != LEX_CHAR) || (lex.value != character)) {
36031055Sminshall 	UnGet(lex);
36131055Sminshall 	return(0);
36231055Sminshall     }
36331055Sminshall     return(1);
36431055Sminshall }
36531055Sminshall 
36631055Sminshall #ifdef	NOTUSED
36731055Sminshall static
36831055Sminshall GetString(string)
36931055Sminshall char	*string;		/* string to get */
37031055Sminshall {
37131055Sminshall     lexicon lex;
37231055Sminshall 
37331055Sminshall     while (*string) {
37431055Sminshall 	lex = Get();
37531055Sminshall 	if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) {
37631055Sminshall 	    UnGet(lex);
37731055Sminshall 	    return(0);		/* XXX restore to state on entry */
37831055Sminshall 	}
37931055Sminshall 	string++;
38031055Sminshall     }
38131055Sminshall     return(1);
38231055Sminshall }
38331055Sminshall #endif	/* NOTUSED */
38431055Sminshall 
38531055Sminshall 
38631055Sminshall static stringWithLength *
38731055Sminshall GetAlphaMericString()
38831055Sminshall {
38931055Sminshall     lexicon lex;
39031055Sminshall     static stringWithLength output = { 0 };
39131055Sminshall     char *pointer = output.array;
39231055Sminshall #   define	IsAlnum(c)	(isalnum(c) || (c == '_') \
39331055Sminshall 					|| (c == '-') || (c == '.'))
39431055Sminshall 
39531055Sminshall     lex = Get();
39631055Sminshall 
39731055Sminshall     if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) {
39831055Sminshall 	UnGet(lex);
39931055Sminshall 	return(0);
40031055Sminshall     }
40131055Sminshall 
40231055Sminshall     while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) {
40331055Sminshall 	*pointer++ = lex.value;
40431055Sminshall 	lex = Get();
40531055Sminshall     }
40631055Sminshall     UnGet(lex);
40731055Sminshall     *pointer = 0;
40831055Sminshall     output.length = pointer-output.array;
40931055Sminshall     return(&output);
41031055Sminshall }
41131055Sminshall 
41231055Sminshall 
41331055Sminshall /* eat up characters until a new line, or end of file.  returns terminating
41431055Sminshall 	character.
41531055Sminshall  */
41631055Sminshall 
41731055Sminshall static lexicon
41831055Sminshall EatToNL()
41931055Sminshall {
42031055Sminshall     lexicon lex;
42131055Sminshall 
42231055Sminshall     lex = Get();
42331055Sminshall 
42431055Sminshall     while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) &&
42531055Sminshall 		(lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) {
42631055Sminshall 	lex = Get();
42731055Sminshall     }
42831055Sminshall     if (lex.type != LEX_END_OF_FILE) {
42931055Sminshall 	return(Get());
43031055Sminshall     } else {
43131055Sminshall 	return(lex);
43231055Sminshall     }
43331055Sminshall }
43431055Sminshall 
43531055Sminshall 
43631055Sminshall static void
43731055Sminshall GetWS()
43831055Sminshall {
43931055Sminshall     lexicon lex;
44031055Sminshall 
44131055Sminshall     lex = Get();
44231055Sminshall 
44331055Sminshall     while ((lex.type == LEX_CHAR) &&
44431055Sminshall 			(isspace(lex.value) || (lex.value == '#'))) {
44531055Sminshall 	if (lex.value == '#') {
44631055Sminshall 	    lex = EatToNL();
44731055Sminshall 	} else {
44831055Sminshall 	    lex = Get();
44931055Sminshall 	}
45031055Sminshall     }
45131055Sminshall     UnGet(lex);
45231055Sminshall }
45331055Sminshall 
45431055Sminshall static void
45531055Sminshall FreeState(pState)
45631055Sminshall state *pState;
45731055Sminshall {
45831055Sminshall     extern void free();
45931055Sminshall 
46031055Sminshall     free((char *)pState);
46131055Sminshall }
46231055Sminshall 
46331055Sminshall 
46431055Sminshall static state *
46531055Sminshall GetState()
46631055Sminshall {
46731055Sminshall     state *pState;
46831055Sminshall     extern char *malloc();
46931055Sminshall 
47031055Sminshall     pState = (state *) malloc(sizeof (state));
47131055Sminshall 
47231055Sminshall     pState->result = TC_NULL;
47331055Sminshall     pState->next = 0;
47431055Sminshall 
47531055Sminshall     return(pState);
47631055Sminshall }
47731055Sminshall 
47831055Sminshall 
47931055Sminshall static state *
48031055Sminshall FindMatchAtThisLevel(pState, character)
48131055Sminshall state	*pState;
48231055Sminshall int	character;
48331055Sminshall {
48431055Sminshall     while (pState) {
48531055Sminshall 	if (pState->match == character) {
48631055Sminshall 	    return(pState);
48731055Sminshall 	}
48831055Sminshall 	pState = pState->next;
48931055Sminshall     }
49031055Sminshall     return(0);
49131055Sminshall }
49231055Sminshall 
49331055Sminshall 
49431055Sminshall static state *
49531055Sminshall PasteEntry(head, string, count, identifier)
49631055Sminshall state			*head;		/* points to who should point here... */
49731055Sminshall char			*string;	/* which characters to paste */
49831055Sminshall int			count;		/* number of character to do */
49931055Sminshall char			*identifier;	/* for error messages */
50031055Sminshall {
50131055Sminshall     state *pState, *other;
50231055Sminshall 
50331055Sminshall     if (!doPaste) {		/* flag to not have any side effects */
50431055Sminshall 	return((state *)1);
50531055Sminshall     }
50631055Sminshall     if (!count) {
50731055Sminshall 	return(head);	/* return pointer to the parent */
50831055Sminshall     }
50931055Sminshall     if ((head->result != TC_NULL) && (head->result != TC_GOTO)) {
51031055Sminshall 	/* this means that a previously defined sequence is an initial
51131055Sminshall 	 * part of this one.
51231055Sminshall 	 */
51331055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
51431055Sminshall 		identifier);
51531055Sminshall 	return(0);
51631055Sminshall     }
51731055Sminshall #   ifdef	DEBUG
51831055Sminshall 	if (debug) {
519*31100Sminshall 	    fprintf(stderr, "%s", uncontrol(*string));
52031055Sminshall 	}
52131055Sminshall #   endif	/* DEBUG */
52231055Sminshall     pState = GetState();
52331055Sminshall     pState->match = *string;
52431055Sminshall     if (head->result == TC_NULL) {
52531055Sminshall 	head->result = TC_GOTO;
52631055Sminshall 	head->address = pState;
52731055Sminshall 	other = pState;
52831055Sminshall     } else {		/* search for same character */
52931055Sminshall 	if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) {
53031055Sminshall 	    FreeState(pState);
53131055Sminshall 	} else {
53231055Sminshall 	    pState->next = head->address;
53331055Sminshall 	    head->address = pState;
53431055Sminshall 	    other = pState;
53531055Sminshall 	}
53631055Sminshall     }
53731055Sminshall     return(PasteEntry(other, string+1, count-1, identifier));
53831055Sminshall }
53931055Sminshall 
54031055Sminshall static
54131055Sminshall GetInput(tc, identifier)
54231055Sminshall int tc;
54331055Sminshall char *identifier;		/* entry being parsed (for error messages) */
54431055Sminshall {
54531055Sminshall     stringWithLength *outputString;
54631055Sminshall     state *head;
54731055Sminshall     state fakeQueue;
54831055Sminshall 
54931055Sminshall     if (doPaste) {
55031055Sminshall 	head = headOfQueue;	/* always points to level above this one */
55131055Sminshall     } else {
55231055Sminshall 	head = &fakeQueue;	/* don't have any side effects... */
55331055Sminshall     }
55431055Sminshall 
55531055Sminshall     if ((outputString = GetQuotedString()) == 0) {
55631055Sminshall 	return(0);
55731055Sminshall     } else if (IsPrint(outputString->array[0])) {
55831055Sminshall 	fprintf(stderr,
55931055Sminshall 	 "first character of sequence for %s is not a control type character\n",
56031055Sminshall 		identifier);
56131055Sminshall 	return(0);
56231055Sminshall     } else {
56331055Sminshall 	if ((head = PasteEntry(head, outputString->array,
56431055Sminshall 				outputString->length, identifier)) == 0) {
56531055Sminshall 	    return(0);
56631055Sminshall 	}
56731055Sminshall 	GetWS();
56831055Sminshall 	while ((outputString = GetQuotedString()) != 0) {
56931055Sminshall 	    if ((head = PasteEntry(head, outputString->array,
57031055Sminshall 				outputString->length, identifier)) == 0) {
57131055Sminshall 		return(0);
57231055Sminshall 	    }
57331055Sminshall 	    GetWS();
57431055Sminshall 	}
57531055Sminshall     }
57631055Sminshall     if (!doPaste) {
57731055Sminshall 	return(1);
57831055Sminshall     }
57931055Sminshall     if ((head->result != TC_NULL) && (head->result != tc)) {
58031055Sminshall 	/* this means that this sequence is an initial part
58131055Sminshall 	 * of a previously defined one.
58231055Sminshall 	 */
58331055Sminshall 	fprintf(stderr, "Conflicting entries found when scanning %s\n",
58431055Sminshall 		identifier);
58531055Sminshall 	return(0);
58631055Sminshall     } else {
58731055Sminshall 	head->result = tc;
58831055Sminshall 	return(1);		/* done */
58931055Sminshall     }
59031055Sminshall }
59131055Sminshall 
59231055Sminshall static
59331055Sminshall GetTc(string)
59431055Sminshall char *string;
59531055Sminshall {
59631055Sminshall     register TC_Ascii_t *Tc;
59731055Sminshall 
59831055Sminshall     for (Tc = TC_Ascii;
59931055Sminshall 		Tc < TC_Ascii+sizeof TC_Ascii/sizeof (TC_Ascii_t); Tc++) {
60031055Sminshall 	if (!ustrcmp(string, Tc->tc_name)) {
60131055Sminshall #	    ifdef	DEBUG
60231055Sminshall 		if (debug) {
60331055Sminshall 		    fprintf(stderr, "%s = ", Tc->tc_name);
60431055Sminshall 		}
60531055Sminshall #	    endif	/* DEBUG */
60631055Sminshall 	    return(Tc->tc_value&0xff);
60731055Sminshall 	}
60831055Sminshall     }
60931055Sminshall     return(0);
61031055Sminshall }
61131055Sminshall static
61231055Sminshall GetDefinition()
61331055Sminshall {
61431055Sminshall     stringWithLength *string;
61531055Sminshall     int Tc;
61631055Sminshall 
61731055Sminshall     GetWS();
61831055Sminshall     if ((string = GetAlphaMericString()) == 0) {
61931055Sminshall 	return(0);
62031055Sminshall     }
62131055Sminshall     string->array[string->length] = 0;
62231055Sminshall     if (doPaste) {
62331055Sminshall 	if ((Tc = GetTc(string->array)) == 0) {
62431055Sminshall 	    if (picky) {
62531055Sminshall 		fprintf(stderr, "%s: unknown 3270 key identifier\n",
62631055Sminshall 							string->array);
62731055Sminshall 	    }
62831055Sminshall 	    Tc = TC_NULL;
62931055Sminshall 	} else if (Tc < TC_LOWEST_USER) {
63031055Sminshall 	    fprintf(stderr, "%s is not allowed to be specified by a user.\n",
63131055Sminshall 			string->array);
63231055Sminshall 	    return(0);
63331055Sminshall 	}
63431055Sminshall     } else {
63531055Sminshall 	Tc = TC_LOWEST_USER;
63631055Sminshall     }
63731055Sminshall     GetWS();
63831055Sminshall     if (!GetCharacter('=')) {
63931055Sminshall 	fprintf(stderr,
64031055Sminshall 		"Required equal sign after 3270 key identifier %s missing\n",
64131055Sminshall 			string->array);
64231055Sminshall 	return(0);
64331055Sminshall     }
64431055Sminshall     GetWS();
64531055Sminshall     if (!GetInput(Tc, string->array)) {
64631055Sminshall 	fprintf(stderr, "Missing definition part for 3270 key %s\n",
64731055Sminshall 				string->array);
64831055Sminshall 	return(0);
64931055Sminshall     } else {
65031055Sminshall 	GetWS();
65131055Sminshall 	while (GetCharacter('|')) {
65231055Sminshall #	    ifdef	DEBUG
65331055Sminshall 		if (debug) {
65431055Sminshall 		    fprintf(stderr, " or ");
65531055Sminshall 		}
65631055Sminshall #	    endif	/* DEBUG */
65731055Sminshall 	    GetWS();
65831055Sminshall 	    if (!GetInput(Tc, string->array)) {
65931055Sminshall 		fprintf(stderr, "Missing definition part for 3270 key %s\n",
66031055Sminshall 					string->array);
66131055Sminshall 		return(0);
66231055Sminshall 	    }
66331055Sminshall 	    GetWS();
66431055Sminshall 	}
66531055Sminshall     }
66631055Sminshall     GetWS();
66731055Sminshall     if (!GetCharacter(';')) {
66831055Sminshall 	fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array);
66931055Sminshall 	return(0);
67031055Sminshall     }
67131055Sminshall #   ifdef	DEBUG
67231055Sminshall 	if (debug) {
67331055Sminshall 	    fprintf(stderr, ";\n");
67431055Sminshall 	}
67531055Sminshall #   endif	/* DEBUG */
67631055Sminshall     return(1);
67731055Sminshall }
67831055Sminshall 
67931055Sminshall 
68031055Sminshall static
68131055Sminshall GetDefinitions()
68231055Sminshall {
68331055Sminshall     if (!GetDefinition()) {
68431055Sminshall 	return(0);
68531055Sminshall     } else {
68631055Sminshall 	while (GetDefinition()) {
68731055Sminshall 	    ;
68831055Sminshall 	}
68931055Sminshall     }
69031055Sminshall     return(1);
69131055Sminshall }
69231055Sminshall 
69331055Sminshall static
69431055Sminshall GetBegin()
69531055Sminshall {
69631055Sminshall     GetWS();
69731055Sminshall     if (!GetCharacter('{')) {
69831055Sminshall 	return(0);
69931055Sminshall     }
70031055Sminshall     return(1);
70131055Sminshall }
70231055Sminshall 
70331055Sminshall static
70431055Sminshall GetEnd()
70531055Sminshall {
70631055Sminshall     GetWS();
70731055Sminshall     if (!GetCharacter('}')) {
70831055Sminshall 	return(0);
70931055Sminshall     }
71031055Sminshall     return(1);
71131055Sminshall }
71231055Sminshall 
71331055Sminshall static
71431055Sminshall GetName()
71531055Sminshall {
71631055Sminshall     if (!GetAlphaMericString()) {
71731055Sminshall 	return(0);
71831055Sminshall     }
71931055Sminshall     GetWS();
72031055Sminshall     while (GetAlphaMericString()) {
72131055Sminshall 	GetWS();
72231055Sminshall     }
72331055Sminshall     return(1);
72431055Sminshall }
72531055Sminshall 
72631055Sminshall static
72731055Sminshall GetNames()
72831055Sminshall {
72931055Sminshall     GetWS();
73031055Sminshall     if (!GetName()) {
73131055Sminshall 	return(0);
73231055Sminshall     } else {
73331055Sminshall 	GetWS();
73431055Sminshall 	while (GetCharacter('|')) {
73531055Sminshall 	    GetWS();
73631055Sminshall 	    if (!GetName()) {
73731055Sminshall 		return(0);
73831055Sminshall 	    }
73931055Sminshall 	}
74031055Sminshall     }
74131055Sminshall     return(1);
74231055Sminshall }
74331055Sminshall 
74431055Sminshall static
74531055Sminshall GetEntry0()
74631055Sminshall {
74731055Sminshall     if (!GetBegin()) {
74831055Sminshall 	fprintf(stderr, "no '{'\n");
74931055Sminshall 	return(0);
75031055Sminshall     } else if (!GetDefinitions()) {
75131055Sminshall 	fprintf(stderr, "unable to parse the definitions\n");
75231055Sminshall 	return(0);
75331055Sminshall     } else if (!GetEnd()) {
75431055Sminshall 	fprintf(stderr, "No '}' or scanning stopped early due to error.\n");
75531055Sminshall 	return(0);
75631055Sminshall     } else {
75731055Sminshall 	/* done */
75831055Sminshall 	return(1);
75931055Sminshall     }
76031055Sminshall }
76131055Sminshall 
76231055Sminshall 
76331055Sminshall static
76431055Sminshall GetEntry()
76531055Sminshall {
76631055Sminshall     if (!GetNames()) {
76731055Sminshall 	fprintf(stderr, "Invalid name field in entry.\n");
76831055Sminshall 	return(0);
76931055Sminshall     } else {
77031055Sminshall 	return(GetEntry0());
77131055Sminshall     }
77231055Sminshall }
77331055Sminshall 
77431055Sminshall /* position ourselves within a given filename to the entry for the current
77531055Sminshall  *	KEYBD (or TERM) variable
77631055Sminshall  */
77731055Sminshall 
77831055Sminshall Position(filename, keybdPointer)
77931055Sminshall char *filename;
78031055Sminshall char *keybdPointer;
78131055Sminshall {
78231055Sminshall     lexicon lex;
78331055Sminshall     stringWithLength *name = 0;
78431055Sminshall     stringWithLength *oldName;
78531055Sminshall #   define	Return(x) {doPaste = 1; return(x);}
78631055Sminshall 
78731055Sminshall     doPaste = 0;
78831055Sminshall 
78931055Sminshall     if ((ourFile = fopen(filename, "r")) == NULL) {
790*31100Sminshall #   if !defined(MSDOS)
79131055Sminshall 	fprintf(stderr, "Unable to open file %s\n", filename);
792*31100Sminshall #   endif /* !defined(MSDOS) */
79331055Sminshall 	Return(0);
79431055Sminshall     }
79531055Sminshall     lex = Get();
79631055Sminshall     while (lex.type != LEX_END_OF_FILE) {
79731055Sminshall 	UnGet(lex);
79831055Sminshall 	/* now, find an entry that is our type. */
79931055Sminshall 	GetWS();
80031055Sminshall 	oldName = name;
80131055Sminshall 	if ((name = GetAlphaMericString()) != 0) {
80231055Sminshall 	    if (!ustrcmp(name->array, keybdPointer)) {
80331055Sminshall 		/* need to make sure there is a name here... */
80431055Sminshall 		lex.type = LEX_CHAR;
80531055Sminshall 		lex.value = 'a';
80631055Sminshall 		UnGet(lex);
80731055Sminshall 		Return(1);
80831055Sminshall 	    }
80931055Sminshall 	} else if (GetCharacter('|')) {
81031055Sminshall 	    ;		/* more names coming */
81131055Sminshall 	} else {
81231055Sminshall 	    lex = Get();
81331055Sminshall 	    UnGet(lex);
81431055Sminshall 	    if (lex.type != LEX_END_OF_FILE) {
81531055Sminshall 		    if (!GetEntry0()) {	/* start of an entry */
81631055Sminshall 			fprintf(stderr,
81731055Sminshall 			    "error was in entry for %s in file %s\n",
81831055Sminshall 			    (oldName)? oldName->array:"(unknown)", filename);
81931055Sminshall 		    Return(0);
82031055Sminshall 		}
82131055Sminshall 	    }
82231055Sminshall 	}
82331055Sminshall 	lex = Get();
82431055Sminshall     }
825*31100Sminshall #if !defined(MSDOS)
82631055Sminshall     fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer,
82731055Sminshall 		    filename);
828*31100Sminshall #endif	/* !defined(MSDOS) */
82931055Sminshall     Return(0);
83031055Sminshall }
83131055Sminshall 
83231055Sminshall char *
83331055Sminshall strsave(string)
83431055Sminshall char *string;
83531055Sminshall {
83631055Sminshall     char *p;
83731055Sminshall     extern char *malloc();
83831055Sminshall 
83931055Sminshall     p = malloc(strlen(string)+1);
84031055Sminshall     if (p != 0) {
84131055Sminshall 	strcpy(p, string);
84231055Sminshall     }
84331055Sminshall     return(p);
84431055Sminshall }
84531055Sminshall 
84631055Sminshall 
84731055Sminshall /*
84831055Sminshall  * InitControl - our interface to the outside.  What we should
84931055Sminshall  *  do is figure out keyboard (or terminal) type, set up file pointer
85031055Sminshall  *  (or string pointer), etc.
85131055Sminshall  */
85231055Sminshall 
85331055Sminshall state *
85431055Sminshall InitControl(keybdPointer, pickyarg)
85531055Sminshall char	*keybdPointer;
85631055Sminshall int	pickyarg;		/* Should we be picky? */
85731055Sminshall {
85831055Sminshall     extern char *getenv();
85931055Sminshall     int GotIt;
86031055Sminshall 
86131055Sminshall     picky = pickyarg;
86231055Sminshall 
86331055Sminshall     if (keybdPointer == 0) {
86431055Sminshall         keybdPointer = getenv("KEYBD");
86531055Sminshall     }
86631055Sminshall     if (keybdPointer == 0) {
86731055Sminshall        keybdPointer = getenv("TERM");
86831055Sminshall     }
86931055Sminshall 
87031055Sminshall 		    /*
87131055Sminshall 		     * Some environments have getenv() return
87231055Sminshall 		     * out of a static area.  So, save the keyboard name.
87331055Sminshall 		     */
87431055Sminshall     if (keybdPointer) {
87531055Sminshall         keybdPointer = strsave(keybdPointer);
87631055Sminshall     }
87731055Sminshall     environPointer = getenv("MAP3270");
87831055Sminshall     if (environPointer
87931055Sminshall 	    && (environPointer[0] != '/')
880*31100Sminshall #if	defined(MSDOS)
88131055Sminshall 	    && (environPointer[0] != '\\')
882*31100Sminshall #endif	/* defined(MSDOS) */
88331055Sminshall 	    && (strncmp(keybdPointer, environPointer,
88431055Sminshall 			strlen(keybdPointer) != 0)
88531055Sminshall 		|| (environPointer[strlen(keybdPointer)] != '{'))) /* } */
88631055Sminshall     {
88731055Sminshall 	environPointer = 0;
88831055Sminshall     }
88931055Sminshall 
89031055Sminshall     if ((!environPointer)
891*31100Sminshall #if	defined(MSDOS)
89231055Sminshall 		|| (*environPointer == '\\')
893*31100Sminshall #endif	/* defined(MSDOS) */
89431055Sminshall 		|| (*environPointer == '/')) {
89531055Sminshall 	usePointer = 0;
89631055Sminshall 	GotIt = 0;
89731055Sminshall 	if (!keybdPointer) {
898*31100Sminshall #if !defined(MSDOS)
89931055Sminshall 	    fprintf(stderr, "%s%s%s%s",
90031055Sminshall 		"Neither the KEYBD environment variable nor the TERM ",
90131055Sminshall 		"environment variable\n(one of which is needed to determine ",
90231055Sminshall 		"the type of keyboard you are using)\n",
90331055Sminshall 		"is set.  To set it, say 'setenv KEYBD <type>'\n");
904*31100Sminshall #endif	/* !defined(MSDOS) */
90531055Sminshall 	} else {
90631055Sminshall 	    if (environPointer) {
90731055Sminshall 		GotIt = Position(environPointer, keybdPointer);
90831055Sminshall 	    }
90931055Sminshall 	    if (!GotIt) {
91031055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
91131055Sminshall 	    }
91231055Sminshall 	}
91331055Sminshall 	if (!GotIt) {
91431055Sminshall 	    if (environPointer) {
91531055Sminshall 		GotIt = Position(environPointer, "unknown");
91631055Sminshall 	    }
91731055Sminshall 	    if (!GotIt) {
91831055Sminshall 		GotIt = Position("/etc/map3270", keybdPointer);
91931055Sminshall 	    }
92031055Sminshall 	}
92131055Sminshall 	if (!GotIt) {
922*31100Sminshall #if !defined(MSDOS)
92331055Sminshall 	    fprintf(stderr, "Using default key mappings.\n");
924*31100Sminshall #endif	/* !defined(MSDOS) */
92531055Sminshall 	    environPointer = keys3a;	/* use incore table */
92631055Sminshall 	    usePointer = 1;		/* flag use of non-file */
92731055Sminshall 	}
92831055Sminshall     } else {
92931055Sminshall 	usePointer = 1;
93031055Sminshall     }
93131055Sminshall     (void) GetEntry();
93231055Sminshall     return(firstentry.address);
93331055Sminshall }
934