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