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