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