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