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