386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 26 Apr 1991 22:38:29 +0000 (14:38 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 26 Apr 1991 22:38:29 +0000 (14:38 -0800)
Work on file usr/src/usr.bin/tn3270/ascii/map3270.h
Work on file usr/src/usr.bin/tn3270/ascii/state.h
Work on file usr/src/usr.bin/tn3270/ascii/mset.c
Work on file usr/src/usr.bin/tn3270/ascii/default.map
Work on file usr/src/usr.bin/tn3270/ascii/map3270.c
Work on file usr/src/usr.bin/tn3270/ascii/termin.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/usr.bin/tn3270/ascii/default.map [new file with mode: 0644]
usr/src/usr.bin/tn3270/ascii/map3270.c [new file with mode: 0644]
usr/src/usr.bin/tn3270/ascii/map3270.h [new file with mode: 0644]
usr/src/usr.bin/tn3270/ascii/mset.c [new file with mode: 0644]
usr/src/usr.bin/tn3270/ascii/state.h [new file with mode: 0644]
usr/src/usr.bin/tn3270/ascii/termin.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/tn3270/ascii/default.map b/usr/src/usr.bin/tn3270/ascii/default.map
new file mode 100644 (file)
index 0000000..7289671
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)default.map 4.2 (Berkeley) 4/26/91
+ */
+
+/* default.map3270:  This file is the system default for the key sequence
+ * if neither the user's TERM nor "unknown" are found in either of
+ * MAP3270 or /etc/map3270.
+ *
+ *
+ */
+#if    defined(MSDOS)
+"tn3270pc{",
+"  ENTER='^M';CLEAR='^Z'|'^Aw';NL='^N'|'^AO';TAB='^I';DP='^U';FM='^Y';",
+"  BTAB='^B'|'^[^I'|'^A^O';LEFT='^H'|'^AK';RIGHT='^L'|'^AM';UP='^K'|'^AH';",
+"  DOWN='^J'|'^AP';HOME='^^'|'^AG';DELETE='^AS'|'^D';EINP='^W';FLINP='^X';",
+"  EEOF='^E'|'^Au';WERASE='^As';FERASE='^At';INSRT='^[ '|'^AR';CURSEL='^[.';",
+"  PFK1='^A;'|'^F01'|'^[1'|'^Ax';PFK2='^A<'|'^F02'|'^[2'|'^Ay';SETTAB='^[;';",
+"  PFK3='^A='|'^F03'|'^[3'|'^Az';CLRTAB='^[+'|'^[:';SETMRG='^[(';",
+"  PFK4='^A>'|'^F04'|'^[4'|'^A{';PFK5='^A?'|'^F05'|'^[5'|'^A|';",
+"  PFK6='^A@'|'^F06'|'^[6'|'^A}';PFK7='^AA'|'^AI'|'^F07'|'^[7'|'^A~';",
+"  PFK8='^AB'|'^AQ'|'^F08'|'^[8'|'^A^?';PFK9='^AC'|'^F09'|'^[9'|'^A^A^@';",
+"  PFK10='^AD'|'^F10'|'^[0'|'^A^A^A';SETHOM='^[!';COLTAB='^[i'|'^[I';",
+"  COLBAK='^[b'|'^[B';INDENT='^[l'|'^[L';UNDENT='^[h'|'^[H';",
+"  PFK11='^AT'|'^F11'|'^[-'|'^A^A^B';PFK12='^AU'|'^F12'|'^A^A^C'|'^[=';",
+"  PFK13='^AV'|'^F13';PFK14='^AW'|'^F14';PFK15='^AX'|'^F15';",
+"  PFK16='^AY'|'^F16';",
+"  PFK17='^AZ'|'^F17';PFK18='^A['|'^F18';PFK19='^A\\\\'|'^F19';",
+"  PFK20='^A]'|'^F20';PFK21='^A\\^'|'^F21';PFK22='^A_'|'^F22';PA3='^Aj'|'^P3';",
+"  PFK23='^A`'|'^F23';PFK24='^Aa'|'^F24';PA1='^Ah'|'^P1';PA2='^Ai'|'^P2';",
+"  RESET='^T'|'^R'; ",
+"  MASTER_RESET='^G';RESHOW='^V';DELTAB='^[\\\'';ESCAPE='^C';",
+"}",
+#else  /* defined(MSDOS) */
+"generic { clear = '^z'; flinp = '^x'; enter = '^m'; delete = '^d' | '^?';",
+"      synch = '^r'; reshow = '^v'; eeof = '^e'; tab = '^i';",
+"      btab = '^b'; nl = '^n'; left = '^h'; right = '^l';",
+"      up = '^k'; down = '^j'; einp = '^w'; reset = '^t';",
+"      xoff = '^s'; xon = '^q'; escape = '^c'; ferase = '^u';",
+"      insrt = '\\E ';",
+"      pa1 = '^p1'; pa2 = '^p2'; pa3 = '^p3';",
+"      pfk1 = '\\E1'; pfk2 = '\\E2'; pfk3 = '\\E3'; pfk4 = '\\E4';",
+"      pfk5 = '\\E5'; pfk6 = '\\E6'; pfk7 = '\\E7'; pfk8 = '\\E8';",
+"      pfk9 = '\\E9'; pfk10 = '\\E0'; pfk11 = '\\E-'; pfk12 = '\\E=';",
+"      pfk13 = '\\E!'; pfk14 = '\\E@'; pfk15 = '\\E#'; pfk16 = '\\E$';",
+"      pfk17 = '\\E%'; pfk18 = '\\E\\^'; pfk19 = '\\E&'; pfk20 = '\\E*';",
+"      pfk21 = '\\E('; pfk22 = '\\E)'; pfk23 = '\\E_'; pfk24 = '\\E+';",
+"}",
+#endif /* defined(MSDOS) */
diff --git a/usr/src/usr.bin/tn3270/ascii/map3270.c b/usr/src/usr.bin/tn3270/ascii/map3270.c
new file mode 100644 (file)
index 0000000..c2cf01c
--- /dev/null
@@ -0,0 +1,931 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)map3270.c  4.2 (Berkeley) 4/26/91";
+#endif /* not lint */
+
+/*     This program reads a description file, somewhat like /etc/termcap,
+    that describes the mapping between the current terminal's keyboard and
+    a 3270 keyboard.
+ */
+#ifdef DOCUMENTATION_ONLY
+/* here is a sample (very small) entry...
+
+       # this table is sensitive to position on a line.  In particular,
+       # a terminal definition for a terminal is terminated whenever a
+       # (non-comment) line beginning in column one is found.
+       #
+       # this is an entry to map tvi924 to 3270 keys...
+       v8|tvi924|924|televideo model 924 {
+               pfk1 =  '\E1';
+               pfk2 =  '\E2';
+               clear = '^z';           # clear the screen
+       }
+ */
+#endif /* DOCUMENTATION_ONLY */
+\f
+#include <stdio.h>
+#include <ctype.h>
+#if    defined(unix)
+#include <strings.h>
+#else  /* defined(unix) */
+#include <string.h>
+#endif /* defined(unix) */
+
+#define        IsPrint(c)      ((isprint(c) && !isspace(c)) || ((c) == ' '))
+
+#include "state.h"
+#include "map3270.h"
+
+#include "../general/globals.h"
+\f
+/* this is the list of types returned by the lex processor */
+#define        LEX_CHAR        400                     /* plain unadorned character */
+#define        LEX_ESCAPED     LEX_CHAR+1              /* escaped with \ */
+#define        LEX_CARETED     LEX_ESCAPED+1           /* escaped with ^ */
+#define        LEX_END_OF_FILE LEX_CARETED+1           /* end of file encountered */
+#define        LEX_ILLEGAL     LEX_END_OF_FILE+1       /* trailing escape character */
+
+/* the following is part of our character set dependancy... */
+#define        ESCAPE          0x1b
+#define        TAB             0x09
+#define        NEWLINE         0x0a
+#define        CARRIAGE_RETURN 0x0d
+
+typedef struct {
+    int type;          /* LEX_* - type of character */
+    int value;         /* character this was */
+} lexicon;
+
+typedef struct {
+    int                length;         /* length of character string */
+    char       array[500];     /* character string */
+} stringWithLength;
+
+#define        panic(s)        { fprintf(stderr, s); exit(1); }
+
+static state firstentry = { 0, STATE_NULL, 0, 0 };
+static state *headOfQueue = &firstentry;
+\f
+/* the following is a primitive adm3a table, to be used when nothing
+ * else seems to be avaliable.
+ */
+
+#ifdef DEBUG
+static int debug = 0;          /* debug flag (for debuggin tables) */
+#endif /* DEBUG */
+
+static int (*GetTc)();
+static int doPaste = 1;                /* should we have side effects */
+static int picky = 0;          /* do we complain of unknown functions? */
+static char usePointer = 0;    /* use pointer, or file */
+static FILE *ourFile= 0;
+static char *environPointer = 0;/* if non-zero, point to input
+                                * string in core.
+                                */
+static char **whichkey = 0;
+static char *keysgeneric[] = {
+#include "default.map"         /* Define the default default */
+
+       0,                      /* Terminate list of entries */
+};
+                       ;
+\f
+static int     Empty = 1,              /* is the unget lifo empty? */
+               Full = 0;               /* is the unget lifo full? */
+static lexicon lifo[200] = { 0 };      /* character stack for parser */
+static int     rp = 0,                 /* read pointer into lifo */
+               wp = 0;                 /* write pointer into lifo */
+
+static int
+GetC()
+{
+    int character;
+
+    if (usePointer) {
+       if ((*environPointer) == 0) {
+           /*
+            * If we have reached the end of this string, go on to
+            * the next (if there is a next).
+            */
+           if (whichkey == 0) {
+               static char suffix = 'A';       /* From environment */
+               char envname[9];
+               extern char *getenv();
+
+               (void) sprintf(envname, "MAP3270%c", suffix++);
+               environPointer = getenv(envname);
+           } else {
+               whichkey++;                     /* default map */
+               environPointer = *whichkey;
+           }
+       }
+       if (*environPointer) {
+          character = 0xff&*environPointer++;
+       } else {
+          character = EOF;
+       }
+    } else {
+       character = getc(ourFile);
+    }
+    return(character);
+}
+
+static lexicon
+Get()
+{
+    lexicon c;
+    register lexicon *pC = &c;
+    register int character;
+
+    if (!Empty) {
+       *pC = lifo[rp];
+       rp++;
+       if (rp == sizeof lifo/sizeof (lexicon)) {
+           rp = 0;
+       }
+       if (rp == wp) {
+           Empty = 1;
+       }
+       Full = 0;
+    } else {
+       character = GetC();
+       switch (character) {
+       case EOF:
+           pC->type = LEX_END_OF_FILE;
+           break;
+       case '^':
+           character = GetC();
+           if (!IsPrint(character)) {
+               pC->type = LEX_ILLEGAL;
+           } else {
+               pC->type = LEX_CARETED;
+               if (character == '?') {
+                   character |= 0x40;  /* rubout */
+               } else {
+                   character &= 0x1f;
+               }
+           }
+           break;
+       case '\\':
+           character = GetC();
+           if (!IsPrint(character)) {
+               pC->type = LEX_ILLEGAL;
+           } else {
+               pC->type = LEX_ESCAPED;
+               switch (character) {
+               case 'E': case 'e':
+                   character = ESCAPE;
+                   break;
+               case 't':
+                   character = TAB;
+                   break;
+               case 'n':
+                   character = NEWLINE;
+                   break;
+               case 'r':
+                   character = CARRIAGE_RETURN;
+                   break;
+               default:
+                   pC->type = LEX_ILLEGAL;
+                   break;
+               }
+           }
+           break;
+       default:
+           if ((IsPrint(character)) || isspace(character)) {
+               pC->type = LEX_CHAR;
+           } else {
+               pC->type = LEX_ILLEGAL;
+           }
+           break;
+       }
+       pC->value = character;
+    }
+    return(*pC);
+}
+
+static void
+UnGet(c)
+lexicon c;                     /* character to unget */
+{
+    if (Full) {
+       fprintf(stderr, "attempt to put too many characters in lifo\n");
+       panic("map3270");
+       /* NOTREACHED */
+    } else {
+       lifo[wp] = c;
+       wp++;
+       if (wp == sizeof lifo/sizeof (lexicon)) {
+           wp = 0;
+       }
+       if (wp == rp) {
+           Full = 1;
+       }
+       Empty = 0;
+    }
+}
+\f
+/*
+ * Construct a control character sequence
+ * for a special character.
+ */
+char *
+uncontrol(c)
+       register int c;
+{
+       static char buf[3];
+
+       if (c == 0x7f)
+               return ("^?");
+       if (c == '\377') {
+               return "-1";
+       }
+       if (c >= 0x20) {
+               buf[0] = c;
+               buf[1] = 0;
+       } else {
+               buf[0] = '^';
+               buf[1] = '@'+c;
+               buf[2] = 0;
+       }
+       return (buf);
+}
+\f
+/* compare two strings, ignoring case */
+
+ustrcmp(string1, string2)
+register char *string1;
+register char *string2;
+{
+    register int c1, c2;
+
+    while ((c1 = (unsigned char) *string1++) != 0) {
+       if (isupper(c1)) {
+           c1 = tolower(c1);
+       }
+       if (isupper(c2 = (unsigned char) *string2++)) {
+           c2 = tolower(c2);
+       }
+       if (c1 < c2) {
+           return(-1);
+       } else if (c1 > c2) {
+           return(1);
+       }
+    }
+    if (*string2) {
+       return(-1);
+    } else {
+       return(0);
+    }
+}
+\f
+
+static stringWithLength *
+GetQuotedString()
+{
+    lexicon lex;
+    static stringWithLength output = { 0 };    /* where return value is held */
+    char *pointer = output.array;
+
+    lex = Get();
+    if ((lex.type != LEX_CHAR) || (lex.value != '\'')) {
+       UnGet(lex);
+       return(0);
+    }
+    while (1) {
+       lex = Get();
+       if ((lex.type == LEX_CHAR) && (lex.value == '\'')) {
+           break;
+       }
+       if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) {
+           UnGet(lex);
+           return(0);          /* illegal character in quoted string */
+       }
+       if (pointer >= output.array+sizeof output.array) {
+           return(0);          /* too long */
+       }
+       *pointer++ = lex.value;
+    }
+    output.length = pointer-output.array;
+    return(&output);
+}
+
+#ifdef NOTUSED
+static stringWithLength *
+GetCharString()
+{
+    lexicon lex;
+    static stringWithLength output;
+    char *pointer = output.array;
+
+    lex = Get();
+
+    while ((lex.type == LEX_CHAR) &&
+                       !isspace(lex.value) && (lex.value != '=')) {
+       *pointer++ = lex.value;
+       lex = Get();
+       if (pointer >= output.array + sizeof output.array) {
+           return(0);          /* too long */
+       }
+    }
+    UnGet(lex);
+    output.length = pointer-output.array;
+    return(&output);
+}
+#endif /* NOTUSED */
+
+static
+GetCharacter(character)
+int    character;              /* desired character */
+{
+    lexicon lex;
+
+    lex = Get();
+
+    if ((lex.type != LEX_CHAR) || (lex.value != character)) {
+       UnGet(lex);
+       return(0);
+    }
+    return(1);
+}
+
+#ifdef NOTUSED
+static
+GetString(string)
+char   *string;                /* string to get */
+{
+    lexicon lex;
+
+    while (*string) {
+       lex = Get();
+       if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) {
+           UnGet(lex);
+           return(0);          /* XXX restore to state on entry */
+       }
+       string++;
+    }
+    return(1);
+}
+#endif /* NOTUSED */
+
+
+static stringWithLength *
+GetAlphaMericString()
+{
+    lexicon lex;
+    static stringWithLength output = { 0 };
+    char *pointer = output.array;
+#   define     IsAlnum(c)      (isalnum(c) || (c == '_') \
+                                       || (c == '-') || (c == '.'))
+
+    lex = Get();
+
+    if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) {
+       UnGet(lex);
+       return(0);
+    }
+
+    while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) {
+       *pointer++ = lex.value;
+       lex = Get();
+    }
+    UnGet(lex);
+    *pointer = 0;
+    output.length = pointer-output.array;
+    return(&output);
+}
+
+
+/* eat up characters until a new line, or end of file.  returns terminating
+       character.
+ */
+
+static lexicon
+EatToNL()
+{
+    lexicon lex;
+
+    lex = Get();
+
+    while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) && 
+               (lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) {
+       lex = Get();
+    }
+    if (lex.type != LEX_END_OF_FILE) {
+       return(Get());
+    } else {
+       return(lex);
+    }
+}
+
+
+static void
+GetWS()
+{
+    lexicon lex;
+
+    lex = Get();
+
+    while ((lex.type == LEX_CHAR) &&
+                       (isspace(lex.value) || (lex.value == '#'))) {
+       if (lex.value == '#') {
+           lex = EatToNL();
+       } else {
+           lex = Get();
+       }
+    }
+    UnGet(lex);
+}
+\f
+static void
+FreeState(pState)
+state *pState;
+{
+    extern int free();
+
+    free((char *)pState);
+}
+
+
+static state *
+GetState()
+{
+    state *pState;
+    extern char *malloc();
+
+    pState = (state *) malloc(sizeof (state));
+
+    pState->result = STATE_NULL;
+    pState->next = 0;
+
+    return(pState);
+}
+
+
+static state *
+FindMatchAtThisLevel(pState, character)
+state  *pState;
+int    character;
+{
+    while (pState) {
+       if (pState->match == character) {
+           return(pState);
+       }
+       pState = pState->next;
+    }
+    return(0);
+}
+
+
+static state *
+PasteEntry(head, string, count, identifier)
+state                  *head;          /* points to who should point here... */
+char                   *string;        /* which characters to paste */
+int                    count;          /* number of character to do */
+char                   *identifier;    /* for error messages */
+{
+    state *pState, *other;
+
+    if (!doPaste) {            /* flag to not have any side effects */
+       return((state *)1);
+    }
+    if (!count) {
+       return(head);   /* return pointer to the parent */
+    }
+    if ((head->result != STATE_NULL) && (head->result != STATE_GOTO)) {
+       /* this means that a previously defined sequence is an initial
+        * part of this one.
+        */
+       fprintf(stderr, "Conflicting entries found when scanning %s\n",
+               identifier);
+       return(0);
+    }
+#   ifdef      DEBUG
+       if (debug) {
+           fprintf(stderr, "%s", uncontrol(*string));
+       }
+#   endif      /* DEBUG */
+    pState = GetState();
+    pState->match = *string;
+    if (head->result == STATE_NULL) {
+       head->result = STATE_GOTO;
+       head->address = pState;
+       other = pState;
+    } else {           /* search for same character */
+       if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) {
+           FreeState(pState);
+       } else {
+           pState->next = head->address;
+           head->address = pState;
+           other = pState;
+       }
+    }
+    return(PasteEntry(other, string+1, count-1, identifier));
+}
+\f
+static
+GetInput(tc, identifier)
+int tc;
+char *identifier;              /* entry being parsed (for error messages) */
+{
+    stringWithLength *outputString;
+    state *head;
+    state fakeQueue;
+
+    if (doPaste) {
+       head = headOfQueue;     /* always points to level above this one */
+    } else {
+       head = &fakeQueue;      /* don't have any side effects... */
+    }
+
+    if ((outputString = GetQuotedString()) == 0) {
+       return(0);
+    } else if (IsPrint(outputString->array[0])) {
+       fprintf(stderr,
+        "first character of sequence for %s is not a control type character\n",
+               identifier);
+       return(0);
+    } else {
+       if ((head = PasteEntry(head, outputString->array,
+                               outputString->length, identifier)) == 0) {
+           return(0);
+       }
+       GetWS();
+       while ((outputString = GetQuotedString()) != 0) {
+           if ((head = PasteEntry(head, outputString->array,
+                               outputString->length, identifier)) == 0) {
+               return(0);
+           }
+           GetWS();
+       }
+    }
+    if (!doPaste) {
+       return(1);
+    }
+    if ((head->result != STATE_NULL) && (head->result != tc)) {
+       /* this means that this sequence is an initial part
+        * of a previously defined one.
+        */
+       fprintf(stderr, "Conflicting entries found when scanning %s\n",
+               identifier);
+       return(0);
+    } else {
+       head->result = tc;
+       return(1);              /* done */
+    }
+}
+\f
+static
+GetDefinition()
+{
+    stringWithLength *string;
+    int Tc;
+
+    GetWS();
+    if ((string = GetAlphaMericString()) == 0) {
+       return(0);
+    }
+    string->array[string->length] = 0;
+    if (doPaste) {
+       if ((Tc = (*GetTc)(string->array)) == -1) {
+           if (picky) {
+               fprintf(stderr, "%s: unknown 3270 key identifier\n",
+                                                       string->array);
+           }
+           Tc = STATE_NULL;
+       }
+    } else {
+       Tc = STATE_NULL;                /* XXX ? */
+    }
+    GetWS();
+    if (!GetCharacter('=')) {
+       fprintf(stderr,
+               "Required equal sign after 3270 key identifier %s missing\n",
+                       string->array);
+       return(0);
+    }
+    GetWS();
+    if (!GetInput(Tc, string->array)) {
+       fprintf(stderr, "Missing definition part for 3270 key %s\n",
+                               string->array);
+       return(0);
+    } else {
+       GetWS();
+       while (GetCharacter('|')) {
+#          ifdef       DEBUG
+               if (debug) {
+                   fprintf(stderr, " or ");
+               }
+#          endif       /* DEBUG */
+           GetWS();
+           if (!GetInput(Tc, string->array)) {
+               fprintf(stderr, "Missing definition part for 3270 key %s\n",
+                                       string->array);
+               return(0);
+           }
+           GetWS();
+       }
+    }
+    GetWS();
+    if (!GetCharacter(';')) {
+       fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array);
+       return(0);
+    }
+#   ifdef      DEBUG
+       if (debug) {
+           fprintf(stderr, ";\n");
+       }
+#   endif      /* DEBUG */
+    return(1);
+}
+
+
+static
+GetDefinitions()
+{
+    if (!GetDefinition()) {
+       return(0);
+    } else {
+       while (GetDefinition()) {
+           ;
+       }
+    }
+    return(1);
+}
+
+static
+GetBegin()
+{
+    GetWS();
+    if (!GetCharacter('{')) {
+       return(0);
+    }
+    return(1);
+}
+
+static
+GetEnd()
+{
+    GetWS();
+    if (!GetCharacter('}')) {
+       return(0);
+    }
+    return(1);
+}
+
+static
+GetName()
+{
+    if (!GetAlphaMericString()) {
+       return(0);
+    }
+    GetWS();
+    while (GetAlphaMericString()) {
+       GetWS();
+    }
+    return(1);
+}
+
+static
+GetNames()
+{
+    GetWS();
+    if (!GetName()) {
+       return(0);
+    } else {
+       GetWS();
+       while (GetCharacter('|')) {
+           GetWS();
+           if (!GetName()) {
+               return(0);
+           }
+       }
+    }
+    return(1);
+}
+
+static
+GetEntry0()
+{
+    if (!GetBegin()) {
+       fprintf(stderr, "no '{'\n");
+       return(0);
+    } else if (!GetDefinitions()) {
+       fprintf(stderr, "unable to parse the definitions\n");
+       return(0);
+    } else if (!GetEnd()) {
+       fprintf(stderr, "No '}' or scanning stopped early due to error.\n");
+       return(0);
+    } else {
+       /* done */
+       return(1);
+    }
+}
+
+
+static
+GetEntry()
+{
+    if (!GetNames()) {
+       fprintf(stderr, "Invalid name field in entry.\n");
+       return(0);
+    } else {
+       return(GetEntry0());
+    }
+}
+\f
+/* position ourselves within a given filename to the entry for the current
+ *     KEYBD (or TERM) variable
+ */
+
+Position(filename, keybdPointer)
+char *filename;
+char *keybdPointer;
+{
+    lexicon lex;
+    stringWithLength *name = 0;
+    stringWithLength *oldName;
+#   define     Return(x) {doPaste = 1; return(x);}
+
+    doPaste = 0;
+
+    if ((ourFile = fopen(filename, "r")) == NULL) {
+#   if !defined(MSDOS)
+       fprintf(stderr, "Unable to open file %s\n", filename);
+#   endif /* !defined(MSDOS) */
+       Return(0);
+    }
+    lex = Get();
+    while (lex.type != LEX_END_OF_FILE) {
+       UnGet(lex);
+       /* now, find an entry that is our type. */
+       GetWS();
+       oldName = name;
+       if ((name = GetAlphaMericString()) != 0) {
+           if (!ustrcmp(name->array, keybdPointer)) {
+               /* need to make sure there is a name here... */
+               lex.type = LEX_CHAR;
+               lex.value = 'a';
+               UnGet(lex);
+               Return(1);
+           }
+       } else if (GetCharacter('|')) {
+           ;           /* more names coming */
+       } else {
+           lex = Get();
+           UnGet(lex);
+           if (lex.type != LEX_END_OF_FILE) {
+                   if (!GetEntry0()) { /* start of an entry */
+                       fprintf(stderr,
+                           "error was in entry for %s in file %s\n",
+                           (oldName)? oldName->array:"(unknown)", filename);
+                   Return(0);
+               }
+           }
+       }
+       lex = Get();
+    }
+#if !defined(MSDOS)
+    fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer,
+                   filename);
+#endif /* !defined(MSDOS) */
+    Return(0);
+}
+
+char *
+strsave(string)
+char *string;
+{
+    char *p;
+    extern char *malloc();
+
+    p = malloc((unsigned int)strlen(string)+1);
+    if (p != 0) {
+       strcpy(p, string);
+    }
+    return(p);
+}
+
+
+/*
+ * InitControl - our interface to the outside.  What we should
+ *  do is figure out keyboard (or terminal) type, set up file pointer
+ *  (or string pointer), etc.
+ */
+
+state *
+InitControl(keybdPointer, pickyarg, translator)
+char   *keybdPointer;
+int    pickyarg;               /* Should we be picky? */
+int    (*translator)();        /* Translates ascii string to integer */
+{
+    extern char *getenv();
+    int GotIt;
+
+    picky = pickyarg;
+    GetTc = translator;
+
+    if (keybdPointer == 0) {
+        keybdPointer = getenv("KEYBD");
+    }
+    if (keybdPointer == 0) {
+       keybdPointer = getenv("TERM");
+    }
+
+                   /*
+                    * Some environments have getenv() return
+                    * out of a static area.  So, save the keyboard name.
+                    */
+    if (keybdPointer) {
+        keybdPointer = strsave(keybdPointer);
+    }
+    environPointer = getenv("MAP3270");
+    if (environPointer
+           && (environPointer[0] != '/')
+#if    defined(MSDOS)
+           && (environPointer[0] != '\\')
+#endif /* defined(MSDOS) */
+           && (strncmp(keybdPointer, environPointer,
+                       strlen(keybdPointer) != 0)
+               || (environPointer[strlen(keybdPointer)] != '{'))) /* } */
+    {
+       environPointer = 0;
+    }
+
+    if ((!environPointer)
+#if    defined(MSDOS)
+               || (*environPointer == '\\')
+#endif /* defined(MSDOS) */
+               || (*environPointer == '/')) {
+       usePointer = 0;
+       GotIt = 0;
+       if (!keybdPointer) {
+#if !defined(MSDOS)
+           fprintf(stderr, "%s%s%s%s",
+               "Neither the KEYBD environment variable nor the TERM ",
+               "environment variable\n(one of which is needed to determine ",
+               "the type of keyboard you are using)\n",
+               "is set.  To set it, say 'setenv KEYBD <type>'\n");
+#endif /* !defined(MSDOS) */
+       } else {
+           if (environPointer) {
+               GotIt = Position(environPointer, keybdPointer);
+           }
+           if (!GotIt) {
+               GotIt = Position("/etc/map3270", keybdPointer);
+           }
+       }
+       if (!GotIt) {
+           if (environPointer) {
+               GotIt = Position(environPointer, "unknown");
+           }
+           if (!GotIt) {
+               GotIt = Position("/etc/map3270", keybdPointer);
+           }
+       }
+       if (!GotIt) {
+#if !defined(MSDOS)
+           fprintf(stderr, "Using default key mappings.\n");
+#endif /* !defined(MSDOS) */
+           usePointer = 1;             /* flag use of non-file */
+           whichkey = keysgeneric;
+           environPointer = *whichkey; /* use default table */
+       }
+    } else {
+       usePointer = 1;
+    }
+    (void) GetEntry();
+    return(firstentry.address);
+}
diff --git a/usr/src/usr.bin/tn3270/ascii/map3270.h b/usr/src/usr.bin/tn3270/ascii/map3270.h
new file mode 100644 (file)
index 0000000..98b3e9d
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)map3270.h   4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * Declaration for map3270.c.
+ */
+
+extern state
+    *InitControl();
diff --git a/usr/src/usr.bin/tn3270/ascii/mset.c b/usr/src/usr.bin/tn3270/ascii/mset.c
new file mode 100644 (file)
index 0000000..0f39698
--- /dev/null
@@ -0,0 +1,410 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1988 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mset.c     4.2 (Berkeley) 4/26/91";
+#endif /* not lint */
+
+/*
+ * this program outputs the user's 3270 mapping table in a form suitable
+ *     for inclusion in the environment.  Typically, this might be used
+ *     by:
+ *             setenv MAP3270 "`mset`"
+ */
+
+#include <stdio.h>
+#if    defined(unix)
+#include <strings.h>
+#else  /* defined(unix) */
+#include <string.h>
+#endif /* defined(unix) */
+#include "../ctlr/function.h"
+
+#include "state.h"
+#include "map3270.h"
+
+#include "../api/astosc.h"
+
+#include "../general/globals.h"
+
+struct regstate {
+       char *result;
+       char *match_start;
+       char *match_end;                /* start of NEXT state's match string */
+       struct regstate *forward;
+       struct regstate *backward;
+};
+
+static struct regstate regstates[500], *rptr= 0;       /* for sorting states */
+static char array[5000];               /* lot's of room */
+static int toshell = 0;                        /* export to shell */
+static int numbchars = 0;              /* number of chars in envir. var */
+
+static int
+MyStrcmp(str1, str2)
+char *str1, *str2;
+{
+       if (strncmp(str1, "PFK", 3) == 0 && strncmp(str2, "PFK", 3) == 0
+           && strlen(str1) != strlen(str2)) {
+          return(strlen(str1) - strlen(str2));
+       }
+       return(strcmp(str1, str2));
+}
+
+static void
+forwRegister(regptr, sptr)
+struct regstate *regptr, *sptr;
+{
+
+    regptr->forward = sptr->forward;
+    regptr->backward = sptr;
+    (sptr->forward)->backward = regptr;
+    sptr->forward = regptr;
+}
+
+static void
+backRegister(regptr, sptr)
+struct regstate *regptr, *sptr;
+{
+
+    regptr->forward = sptr;
+    regptr->backward = sptr->backward;
+    (sptr->backward)->forward = regptr;
+    sptr->backward = regptr;
+}
+
+static struct regstate *
+doRegister(regptr)
+register struct regstate *regptr;
+{
+    static struct regstate *pivot = regstates;
+    register struct regstate *sptr = pivot;
+    int check;
+
+    if (pivot == regstates) {          /* first time called */
+       pivot->forward = regptr;
+       regptr->backward = pivot++;
+       pivot->backward = regptr;
+       regptr->forward = pivot++;
+       return(++regptr);
+    }
+    if ((check = MyStrcmp(regptr->result, pivot->result)) < 0) {
+       while (check < 0) {
+           if (sptr->backward == regstates) {
+               backRegister(regptr, sptr);
+               pivot = pivot->backward;
+               return(++regptr);
+            }
+            sptr = sptr->backward;
+            check = MyStrcmp(regptr->result, sptr->result);
+       }
+       forwRegister(regptr, sptr);
+       pivot = pivot->backward;
+       return(++regptr);
+    }
+    while (check > 0) {
+       if ((sptr->forward)->result == 0) {
+           forwRegister(regptr, sptr);
+           pivot = pivot->forward;
+           return(++regptr);
+       }
+       sptr = sptr->forward;
+       check = MyStrcmp(regptr->result, sptr->result);
+    }
+    backRegister(regptr, sptr);
+    if (pivot->forward->result) {
+       pivot = pivot->forward;
+    }
+    return(++regptr);
+}
+
+static char *
+addString(strcount, character)
+int strcount;
+char character;
+{
+    static char *string = array;
+    int i;
+
+    if (rptr->match_start == 0) {
+       rptr->match_start = string;
+       for (i=0; i < strcount; i++) {
+           *string++ = *((rptr-1)->match_start+i);
+       }
+    }
+    *string++ = character;
+    return(string);
+}
+
+static char savename[20] = " ";  /* for deciding if name is new */
+
+static void
+printString(string, begin, tc_name)
+register char *string;
+char *begin, *tc_name;
+{
+    register char *st1, *st2;
+    register int pchar;
+    static char suffix = 'A';
+    int new = strcmp(savename, tc_name);
+    char delim = new ? ';' : '|';
+    char *uncontrol();
+
+    st1 = begin;
+
+    numbchars += 5 + (new ? strlen(tc_name) : -1);
+    if (toshell && numbchars > 1011) {
+        new = 1;
+       delim = ';';
+        numbchars = 5 + strlen(tc_name);
+        printf(";\nsetenv MAP3270%c ", suffix++);
+    }
+    if (strcmp(" ", savename)) {
+       if (toshell) {
+          printf("%c%c", '\\', delim);
+       }
+       else {
+          printf("%c", delim);
+       }
+    }
+    else {
+       numbchars -= 2;
+    }
+    if (toshell && new) {
+        printf("%s=%c'", tc_name,'\\');
+    }
+    else if (new) {
+        printf("%s='", tc_name);
+    }
+    else if (toshell) {
+       printf("%c'", '\\');
+    }
+    else {
+       printf("'");
+    }
+    (void) strcpy(savename, tc_name);
+    while (st1 != string) {
+       if (toshell && numbchars >= 1016) { /* leave room for ctrl and delim */
+          numbchars = 0;
+           printf(";\nsetenv MAP3270%c ", suffix++);
+       }
+       pchar = 0xff&(*st1++);
+       switch (pchar) {
+       case '"':
+       case '!':
+       case '$':
+       case '(':
+       case ')':
+       case ' ':
+       case ';':
+       case '&':
+       case '|':
+       case '>':
+       case '<':
+       case '`':
+       case '#':
+           numbchars += 2;
+           if (toshell) {
+              printf("%c%c", '\\', pchar);
+           }
+           else {
+              printf("%c", pchar);
+           }
+           break;
+       case '\\':
+       case '\'':
+           numbchars += 4;
+           if (toshell) {
+              printf("%c%c%c%c", '\\', '\\', '\\', pchar);
+           }
+           else {
+              printf("%c%c", '\\', pchar);
+           }
+           break;
+       case '^':
+           numbchars += 3;
+           if (toshell) {
+              printf("%c%c%c", '\\', '\\', pchar);
+           }
+           else {
+              printf("%c%c", '\\', pchar);
+           }
+           break;
+       default:
+           st2 = uncontrol(pchar);
+           while ((pchar = *st2++) != 0) {
+               switch (pchar) {
+               case '"':
+               case '!':
+               case '$':
+               case '(':
+               case ')':
+               case ' ':
+               case ';':
+               case '&':
+               case '|':
+               case '>':
+               case '<':
+               case '`':
+               case '#':
+               case '\\':
+               case '\'':
+                  if (toshell) {
+                     numbchars += 2; 
+                     printf("%c%c", '\\', pchar);
+                  }
+                  else {
+                     printf("%c", pchar);
+                  }
+                  break;
+               default:
+                  numbchars++;
+                  printf("%c", pchar);
+                  break;
+               }
+           }
+           break;
+       }
+    }
+    numbchars += 2;
+    if (toshell) {
+       printf("%c'", '\\');
+    }
+    else {
+       printf("'");
+    }
+}
+
+static void
+recurse(strcount, head)
+state *head;
+int strcount;
+{
+               /*      if there is a left,
+                *          recurse on left,
+                *      if there is no down,
+                *          print the string to here
+                *      else,
+                *           add the current match to the string,
+                *           recurse.
+                *      exit.
+                */
+
+    if (head->next) {
+       recurse(strcount, head->next);
+    }
+    if (head->result != STATE_GOTO) {
+       rptr->match_end = addString(strcount, head->match);
+       rptr->result = astosc[head->result].name;
+       rptr = doRegister(rptr);
+    } else {
+       (void) addString(strcount, head->match);
+       recurse(strcount+1, head->address);
+       strcount--;
+    }
+    return;
+}
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    state *head;
+    char *keybdPointer = (char *) 0;
+    char *commandName = argv[0];
+    extern char *getenv();
+    int picky = 0;
+
+    while ((argc > 1) && (argv[1][0] == '-')) {
+       if (!strcmp(argv[1], "-picky")) {
+           picky++;
+       } else if (!strcmp(argv[1], "-shell")) {
+           toshell++;
+       } else {
+           fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
+               commandName);
+           exit(1);
+           /*NOTREACHED*/
+       }
+       argv++;
+       argc--;
+    }
+    if (argc == 2) {
+        keybdPointer = argv[1];
+    } else if (argc > 2) {
+       fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
+               commandName);
+       exit(1);
+       /*NOTREACHED*/
+    }
+    head = InitControl(keybdPointer, picky, ascii_to_index);
+    if (!head) {
+       return(1);
+    }
+    if (keybdPointer == 0) {
+        keybdPointer = getenv("KEYBD");
+    }
+    if (keybdPointer == 0) {
+       keybdPointer = getenv("TERM");
+    }
+    if (keybdPointer == 0) {
+       keybdPointer = "3a";    /* use 3a as the terminal */
+    }
+    if (toshell) {
+       printf("set noglob;\nsetenv MAP3270 ");
+    }
+    printf("%s{", keybdPointer);
+    numbchars = 2 + strlen(keybdPointer);
+    /* now, run through the table registering entries */
+    rptr = regstates + 2;
+    recurse(0, head);
+    /* now print them out */
+    for (rptr = regstates[0].forward; rptr->result != 0;
+        rptr = rptr->forward) { 
+       printString(rptr->match_end, rptr->match_start, rptr->result);
+    }
+    if (toshell) {
+       printf("%c;};\nunset noglob;\n", '\\');
+    }
+    else {
+      printf(";}\n");
+    }
+    return(0);
+}
diff --git a/usr/src/usr.bin/tn3270/ascii/state.h b/usr/src/usr.bin/tn3270/ascii/state.h
new file mode 100644 (file)
index 0000000..bf0e969
--- /dev/null
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)state.h     4.2 (Berkeley) 4/26/91
+ */
+
+#define        INCLUDED_STATE
+
+/* this defines the state structure used by the key mapping routines */
+
+
+#define        STATE_NULL      -1              /* Falls off edge */
+#define        STATE_GOTO      -2              /* GOTO internal state */
+
+#define state  struct State
+struct State {
+    int                match;          /* character to match */
+    int                result;         /* 3270 control code */
+    state      *next;          /* next entry in this same state */
+    state      *address;       /* if goto, where is next state */
+};
diff --git a/usr/src/usr.bin/tn3270/ascii/termin.c b/usr/src/usr.bin/tn3270/ascii/termin.c
new file mode 100644 (file)
index 0000000..9433064
--- /dev/null
@@ -0,0 +1,281 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)termin.c   4.2 (Berkeley) 4/26/91";
+#endif /* not lint */
+
+/* this takes characters from the keyboard, and produces 3270 keystroke
+       codes
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "../general/general.h"
+#include "../ctlr/function.h"
+#include "../ctlr/externs.h"
+#include "../ctlr/declare.h"
+
+#include "../api/astosc.h"
+#include "state.h"
+
+#include "../general/globals.h"
+
+#define IsControl(c)   (!isprint(c) || (isspace(c) && ((c) != ' ')))
+
+#define NextState(x)   (x->next)
+\f
+/* XXX temporary - hard code in the state table */
+
+#define MATCH_ANY 0xff                 /* actually, match any character */
+
+\f
+static unsigned char
+       ourBuffer[100],         /* where we store stuff */
+       *ourPHead = ourBuffer,  /* first character in buffer */
+       *ourPTail = ourBuffer,  /* where next character goes */
+       *TransPointer = 0;      /* For transparent mode data */
+
+static int InControl;
+static int WaitingForSynch;
+
+static struct astosc
+       *spacePTR = 0;          /* Space is hard to enter */
+
+static state
+       *headOfControl = 0;     /* where we enter code state table */
+
+#define FullChar       ((ourPTail+5) >= ourBuffer+sizeof ourBuffer)
+#define EmptyChar      (ourPTail == ourPHead)
+
+\f
+/*
+ * init_keyboard()
+ *
+ * Initialize the keyboard variables.
+ */
+
+void
+init_keyboard()
+{
+    ourPHead = ourPTail = ourBuffer;
+    InControl = 0;
+    WaitingForSynch = 0;
+}
+
+
+/*
+ * Initialize the keyboard mapping file.
+ */
+
+void
+InitMapping()
+{
+    extern state *InitControl();
+    register struct astosc *ptr;
+
+    if (!headOfControl) {
+       /* need to initialize */
+       headOfControl = InitControl((char *)0, 0, ascii_to_index);
+       if (!headOfControl) {           /* should not occur */
+           quit();
+       }
+       for (ptr = &astosc[0]; ptr <= &astosc[highestof(astosc)]; ptr++) {
+           if (ptr->function == FCN_SPACE) {
+               spacePTR = ptr;
+           }
+       }
+    }
+}
+
+
+/* AddChar - put a function index in our buffer */
+
+static void
+AddChar(c)
+int    c;
+{
+    if (!FullChar) {
+       *ourPTail++ = c;
+    } else {
+       RingBell("Typeahead buffer full");
+    }
+}
+
+/* FlushChar - put everything where it belongs */
+
+static void
+FlushChar()
+{
+    ourPTail = ourBuffer;
+    ourPHead = ourBuffer;
+}
+
+/*ARGSUSED*/
+void
+TransInput(onoff, mode)
+int    mode;                   /* Which KIND of transparent input */
+int    onoff;                  /* Going in, or coming out */
+{
+    if (onoff) {
+       /* Flush pending input */
+       FlushChar();
+       TransPointer = ourBuffer;
+    } else {
+    }
+}
+
+int
+TerminalIn()
+{
+    /* send data from us to next link in stream */
+    int work = 0;
+    register struct astosc *ptr;
+
+    while (!EmptyChar) {                       /* send up the link */
+       if (*ourPHead == ' ') {
+           ptr = spacePTR;
+       } else {
+           ptr = &astosc[*ourPHead];
+       }
+       if (AcceptKeystroke(ptr->scancode, ptr->shiftstate) == 1) {
+           ourPHead++;
+           work = 1;
+       } else {
+           break;
+       }
+    }
+
+    if (EmptyChar) {
+       FlushChar();
+    }
+       /* return value answers question: "did we do anything useful?" */
+    return work;
+}
+
+int
+DataFromTerminal(buffer, count)
+register char  *buffer;                /* the data read in */
+register int   count;                  /* how many bytes in this buffer */
+{
+    register state *regControlPointer;
+    register char c;
+    register int result;
+    int origCount;
+    extern int bellwinup;
+    static state *controlPointer;
+
+    if (TransPointer) {
+       int i;
+
+       if ((count+TransPointer) >= (ourBuffer+sizeof ourBuffer)) {
+           i = ourBuffer+sizeof ourBuffer-TransPointer;
+       } else {
+           i = count;
+       }
+       while (i--) {
+           c = (*buffer++)&0x7f;
+           *TransPointer++ = c|0x80;
+           if (c == '\r') {
+               SendTransparent((char *)ourBuffer, TransPointer-ourBuffer);
+               TransPointer = 0;               /* Done */
+               break;
+           }
+       }
+       return count;
+    }
+
+    if (bellwinup) {
+       void BellOff();
+
+       BellOff();
+    }
+
+    origCount = count;
+
+    while (count) {
+       c = *buffer++&0x7f;
+       count--;
+
+       if (!InControl && !IsControl(c)) {
+           AddChar(c);                 /* add ascii character */
+       } else {
+           if (!InControl) {           /* first character of sequence */
+               InControl = 1;
+               controlPointer = headOfControl;
+           }
+           /* control pointer points to current position in state table */
+           for (regControlPointer = controlPointer; ;
+                       regControlPointer = NextState(regControlPointer)) {
+               if (!regControlPointer) {       /* ran off end */
+                   RingBell("Invalid control sequence");
+                   regControlPointer = headOfControl;
+                   InControl = 0;
+                   count = 0;          /* Flush current input */
+                   break;
+               }
+               if ((regControlPointer->match == c) /* hit this character */
+                       || (regControlPointer->match == MATCH_ANY)) {
+                   result = regControlPointer->result;
+                   if (result == STATE_GOTO) {
+                       regControlPointer = regControlPointer->address;
+                       break;                  /* go to next character */
+                   }
+                   if (WaitingForSynch) {
+                       if (astosc[result].function == FCN_SYNCH) {
+                           WaitingForSynch = 0;
+                       } else {
+                           void RingBell();
+
+                           RingBell("Need to type synch character");
+                       }
+                   }
+                   else if (astosc[result].function == FCN_FLINP) {
+                       FlushChar();            /* Don't add FLINP */
+                   } else {
+                       if (astosc[result].function == FCN_MASTER_RESET) {
+                           FlushChar();
+                       }
+                       AddChar(result);                /* add this code */
+                   }
+                   InControl = 0;      /* out of control now */
+                   break;
+               }
+           }
+           controlPointer = regControlPointer;         /* save state */
+       }
+    }
+    (void) TerminalIn();                       /* try to send data */
+    return(origCount-count);
+}