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