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