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