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