xref: /original-bsd/usr.bin/tn3270/ascii/mset.c (revision 57124d5e)
1 /*
2  *	Copyright (c) 1984-1987 by the Regents of the
3  *	University of California and by Gregory Glenn Minshall.
4  *
5  *	Permission to use, copy, modify, and distribute these
6  *	programs and their documentation for any purpose and
7  *	without fee is hereby granted, provided that this
8  *	copyright and permission appear on all copies and
9  *	supporting documentation, the name of the Regents of
10  *	the University of California not be used in advertising
11  *	or publicity pertaining to distribution of the programs
12  *	without specific prior permission, and notice be given in
13  *	supporting documentation that copying and distribution is
14  *	by permission of the Regents of the University of California
15  *	and by Gregory Glenn Minshall.  Neither the Regents of the
16  *	University of California nor Gregory Glenn Minshall make
17  *	representations about the suitability of this software
18  *	for any purpose.  It is provided "as is" without
19  *	express or implied warranty.
20  */
21 
22 #ifndef	lint
23 static	char	sccsid[] = "@(#)mset.c	3.1 (Berkeley) 08/11/87";
24 #endif	/* ndef lint */
25 
26 /*
27  * this program outputs the user's 3270 mapping table in a form suitable
28  *	for inclusion in the environment.  Typically, this might be used
29  *	by:
30  *		setenv MAP3270 "`mset`"
31  */
32 
33 #include <stdio.h>
34 #if	defined(unix)
35 #include <strings.h>
36 #else	/* defined(unix) */
37 #include <string.h>
38 #endif	/* defined(unix) */
39 #include "../ctlr/function.h"
40 
41 #include "state.h"
42 #include "../api/astosc.h"
43 
44 #include "../general/globals.h"
45 #include "map3270.ext"
46 
47 struct regstate {
48 	char *result;
49 	char *match_start;
50 	char *match_end;		/* start of NEXT state's match string */
51 	struct regstate *forward;
52 	struct regstate *backward;
53 };
54 
55 static struct regstate regstates[500], *rptr= 0;	/* for sorting states */
56 static char array[5000];		/* lot's of room */
57 static int toshell = 0;			/* export to shell */
58 static int numbchars = 0;		/* number of chars in envir. var */
59 
60 static int
61 MyStrcmp(str1, str2)
62 char *str1, *str2;
63 {
64 	if (strncmp(str1, "PFK", 3) == 0 && strncmp(str2, "PFK", 3) == 0
65 	    && strlen(str1) != strlen(str2)) {
66 	   return(strlen(str1) - strlen(str2));
67 	}
68 	return(strcmp(str1, str2));
69 }
70 
71 static void
72 forwRegister(regptr, sptr)
73 struct regstate *regptr, *sptr;
74 {
75 
76     regptr->forward = sptr->forward;
77     regptr->backward = sptr;
78     (sptr->forward)->backward = regptr;
79     sptr->forward = regptr;
80 }
81 
82 static void
83 backRegister(regptr, sptr)
84 struct regstate *regptr, *sptr;
85 {
86 
87     regptr->forward = sptr;
88     regptr->backward = sptr->backward;
89     (sptr->backward)->forward = regptr;
90     sptr->backward = regptr;
91 }
92 
93 static struct regstate *
94 doRegister(regptr)
95 register struct regstate *regptr;
96 {
97     static struct regstate *pivot = regstates;
98     register struct regstate *sptr = pivot;
99     int check;
100 
101     if (pivot == regstates) {		/* first time called */
102 	pivot->forward = regptr;
103 	regptr->backward = pivot++;
104 	pivot->backward = regptr;
105 	regptr->forward = pivot++;
106 	return(++regptr);
107     }
108     if ((check = MyStrcmp(regptr->result, pivot->result)) < 0) {
109 	while (check < 0) {
110 	    if (sptr->backward == regstates) {
111 		backRegister(regptr, sptr);
112 		pivot = pivot->backward;
113 		return(++regptr);
114 	     }
115 	     sptr = sptr->backward;
116 	     check = MyStrcmp(regptr->result, sptr->result);
117 	}
118 	forwRegister(regptr, sptr);
119 	pivot = pivot->backward;
120 	return(++regptr);
121     }
122     while (check > 0) {
123 	if ((sptr->forward)->result == 0) {
124 	    forwRegister(regptr, sptr);
125     	    pivot = pivot->forward;
126 	    return(++regptr);
127 	}
128 	sptr = sptr->forward;
129 	check = MyStrcmp(regptr->result, sptr->result);
130     }
131     backRegister(regptr, sptr);
132     if (pivot->forward->result) {
133 	pivot = pivot->forward;
134     }
135     return(++regptr);
136 }
137 
138 static char *
139 addString(strcount, character)
140 int strcount;
141 char character;
142 {
143     static char *string = array;
144     int i;
145 
146     if (rptr->match_start == 0) {
147 	rptr->match_start = string;
148 	for (i=0; i < strcount; i++) {
149 	    *string++ = *((rptr-1)->match_start+i);
150 	}
151     }
152     *string++ = character;
153     return(string);
154 }
155 
156 static char savename[20] = " ";  /* for deciding if name is new */
157 
158 static void
159 printString(string, begin, tc_name)
160 register char *string;
161 char *begin, *tc_name;
162 {
163     register char *st1, *st2;
164     register int pchar;
165     static char suffix = 'A';
166     int new = strcmp(savename, tc_name);
167     char delim = new ? ';' : '|';
168     char *uncontrol();
169 
170     st1 = begin;
171 
172     numbchars += 5 + (new ? strlen(tc_name) : -1);
173     if (toshell && numbchars > 1011) {
174         new = 1;
175 	delim = ';';
176         numbchars = 5 + strlen(tc_name);
177         printf(";\nsetenv MAP3270%c ", suffix++);
178     }
179     if (strcmp(" ", savename)) {
180 	if (toshell) {
181 	   printf("%c%c", '\\', delim);
182 	}
183 	else {
184 	   printf("%c", delim);
185 	}
186     }
187     else {
188 	numbchars -= 2;
189     }
190     if (toshell && new) {
191         printf("%s=%c'", tc_name,'\\');
192     }
193     else if (new) {
194         printf("%s='", tc_name);
195     }
196     else if (toshell) {
197 	printf("%c'", '\\');
198     }
199     else {
200 	printf("'");
201     }
202     (void) strcpy(savename, tc_name);
203     while (st1 != string) {
204 	if (toshell && numbchars >= 1016) { /* leave room for ctrl and delim */
205 	   numbchars = 0;
206            printf(";\nsetenv MAP3270%c ", suffix++);
207 	}
208 	pchar = 0xff&(*st1++);
209 	switch (pchar) {
210 	case '"':
211 	case '!':
212 	case '$':
213 	case '(':
214 	case ')':
215 	case ' ':
216 	case ';':
217 	case '&':
218 	case '|':
219 	case '>':
220 	case '<':
221 	case '`':
222 	case '#':
223 	    numbchars += 2;
224 	    if (toshell) {
225 	       printf("%c%c", '\\', pchar);
226 	    }
227 	    else {
228 	       printf("%c", pchar);
229 	    }
230 	    break;
231 	case '\\':
232 	case '\'':
233 	    numbchars += 4;
234 	    if (toshell) {
235 	       printf("%c%c%c%c", '\\', '\\', '\\', pchar);
236 	    }
237 	    else {
238 	       printf("%c%c", '\\', pchar);
239 	    }
240 	    break;
241 	case '^':
242 	    numbchars += 3;
243 	    if (toshell) {
244 	       printf("%c%c%c", '\\', '\\', pchar);
245 	    }
246 	    else {
247 	       printf("%c%c", '\\', pchar);
248 	    }
249 	    break;
250 	default:
251 	    st2 = uncontrol(pchar);
252 	    while ((pchar = *st2++) != 0) {
253 		switch (pchar) {
254 		case '"':
255 		case '!':
256 		case '$':
257 		case '(':
258 		case ')':
259 		case ' ':
260 		case ';':
261 		case '&':
262 		case '|':
263 		case '>':
264 		case '<':
265 		case '`':
266 		case '#':
267 		case '\\':
268 		case '\'':
269 		   if (toshell) {
270 	    	      numbchars += 2;
271 	    	      printf("%c%c", '\\', pchar);
272 		   }
273 		   else {
274 		      printf("%c", pchar);
275 		   }
276 		   break;
277 		default:
278 		   numbchars++;
279 	    	   printf("%c", pchar);
280 		   break;
281 		}
282 	    }
283 	    break;
284 	}
285     }
286     numbchars += 2;
287     if (toshell) {
288        printf("%c'", '\\');
289     }
290     else {
291        printf("'");
292     }
293 }
294 
295 static void
296 recurse(strcount, head)
297 state *head;
298 int strcount;
299 {
300 		/*	if there is a left,
301 		 *	    recurse on left,
302 		 *	if there is no down,
303 		 *	    print the string to here
304 		 *	else,
305 		 *	     add the current match to the string,
306 		 *	     recurse.
307 		 *	exit.
308 		 */
309 
310     if (head->next) {
311 	recurse(strcount, head->next);
312     }
313     if (head->result != STATE_GOTO) {
314 	rptr->match_end = addString(strcount, head->match);
315 	rptr->result = astosc[head->result].name;
316 	rptr = doRegister(rptr);
317     } else {
318 	(void) addString(strcount, head->match);
319 	recurse(strcount+1, head->address);
320 	strcount--;
321     }
322     return;
323 }
324 
325 
326 main(argc, argv)
327 int argc;
328 char *argv[];
329 {
330     state *head;
331     char *keybdPointer = (char *) 0;
332     char *commandName = argv[0];
333     extern char *getenv();
334     int picky = 0;
335 
336     while ((argc > 1) && (argv[1][0] == '-')) {
337 	if (!strcmp(argv[1], "-picky")) {
338 	    picky++;
339 	} else if (!strcmp(argv[1], "-shell")) {
340 	    toshell++;
341 	} else {
342 	    fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
343 		commandName);
344 	    exit(1);
345 	    /*NOTREACHED*/
346 	}
347 	argv++;
348 	argc--;
349     }
350     if (argc == 2) {
351         keybdPointer = argv[1];
352     } else if (argc > 2) {
353 	fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
354 		commandName);
355 	exit(1);
356 	/*NOTREACHED*/
357     }
358     head = InitControl(keybdPointer, picky, ascii_to_index);
359     if (!head) {
360 	return(1);
361     }
362     if (keybdPointer == 0) {
363         keybdPointer = getenv("KEYBD");
364     }
365     if (keybdPointer == 0) {
366 	keybdPointer = getenv("TERM");
367     }
368     if (keybdPointer == 0) {
369 	keybdPointer = "3a";	/* use 3a as the terminal */
370     }
371     if (toshell) {
372        printf("set noglob;\nsetenv MAP3270 ");
373     }
374     printf("%s{", keybdPointer);
375     numbchars = 2 + strlen(keybdPointer);
376     /* now, run through the table registering entries */
377     rptr = regstates + 2;
378     recurse(0, head);
379     /* now print them out */
380     for (rptr = regstates[0].forward; rptr->result != 0;
381 	 rptr = rptr->forward) {
382 	printString(rptr->match_end, rptr->match_start, rptr->result);
383     }
384     if (toshell) {
385        printf("%c;};\nunset noglob;\n", '\\');
386     }
387     else {
388       printf(";}\n");
389     }
390     return(0);
391 }
392