From: William F. Jolitz Date: Fri, 26 Apr 1991 22:38:29 +0000 (-0800) Subject: 386BSD 0.1 development X-Git-Tag: 386BSD-0.1~1579 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/12aa61145b95540513900b65e1833c849fee3d97 386BSD 0.1 development 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 Synthesized-from: 386BSD-0.1 --- diff --git a/usr/src/usr.bin/tn3270/ascii/default.map b/usr/src/usr.bin/tn3270/ascii/default.map new file mode 100644 index 0000000000..7289671f8d --- /dev/null +++ b/usr/src/usr.bin/tn3270/ascii/default.map @@ -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 index 0000000000..c2cf01c9e2 --- /dev/null +++ b/usr/src/usr.bin/tn3270/ascii/map3270.c @@ -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 */ + +#include +#include +#if defined(unix) +#include +#else /* defined(unix) */ +#include +#endif /* defined(unix) */ + +#define IsPrint(c) ((isprint(c) && !isspace(c)) || ((c) == ' ')) + +#include "state.h" +#include "map3270.h" + +#include "../general/globals.h" + +/* 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; + +/* 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 */ +}; + ; + +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; + } +} + +/* + * 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); +} + +/* 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); + } +} + + +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); +} + +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)); +} + +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 */ + } +} + +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()); + } +} + +/* 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 '\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 index 0000000000..98b3e9d91b --- /dev/null +++ b/usr/src/usr.bin/tn3270/ascii/map3270.h @@ -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 index 0000000000..0f39698919 --- /dev/null +++ b/usr/src/usr.bin/tn3270/ascii/mset.c @@ -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 +#if defined(unix) +#include +#else /* defined(unix) */ +#include +#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 index 0000000000..bf0e969aaa --- /dev/null +++ b/usr/src/usr.bin/tn3270/ascii/state.h @@ -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 index 0000000000..943306424c --- /dev/null +++ b/usr/src/usr.bin/tn3270/ascii/termin.c @@ -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 +#include + +#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) + +/* XXX temporary - hard code in the state table */ + +#define MATCH_ANY 0xff /* actually, match any character */ + + +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) + + +/* + * 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); +}