1*31055Sminshall /* 2*31055Sminshall * Copyright (c) 1984, 1985, 1986 by the Regents of the 3*31055Sminshall * University of California and by Gregory Glenn Minshall. 4*31055Sminshall * 5*31055Sminshall * Permission to use, copy, modify, and distribute these 6*31055Sminshall * programs and their documentation for any purpose and 7*31055Sminshall * without fee is hereby granted, provided that this 8*31055Sminshall * copyright and permission appear on all copies and 9*31055Sminshall * supporting documentation, the name of the Regents of 10*31055Sminshall * the University of California not be used in advertising 11*31055Sminshall * or publicity pertaining to distribution of the programs 12*31055Sminshall * without specific prior permission, and notice be given in 13*31055Sminshall * supporting documentation that copying and distribution is 14*31055Sminshall * by permission of the Regents of the University of California 15*31055Sminshall * and by Gregory Glenn Minshall. Neither the Regents of the 16*31055Sminshall * University of California nor Gregory Glenn Minshall make 17*31055Sminshall * representations about the suitability of this software 18*31055Sminshall * for any purpose. It is provided "as is" without 19*31055Sminshall * express or implied warranty. 20*31055Sminshall */ 21*31055Sminshall 22*31055Sminshall #ifndef lint 23*31055Sminshall static char sccsid[] = "@(#)map3270.c 3.1 10/29/86"; 24*31055Sminshall #endif /* ndef lint */ 25*31055Sminshall 26*31055Sminshall 27*31055Sminshall /* This program reads a description file, somewhat like /etc/termcap, 28*31055Sminshall that describes the mapping between the current terminal's keyboard and 29*31055Sminshall a 3270 keyboard. 30*31055Sminshall */ 31*31055Sminshall #ifdef DOCUMENTATION_ONLY 32*31055Sminshall /* here is a sample (very small) entry... 33*31055Sminshall 34*31055Sminshall # this table is sensitive to position on a line. In particular, 35*31055Sminshall # a terminal definition for a terminal is terminated whenever a 36*31055Sminshall # (non-comment) line beginning in column one is found. 37*31055Sminshall # 38*31055Sminshall # this is an entry to map tvi924 to 3270 keys... 39*31055Sminshall v8|tvi924|924|televideo model 924 { 40*31055Sminshall pfk1 = '\E1'; 41*31055Sminshall pfk2 = '\E2'; 42*31055Sminshall clear = '^z'; # clear the screen 43*31055Sminshall } 44*31055Sminshall */ 45*31055Sminshall #endif /* DOCUMENTATION_ONLY */ 46*31055Sminshall 47*31055Sminshall #include <stdio.h> 48*31055Sminshall #include <ctype.h> 49*31055Sminshall #include <curses.h> 50*31055Sminshall #include <strings.h> 51*31055Sminshall 52*31055Sminshall #define IsPrint(c) ((isprint(c) && !isspace(c)) || ((c) == ' ')) 53*31055Sminshall 54*31055Sminshall #define LETS_SEE_ASCII 55*31055Sminshall #include "m4.out" 56*31055Sminshall 57*31055Sminshall #include "state.h" 58*31055Sminshall 59*31055Sminshall #include "../system/globals.h" 60*31055Sminshall #include "map3270.ext" 61*31055Sminshall 62*31055Sminshall /* this is the list of types returned by the lex processor */ 63*31055Sminshall #define LEX_CHAR TC_HIGHEST /* plain unadorned character */ 64*31055Sminshall #define LEX_ESCAPED LEX_CHAR+1 /* escaped with \ */ 65*31055Sminshall #define LEX_CARETED LEX_ESCAPED+1 /* escaped with ^ */ 66*31055Sminshall #define LEX_END_OF_FILE LEX_CARETED+1 /* end of file encountered */ 67*31055Sminshall #define LEX_ILLEGAL LEX_END_OF_FILE+1 /* trailing escape character */ 68*31055Sminshall 69*31055Sminshall /* the following is part of our character set dependancy... */ 70*31055Sminshall #define ESCAPE 0x1b 71*31055Sminshall #define TAB 0x09 72*31055Sminshall #define NEWLINE 0x0a 73*31055Sminshall #define CARRIAGE_RETURN 0x0d 74*31055Sminshall 75*31055Sminshall typedef struct { 76*31055Sminshall int type; /* LEX_* - type of character */ 77*31055Sminshall int value; /* character this was */ 78*31055Sminshall } lexicon; 79*31055Sminshall 80*31055Sminshall typedef struct { 81*31055Sminshall int length; /* length of character string */ 82*31055Sminshall char array[500]; /* character string */ 83*31055Sminshall } stringWithLength; 84*31055Sminshall 85*31055Sminshall #define panic(s) { fprintf(stderr, s); exit(1); } 86*31055Sminshall 87*31055Sminshall static state firstentry = { 0, TC_NULL, 0, 0 }; 88*31055Sminshall static state *headOfQueue = &firstentry; 89*31055Sminshall 90*31055Sminshall /* the following is a primitive adm3a table, to be used when nothing 91*31055Sminshall * else seems to be avaliable. 92*31055Sminshall */ 93*31055Sminshall 94*31055Sminshall #ifdef DEBUG 95*31055Sminshall static int debug = 0; /* debug flag (for debuggin tables) */ 96*31055Sminshall #endif /* DEBUG */ 97*31055Sminshall 98*31055Sminshall static int doPaste = 1; /* should we have side effects */ 99*31055Sminshall static int picky = 0; /* do we complain of unknown TC's? */ 100*31055Sminshall static char usePointer = 0; /* use pointer, or file */ 101*31055Sminshall static FILE *ourFile= 0; 102*31055Sminshall static char *environPointer = 0; /* if non-zero, point to input 103*31055Sminshall * string in core. 104*31055Sminshall */ 105*31055Sminshall static char keys3a[] = 106*31055Sminshall #include "default.map" /* Define the default default */ 107*31055Sminshall ; 108*31055Sminshall 109*31055Sminshall static int Empty = 1, /* is the unget lifo empty? */ 110*31055Sminshall Full = 0; /* is the unget lifo full? */ 111*31055Sminshall static lexicon lifo[200] = 0; /* character stack for parser */ 112*31055Sminshall static int rp = 0, /* read pointer into lifo */ 113*31055Sminshall wp = 0; /* write pointer into lifo */ 114*31055Sminshall 115*31055Sminshall static int 116*31055Sminshall GetC() 117*31055Sminshall { 118*31055Sminshall int character; 119*31055Sminshall 120*31055Sminshall if (usePointer) { 121*31055Sminshall if (*environPointer) { 122*31055Sminshall character = 0xff&*environPointer++; 123*31055Sminshall } else { 124*31055Sminshall static char suffix = 'A'; 125*31055Sminshall char envname[9]; 126*31055Sminshall extern char *getenv(); 127*31055Sminshall 128*31055Sminshall (void) sprintf(envname, "MAP3270%c", suffix++); 129*31055Sminshall environPointer = getenv(envname); 130*31055Sminshall if (*environPointer) { 131*31055Sminshall character = 0xff&*environPointer++; 132*31055Sminshall } else { 133*31055Sminshall character = EOF; 134*31055Sminshall } 135*31055Sminshall } 136*31055Sminshall } else { 137*31055Sminshall character = getc(ourFile); 138*31055Sminshall } 139*31055Sminshall return(character); 140*31055Sminshall } 141*31055Sminshall 142*31055Sminshall static lexicon 143*31055Sminshall Get() 144*31055Sminshall { 145*31055Sminshall lexicon c; 146*31055Sminshall register lexicon *pC = &c; 147*31055Sminshall register int character; 148*31055Sminshall 149*31055Sminshall if (!Empty) { 150*31055Sminshall *pC = lifo[rp]; 151*31055Sminshall rp++; 152*31055Sminshall if (rp == sizeof lifo/sizeof (lexicon)) { 153*31055Sminshall rp = 0; 154*31055Sminshall } 155*31055Sminshall if (rp == wp) { 156*31055Sminshall Empty = 1; 157*31055Sminshall } 158*31055Sminshall Full = 0; 159*31055Sminshall } else { 160*31055Sminshall character = GetC(); 161*31055Sminshall switch (character) { 162*31055Sminshall case EOF: 163*31055Sminshall pC->type = LEX_END_OF_FILE; 164*31055Sminshall break; 165*31055Sminshall case '^': 166*31055Sminshall character = GetC(); 167*31055Sminshall if (!IsPrint(character)) { 168*31055Sminshall pC->type = LEX_ILLEGAL; 169*31055Sminshall } else { 170*31055Sminshall pC->type = LEX_CARETED; 171*31055Sminshall if (character == '?') { 172*31055Sminshall character |= 0x40; /* rubout */ 173*31055Sminshall } else { 174*31055Sminshall character &= 0x1f; 175*31055Sminshall } 176*31055Sminshall } 177*31055Sminshall break; 178*31055Sminshall case '\\': 179*31055Sminshall character = GetC(); 180*31055Sminshall if (!IsPrint(character)) { 181*31055Sminshall pC->type = LEX_ILLEGAL; 182*31055Sminshall } else { 183*31055Sminshall pC->type = LEX_ESCAPED; 184*31055Sminshall switch (character) { 185*31055Sminshall case 'E': case 'e': 186*31055Sminshall character = ESCAPE; 187*31055Sminshall break; 188*31055Sminshall case 't': 189*31055Sminshall character = TAB; 190*31055Sminshall break; 191*31055Sminshall case 'n': 192*31055Sminshall character = NEWLINE; 193*31055Sminshall break; 194*31055Sminshall case 'r': 195*31055Sminshall character = CARRIAGE_RETURN; 196*31055Sminshall break; 197*31055Sminshall default: 198*31055Sminshall pC->type = LEX_ILLEGAL; 199*31055Sminshall break; 200*31055Sminshall } 201*31055Sminshall } 202*31055Sminshall break; 203*31055Sminshall default: 204*31055Sminshall if ((IsPrint(character)) || isspace(character)) { 205*31055Sminshall pC->type = LEX_CHAR; 206*31055Sminshall } else { 207*31055Sminshall pC->type = LEX_ILLEGAL; 208*31055Sminshall } 209*31055Sminshall break; 210*31055Sminshall } 211*31055Sminshall pC->value = character; 212*31055Sminshall } 213*31055Sminshall return(*pC); 214*31055Sminshall } 215*31055Sminshall 216*31055Sminshall static void 217*31055Sminshall UnGet(c) 218*31055Sminshall lexicon c; /* character to unget */ 219*31055Sminshall { 220*31055Sminshall if (Full) { 221*31055Sminshall fprintf(stderr, "attempt to put too many characters in lifo\n"); 222*31055Sminshall panic("map3270"); 223*31055Sminshall /* NOTREACHED */ 224*31055Sminshall } else { 225*31055Sminshall lifo[wp] = c; 226*31055Sminshall wp++; 227*31055Sminshall if (wp == sizeof lifo/sizeof (lexicon)) { 228*31055Sminshall wp = 0; 229*31055Sminshall } 230*31055Sminshall if (wp == rp) { 231*31055Sminshall Full = 1; 232*31055Sminshall } 233*31055Sminshall Empty = 0; 234*31055Sminshall } 235*31055Sminshall } 236*31055Sminshall 237*31055Sminshall /* compare two strings, ignoring case */ 238*31055Sminshall 239*31055Sminshall ustrcmp(string1, string2) 240*31055Sminshall register char *string1; 241*31055Sminshall register char *string2; 242*31055Sminshall { 243*31055Sminshall register int c1, c2; 244*31055Sminshall 245*31055Sminshall while ((c1 = (unsigned char) *string1++) != 0) { 246*31055Sminshall if (isupper(c1)) { 247*31055Sminshall c1 = tolower(c1); 248*31055Sminshall } 249*31055Sminshall if (isupper(c2 = (unsigned char) *string2++)) { 250*31055Sminshall c2 = tolower(c2); 251*31055Sminshall } 252*31055Sminshall if (c1 < c2) { 253*31055Sminshall return(-1); 254*31055Sminshall } else if (c1 > c2) { 255*31055Sminshall return(1); 256*31055Sminshall } 257*31055Sminshall } 258*31055Sminshall if (*string2) { 259*31055Sminshall return(-1); 260*31055Sminshall } else { 261*31055Sminshall return(0); 262*31055Sminshall } 263*31055Sminshall } 264*31055Sminshall 265*31055Sminshall 266*31055Sminshall static stringWithLength * 267*31055Sminshall GetQuotedString() 268*31055Sminshall { 269*31055Sminshall lexicon lex; 270*31055Sminshall static stringWithLength output = { 0 }; /* where return value is held */ 271*31055Sminshall char *pointer = output.array; 272*31055Sminshall 273*31055Sminshall lex = Get(); 274*31055Sminshall if ((lex.type != LEX_CHAR) || (lex.value != '\'')) { 275*31055Sminshall UnGet(lex); 276*31055Sminshall return(0); 277*31055Sminshall } 278*31055Sminshall while (1) { 279*31055Sminshall lex = Get(); 280*31055Sminshall if ((lex.type == LEX_CHAR) && (lex.value == '\'')) { 281*31055Sminshall break; 282*31055Sminshall } 283*31055Sminshall if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) { 284*31055Sminshall UnGet(lex); 285*31055Sminshall return(0); /* illegal character in quoted string */ 286*31055Sminshall } 287*31055Sminshall if (pointer >= output.array+sizeof output.array) { 288*31055Sminshall return(0); /* too long */ 289*31055Sminshall } 290*31055Sminshall *pointer++ = lex.value; 291*31055Sminshall } 292*31055Sminshall output.length = pointer-output.array; 293*31055Sminshall return(&output); 294*31055Sminshall } 295*31055Sminshall 296*31055Sminshall #ifdef NOTUSED 297*31055Sminshall static stringWithLength * 298*31055Sminshall GetCharString() 299*31055Sminshall { 300*31055Sminshall lexicon lex; 301*31055Sminshall static stringWithLength output; 302*31055Sminshall char *pointer = output.array; 303*31055Sminshall 304*31055Sminshall lex = Get(); 305*31055Sminshall 306*31055Sminshall while ((lex.type == LEX_CHAR) && 307*31055Sminshall !isspace(lex.value) && (lex.value != '=')) { 308*31055Sminshall *pointer++ = lex.value; 309*31055Sminshall lex = Get(); 310*31055Sminshall if (pointer >= output.array + sizeof output.array) { 311*31055Sminshall return(0); /* too long */ 312*31055Sminshall } 313*31055Sminshall } 314*31055Sminshall UnGet(lex); 315*31055Sminshall output.length = pointer-output.array; 316*31055Sminshall return(&output); 317*31055Sminshall } 318*31055Sminshall #endif /* NOTUSED */ 319*31055Sminshall 320*31055Sminshall static 321*31055Sminshall GetCharacter(character) 322*31055Sminshall int character; /* desired character */ 323*31055Sminshall { 324*31055Sminshall lexicon lex; 325*31055Sminshall 326*31055Sminshall lex = Get(); 327*31055Sminshall 328*31055Sminshall if ((lex.type != LEX_CHAR) || (lex.value != character)) { 329*31055Sminshall UnGet(lex); 330*31055Sminshall return(0); 331*31055Sminshall } 332*31055Sminshall return(1); 333*31055Sminshall } 334*31055Sminshall 335*31055Sminshall #ifdef NOTUSED 336*31055Sminshall static 337*31055Sminshall GetString(string) 338*31055Sminshall char *string; /* string to get */ 339*31055Sminshall { 340*31055Sminshall lexicon lex; 341*31055Sminshall 342*31055Sminshall while (*string) { 343*31055Sminshall lex = Get(); 344*31055Sminshall if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) { 345*31055Sminshall UnGet(lex); 346*31055Sminshall return(0); /* XXX restore to state on entry */ 347*31055Sminshall } 348*31055Sminshall string++; 349*31055Sminshall } 350*31055Sminshall return(1); 351*31055Sminshall } 352*31055Sminshall #endif /* NOTUSED */ 353*31055Sminshall 354*31055Sminshall 355*31055Sminshall static stringWithLength * 356*31055Sminshall GetAlphaMericString() 357*31055Sminshall { 358*31055Sminshall lexicon lex; 359*31055Sminshall static stringWithLength output = { 0 }; 360*31055Sminshall char *pointer = output.array; 361*31055Sminshall # define IsAlnum(c) (isalnum(c) || (c == '_') \ 362*31055Sminshall || (c == '-') || (c == '.')) 363*31055Sminshall 364*31055Sminshall lex = Get(); 365*31055Sminshall 366*31055Sminshall if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) { 367*31055Sminshall UnGet(lex); 368*31055Sminshall return(0); 369*31055Sminshall } 370*31055Sminshall 371*31055Sminshall while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) { 372*31055Sminshall *pointer++ = lex.value; 373*31055Sminshall lex = Get(); 374*31055Sminshall } 375*31055Sminshall UnGet(lex); 376*31055Sminshall *pointer = 0; 377*31055Sminshall output.length = pointer-output.array; 378*31055Sminshall return(&output); 379*31055Sminshall } 380*31055Sminshall 381*31055Sminshall 382*31055Sminshall /* eat up characters until a new line, or end of file. returns terminating 383*31055Sminshall character. 384*31055Sminshall */ 385*31055Sminshall 386*31055Sminshall static lexicon 387*31055Sminshall EatToNL() 388*31055Sminshall { 389*31055Sminshall lexicon lex; 390*31055Sminshall 391*31055Sminshall lex = Get(); 392*31055Sminshall 393*31055Sminshall while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) && 394*31055Sminshall (lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) { 395*31055Sminshall lex = Get(); 396*31055Sminshall } 397*31055Sminshall if (lex.type != LEX_END_OF_FILE) { 398*31055Sminshall return(Get()); 399*31055Sminshall } else { 400*31055Sminshall return(lex); 401*31055Sminshall } 402*31055Sminshall } 403*31055Sminshall 404*31055Sminshall 405*31055Sminshall static void 406*31055Sminshall GetWS() 407*31055Sminshall { 408*31055Sminshall lexicon lex; 409*31055Sminshall 410*31055Sminshall lex = Get(); 411*31055Sminshall 412*31055Sminshall while ((lex.type == LEX_CHAR) && 413*31055Sminshall (isspace(lex.value) || (lex.value == '#'))) { 414*31055Sminshall if (lex.value == '#') { 415*31055Sminshall lex = EatToNL(); 416*31055Sminshall } else { 417*31055Sminshall lex = Get(); 418*31055Sminshall } 419*31055Sminshall } 420*31055Sminshall UnGet(lex); 421*31055Sminshall } 422*31055Sminshall 423*31055Sminshall static void 424*31055Sminshall FreeState(pState) 425*31055Sminshall state *pState; 426*31055Sminshall { 427*31055Sminshall extern void free(); 428*31055Sminshall 429*31055Sminshall free((char *)pState); 430*31055Sminshall } 431*31055Sminshall 432*31055Sminshall 433*31055Sminshall static state * 434*31055Sminshall GetState() 435*31055Sminshall { 436*31055Sminshall state *pState; 437*31055Sminshall extern char *malloc(); 438*31055Sminshall 439*31055Sminshall pState = (state *) malloc(sizeof (state)); 440*31055Sminshall 441*31055Sminshall pState->result = TC_NULL; 442*31055Sminshall pState->next = 0; 443*31055Sminshall 444*31055Sminshall return(pState); 445*31055Sminshall } 446*31055Sminshall 447*31055Sminshall 448*31055Sminshall static state * 449*31055Sminshall FindMatchAtThisLevel(pState, character) 450*31055Sminshall state *pState; 451*31055Sminshall int character; 452*31055Sminshall { 453*31055Sminshall while (pState) { 454*31055Sminshall if (pState->match == character) { 455*31055Sminshall return(pState); 456*31055Sminshall } 457*31055Sminshall pState = pState->next; 458*31055Sminshall } 459*31055Sminshall return(0); 460*31055Sminshall } 461*31055Sminshall 462*31055Sminshall 463*31055Sminshall static state * 464*31055Sminshall PasteEntry(head, string, count, identifier) 465*31055Sminshall state *head; /* points to who should point here... */ 466*31055Sminshall char *string; /* which characters to paste */ 467*31055Sminshall int count; /* number of character to do */ 468*31055Sminshall char *identifier; /* for error messages */ 469*31055Sminshall { 470*31055Sminshall state *pState, *other; 471*31055Sminshall 472*31055Sminshall if (!doPaste) { /* flag to not have any side effects */ 473*31055Sminshall return((state *)1); 474*31055Sminshall } 475*31055Sminshall if (!count) { 476*31055Sminshall return(head); /* return pointer to the parent */ 477*31055Sminshall } 478*31055Sminshall if ((head->result != TC_NULL) && (head->result != TC_GOTO)) { 479*31055Sminshall /* this means that a previously defined sequence is an initial 480*31055Sminshall * part of this one. 481*31055Sminshall */ 482*31055Sminshall fprintf(stderr, "Conflicting entries found when scanning %s\n", 483*31055Sminshall identifier); 484*31055Sminshall return(0); 485*31055Sminshall } 486*31055Sminshall # ifdef DEBUG 487*31055Sminshall if (debug) { 488*31055Sminshall fprintf(stderr, "%s", unctrl(*string)); 489*31055Sminshall } 490*31055Sminshall # endif /* DEBUG */ 491*31055Sminshall pState = GetState(); 492*31055Sminshall pState->match = *string; 493*31055Sminshall if (head->result == TC_NULL) { 494*31055Sminshall head->result = TC_GOTO; 495*31055Sminshall head->address = pState; 496*31055Sminshall other = pState; 497*31055Sminshall } else { /* search for same character */ 498*31055Sminshall if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) { 499*31055Sminshall FreeState(pState); 500*31055Sminshall } else { 501*31055Sminshall pState->next = head->address; 502*31055Sminshall head->address = pState; 503*31055Sminshall other = pState; 504*31055Sminshall } 505*31055Sminshall } 506*31055Sminshall return(PasteEntry(other, string+1, count-1, identifier)); 507*31055Sminshall } 508*31055Sminshall 509*31055Sminshall static 510*31055Sminshall GetInput(tc, identifier) 511*31055Sminshall int tc; 512*31055Sminshall char *identifier; /* entry being parsed (for error messages) */ 513*31055Sminshall { 514*31055Sminshall stringWithLength *outputString; 515*31055Sminshall state *head; 516*31055Sminshall state fakeQueue; 517*31055Sminshall 518*31055Sminshall if (doPaste) { 519*31055Sminshall head = headOfQueue; /* always points to level above this one */ 520*31055Sminshall } else { 521*31055Sminshall head = &fakeQueue; /* don't have any side effects... */ 522*31055Sminshall } 523*31055Sminshall 524*31055Sminshall if ((outputString = GetQuotedString()) == 0) { 525*31055Sminshall return(0); 526*31055Sminshall } else if (IsPrint(outputString->array[0])) { 527*31055Sminshall fprintf(stderr, 528*31055Sminshall "first character of sequence for %s is not a control type character\n", 529*31055Sminshall identifier); 530*31055Sminshall return(0); 531*31055Sminshall } else { 532*31055Sminshall if ((head = PasteEntry(head, outputString->array, 533*31055Sminshall outputString->length, identifier)) == 0) { 534*31055Sminshall return(0); 535*31055Sminshall } 536*31055Sminshall GetWS(); 537*31055Sminshall while ((outputString = GetQuotedString()) != 0) { 538*31055Sminshall if ((head = PasteEntry(head, outputString->array, 539*31055Sminshall outputString->length, identifier)) == 0) { 540*31055Sminshall return(0); 541*31055Sminshall } 542*31055Sminshall GetWS(); 543*31055Sminshall } 544*31055Sminshall } 545*31055Sminshall if (!doPaste) { 546*31055Sminshall return(1); 547*31055Sminshall } 548*31055Sminshall if ((head->result != TC_NULL) && (head->result != tc)) { 549*31055Sminshall /* this means that this sequence is an initial part 550*31055Sminshall * of a previously defined one. 551*31055Sminshall */ 552*31055Sminshall fprintf(stderr, "Conflicting entries found when scanning %s\n", 553*31055Sminshall identifier); 554*31055Sminshall return(0); 555*31055Sminshall } else { 556*31055Sminshall head->result = tc; 557*31055Sminshall return(1); /* done */ 558*31055Sminshall } 559*31055Sminshall } 560*31055Sminshall 561*31055Sminshall static 562*31055Sminshall GetTc(string) 563*31055Sminshall char *string; 564*31055Sminshall { 565*31055Sminshall register TC_Ascii_t *Tc; 566*31055Sminshall 567*31055Sminshall for (Tc = TC_Ascii; 568*31055Sminshall Tc < TC_Ascii+sizeof TC_Ascii/sizeof (TC_Ascii_t); Tc++) { 569*31055Sminshall if (!ustrcmp(string, Tc->tc_name)) { 570*31055Sminshall # ifdef DEBUG 571*31055Sminshall if (debug) { 572*31055Sminshall fprintf(stderr, "%s = ", Tc->tc_name); 573*31055Sminshall } 574*31055Sminshall # endif /* DEBUG */ 575*31055Sminshall return(Tc->tc_value&0xff); 576*31055Sminshall } 577*31055Sminshall } 578*31055Sminshall return(0); 579*31055Sminshall } 580*31055Sminshall static 581*31055Sminshall GetDefinition() 582*31055Sminshall { 583*31055Sminshall stringWithLength *string; 584*31055Sminshall int Tc; 585*31055Sminshall 586*31055Sminshall GetWS(); 587*31055Sminshall if ((string = GetAlphaMericString()) == 0) { 588*31055Sminshall return(0); 589*31055Sminshall } 590*31055Sminshall string->array[string->length] = 0; 591*31055Sminshall if (doPaste) { 592*31055Sminshall if ((Tc = GetTc(string->array)) == 0) { 593*31055Sminshall if (picky) { 594*31055Sminshall fprintf(stderr, "%s: unknown 3270 key identifier\n", 595*31055Sminshall string->array); 596*31055Sminshall } 597*31055Sminshall Tc = TC_NULL; 598*31055Sminshall } else if (Tc < TC_LOWEST_USER) { 599*31055Sminshall fprintf(stderr, "%s is not allowed to be specified by a user.\n", 600*31055Sminshall string->array); 601*31055Sminshall return(0); 602*31055Sminshall } 603*31055Sminshall } else { 604*31055Sminshall Tc = TC_LOWEST_USER; 605*31055Sminshall } 606*31055Sminshall GetWS(); 607*31055Sminshall if (!GetCharacter('=')) { 608*31055Sminshall fprintf(stderr, 609*31055Sminshall "Required equal sign after 3270 key identifier %s missing\n", 610*31055Sminshall string->array); 611*31055Sminshall return(0); 612*31055Sminshall } 613*31055Sminshall GetWS(); 614*31055Sminshall if (!GetInput(Tc, string->array)) { 615*31055Sminshall fprintf(stderr, "Missing definition part for 3270 key %s\n", 616*31055Sminshall string->array); 617*31055Sminshall return(0); 618*31055Sminshall } else { 619*31055Sminshall GetWS(); 620*31055Sminshall while (GetCharacter('|')) { 621*31055Sminshall # ifdef DEBUG 622*31055Sminshall if (debug) { 623*31055Sminshall fprintf(stderr, " or "); 624*31055Sminshall } 625*31055Sminshall # endif /* DEBUG */ 626*31055Sminshall GetWS(); 627*31055Sminshall if (!GetInput(Tc, string->array)) { 628*31055Sminshall fprintf(stderr, "Missing definition part for 3270 key %s\n", 629*31055Sminshall string->array); 630*31055Sminshall return(0); 631*31055Sminshall } 632*31055Sminshall GetWS(); 633*31055Sminshall } 634*31055Sminshall } 635*31055Sminshall GetWS(); 636*31055Sminshall if (!GetCharacter(';')) { 637*31055Sminshall fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array); 638*31055Sminshall return(0); 639*31055Sminshall } 640*31055Sminshall # ifdef DEBUG 641*31055Sminshall if (debug) { 642*31055Sminshall fprintf(stderr, ";\n"); 643*31055Sminshall } 644*31055Sminshall # endif /* DEBUG */ 645*31055Sminshall return(1); 646*31055Sminshall } 647*31055Sminshall 648*31055Sminshall 649*31055Sminshall static 650*31055Sminshall GetDefinitions() 651*31055Sminshall { 652*31055Sminshall if (!GetDefinition()) { 653*31055Sminshall return(0); 654*31055Sminshall } else { 655*31055Sminshall while (GetDefinition()) { 656*31055Sminshall ; 657*31055Sminshall } 658*31055Sminshall } 659*31055Sminshall return(1); 660*31055Sminshall } 661*31055Sminshall 662*31055Sminshall static 663*31055Sminshall GetBegin() 664*31055Sminshall { 665*31055Sminshall GetWS(); 666*31055Sminshall if (!GetCharacter('{')) { 667*31055Sminshall return(0); 668*31055Sminshall } 669*31055Sminshall return(1); 670*31055Sminshall } 671*31055Sminshall 672*31055Sminshall static 673*31055Sminshall GetEnd() 674*31055Sminshall { 675*31055Sminshall GetWS(); 676*31055Sminshall if (!GetCharacter('}')) { 677*31055Sminshall return(0); 678*31055Sminshall } 679*31055Sminshall return(1); 680*31055Sminshall } 681*31055Sminshall 682*31055Sminshall static 683*31055Sminshall GetName() 684*31055Sminshall { 685*31055Sminshall if (!GetAlphaMericString()) { 686*31055Sminshall return(0); 687*31055Sminshall } 688*31055Sminshall GetWS(); 689*31055Sminshall while (GetAlphaMericString()) { 690*31055Sminshall GetWS(); 691*31055Sminshall } 692*31055Sminshall return(1); 693*31055Sminshall } 694*31055Sminshall 695*31055Sminshall static 696*31055Sminshall GetNames() 697*31055Sminshall { 698*31055Sminshall GetWS(); 699*31055Sminshall if (!GetName()) { 700*31055Sminshall return(0); 701*31055Sminshall } else { 702*31055Sminshall GetWS(); 703*31055Sminshall while (GetCharacter('|')) { 704*31055Sminshall GetWS(); 705*31055Sminshall if (!GetName()) { 706*31055Sminshall return(0); 707*31055Sminshall } 708*31055Sminshall } 709*31055Sminshall } 710*31055Sminshall return(1); 711*31055Sminshall } 712*31055Sminshall 713*31055Sminshall static 714*31055Sminshall GetEntry0() 715*31055Sminshall { 716*31055Sminshall if (!GetBegin()) { 717*31055Sminshall fprintf(stderr, "no '{'\n"); 718*31055Sminshall return(0); 719*31055Sminshall } else if (!GetDefinitions()) { 720*31055Sminshall fprintf(stderr, "unable to parse the definitions\n"); 721*31055Sminshall return(0); 722*31055Sminshall } else if (!GetEnd()) { 723*31055Sminshall fprintf(stderr, "No '}' or scanning stopped early due to error.\n"); 724*31055Sminshall return(0); 725*31055Sminshall } else { 726*31055Sminshall /* done */ 727*31055Sminshall return(1); 728*31055Sminshall } 729*31055Sminshall } 730*31055Sminshall 731*31055Sminshall 732*31055Sminshall static 733*31055Sminshall GetEntry() 734*31055Sminshall { 735*31055Sminshall if (!GetNames()) { 736*31055Sminshall fprintf(stderr, "Invalid name field in entry.\n"); 737*31055Sminshall return(0); 738*31055Sminshall } else { 739*31055Sminshall return(GetEntry0()); 740*31055Sminshall } 741*31055Sminshall } 742*31055Sminshall 743*31055Sminshall /* position ourselves within a given filename to the entry for the current 744*31055Sminshall * KEYBD (or TERM) variable 745*31055Sminshall */ 746*31055Sminshall 747*31055Sminshall Position(filename, keybdPointer) 748*31055Sminshall char *filename; 749*31055Sminshall char *keybdPointer; 750*31055Sminshall { 751*31055Sminshall lexicon lex; 752*31055Sminshall stringWithLength *name = 0; 753*31055Sminshall stringWithLength *oldName; 754*31055Sminshall # define Return(x) {doPaste = 1; return(x);} 755*31055Sminshall 756*31055Sminshall doPaste = 0; 757*31055Sminshall 758*31055Sminshall if ((ourFile = fopen(filename, "r")) == NULL) { 759*31055Sminshall # if !defined(msdos) 760*31055Sminshall fprintf(stderr, "Unable to open file %s\n", filename); 761*31055Sminshall # endif /* !defined(msdos) */ 762*31055Sminshall Return(0); 763*31055Sminshall } 764*31055Sminshall lex = Get(); 765*31055Sminshall while (lex.type != LEX_END_OF_FILE) { 766*31055Sminshall UnGet(lex); 767*31055Sminshall /* now, find an entry that is our type. */ 768*31055Sminshall GetWS(); 769*31055Sminshall oldName = name; 770*31055Sminshall if ((name = GetAlphaMericString()) != 0) { 771*31055Sminshall if (!ustrcmp(name->array, keybdPointer)) { 772*31055Sminshall /* need to make sure there is a name here... */ 773*31055Sminshall lex.type = LEX_CHAR; 774*31055Sminshall lex.value = 'a'; 775*31055Sminshall UnGet(lex); 776*31055Sminshall Return(1); 777*31055Sminshall } 778*31055Sminshall } else if (GetCharacter('|')) { 779*31055Sminshall ; /* more names coming */ 780*31055Sminshall } else { 781*31055Sminshall lex = Get(); 782*31055Sminshall UnGet(lex); 783*31055Sminshall if (lex.type != LEX_END_OF_FILE) { 784*31055Sminshall if (!GetEntry0()) { /* start of an entry */ 785*31055Sminshall fprintf(stderr, 786*31055Sminshall "error was in entry for %s in file %s\n", 787*31055Sminshall (oldName)? oldName->array:"(unknown)", filename); 788*31055Sminshall Return(0); 789*31055Sminshall } 790*31055Sminshall } 791*31055Sminshall } 792*31055Sminshall lex = Get(); 793*31055Sminshall } 794*31055Sminshall #if !defined(msdos) 795*31055Sminshall fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer, 796*31055Sminshall filename); 797*31055Sminshall #endif /* !defined(msdos) */ 798*31055Sminshall Return(0); 799*31055Sminshall } 800*31055Sminshall 801*31055Sminshall char * 802*31055Sminshall strsave(string) 803*31055Sminshall char *string; 804*31055Sminshall { 805*31055Sminshall char *p; 806*31055Sminshall extern char *malloc(); 807*31055Sminshall 808*31055Sminshall p = malloc(strlen(string)+1); 809*31055Sminshall if (p != 0) { 810*31055Sminshall strcpy(p, string); 811*31055Sminshall } 812*31055Sminshall return(p); 813*31055Sminshall } 814*31055Sminshall 815*31055Sminshall 816*31055Sminshall /* 817*31055Sminshall * InitControl - our interface to the outside. What we should 818*31055Sminshall * do is figure out keyboard (or terminal) type, set up file pointer 819*31055Sminshall * (or string pointer), etc. 820*31055Sminshall */ 821*31055Sminshall 822*31055Sminshall state * 823*31055Sminshall InitControl(keybdPointer, pickyarg) 824*31055Sminshall char *keybdPointer; 825*31055Sminshall int pickyarg; /* Should we be picky? */ 826*31055Sminshall { 827*31055Sminshall extern char *getenv(); 828*31055Sminshall int GotIt; 829*31055Sminshall 830*31055Sminshall picky = pickyarg; 831*31055Sminshall 832*31055Sminshall if (keybdPointer == 0) { 833*31055Sminshall keybdPointer = getenv("KEYBD"); 834*31055Sminshall } 835*31055Sminshall if (keybdPointer == 0) { 836*31055Sminshall keybdPointer = getenv("TERM"); 837*31055Sminshall } 838*31055Sminshall 839*31055Sminshall /* 840*31055Sminshall * Some environments have getenv() return 841*31055Sminshall * out of a static area. So, save the keyboard name. 842*31055Sminshall */ 843*31055Sminshall if (keybdPointer) { 844*31055Sminshall keybdPointer = strsave(keybdPointer); 845*31055Sminshall } 846*31055Sminshall environPointer = getenv("MAP3270"); 847*31055Sminshall if (environPointer 848*31055Sminshall && (environPointer[0] != '/') 849*31055Sminshall #if defined(msdos) 850*31055Sminshall && (environPointer[0] != '\\') 851*31055Sminshall #endif defined(msdos) 852*31055Sminshall && (strncmp(keybdPointer, environPointer, 853*31055Sminshall strlen(keybdPointer) != 0) 854*31055Sminshall || (environPointer[strlen(keybdPointer)] != '{'))) /* } */ 855*31055Sminshall { 856*31055Sminshall environPointer = 0; 857*31055Sminshall } 858*31055Sminshall 859*31055Sminshall if ((!environPointer) 860*31055Sminshall #if defined(msdos) 861*31055Sminshall || (*environPointer == '\\') 862*31055Sminshall #endif /* defined(msdos) */ 863*31055Sminshall || (*environPointer == '/')) { 864*31055Sminshall usePointer = 0; 865*31055Sminshall GotIt = 0; 866*31055Sminshall if (!keybdPointer) { 867*31055Sminshall #if !defined(msdos) 868*31055Sminshall fprintf(stderr, "%s%s%s%s", 869*31055Sminshall "Neither the KEYBD environment variable nor the TERM ", 870*31055Sminshall "environment variable\n(one of which is needed to determine ", 871*31055Sminshall "the type of keyboard you are using)\n", 872*31055Sminshall "is set. To set it, say 'setenv KEYBD <type>'\n"); 873*31055Sminshall #endif /* !defined(msdos) */ 874*31055Sminshall } else { 875*31055Sminshall if (environPointer) { 876*31055Sminshall GotIt = Position(environPointer, keybdPointer); 877*31055Sminshall } 878*31055Sminshall if (!GotIt) { 879*31055Sminshall GotIt = Position("/etc/map3270", keybdPointer); 880*31055Sminshall } 881*31055Sminshall } 882*31055Sminshall if (!GotIt) { 883*31055Sminshall if (environPointer) { 884*31055Sminshall GotIt = Position(environPointer, "unknown"); 885*31055Sminshall } 886*31055Sminshall if (!GotIt) { 887*31055Sminshall GotIt = Position("/etc/map3270", keybdPointer); 888*31055Sminshall } 889*31055Sminshall } 890*31055Sminshall if (!GotIt) { 891*31055Sminshall #if !defined(msdos) 892*31055Sminshall fprintf(stderr, "Using default key mappings.\n"); 893*31055Sminshall #endif /* !defined(msdos) */ 894*31055Sminshall environPointer = keys3a; /* use incore table */ 895*31055Sminshall usePointer = 1; /* flag use of non-file */ 896*31055Sminshall } 897*31055Sminshall } else { 898*31055Sminshall usePointer = 1; 899*31055Sminshall } 900*31055Sminshall (void) GetEntry(); 901*31055Sminshall return(firstentry.address); 902*31055Sminshall } 903