xref: /original-bsd/usr.bin/tn3270/ascii/mset.c (revision 00986467)
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.3 (Berkeley) 06/29/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 "../api/astosc.h"
45 
46 #include "../general/globals.h"
47 #include "map3270.ext"
48 
49 struct regstate {
50 	char *result;
51 	char *match_start;
52 	char *match_end;		/* start of NEXT state's match string */
53 	struct regstate *forward;
54 	struct regstate *backward;
55 };
56 
57 static struct regstate regstates[500], *rptr= 0;	/* for sorting states */
58 static char array[5000];		/* lot's of room */
59 static int toshell = 0;			/* export to shell */
60 static int numbchars = 0;		/* number of chars in envir. var */
61 
62 static int
63 MyStrcmp(str1, str2)
64 char *str1, *str2;
65 {
66 	if (strncmp(str1, "PFK", 3) == 0 && strncmp(str2, "PFK", 3) == 0
67 	    && strlen(str1) != strlen(str2)) {
68 	   return(strlen(str1) - strlen(str2));
69 	}
70 	return(strcmp(str1, str2));
71 }
72 
73 static void
74 forwRegister(regptr, sptr)
75 struct regstate *regptr, *sptr;
76 {
77 
78     regptr->forward = sptr->forward;
79     regptr->backward = sptr;
80     (sptr->forward)->backward = regptr;
81     sptr->forward = regptr;
82 }
83 
84 static void
85 backRegister(regptr, sptr)
86 struct regstate *regptr, *sptr;
87 {
88 
89     regptr->forward = sptr;
90     regptr->backward = sptr->backward;
91     (sptr->backward)->forward = regptr;
92     sptr->backward = regptr;
93 }
94 
95 static struct regstate *
96 doRegister(regptr)
97 register struct regstate *regptr;
98 {
99     static struct regstate *pivot = regstates;
100     register struct regstate *sptr = pivot;
101     int check;
102 
103     if (pivot == regstates) {		/* first time called */
104 	pivot->forward = regptr;
105 	regptr->backward = pivot++;
106 	pivot->backward = regptr;
107 	regptr->forward = pivot++;
108 	return(++regptr);
109     }
110     if ((check = MyStrcmp(regptr->result, pivot->result)) < 0) {
111 	while (check < 0) {
112 	    if (sptr->backward == regstates) {
113 		backRegister(regptr, sptr);
114 		pivot = pivot->backward;
115 		return(++regptr);
116 	     }
117 	     sptr = sptr->backward;
118 	     check = MyStrcmp(regptr->result, sptr->result);
119 	}
120 	forwRegister(regptr, sptr);
121 	pivot = pivot->backward;
122 	return(++regptr);
123     }
124     while (check > 0) {
125 	if ((sptr->forward)->result == 0) {
126 	    forwRegister(regptr, sptr);
127     	    pivot = pivot->forward;
128 	    return(++regptr);
129 	}
130 	sptr = sptr->forward;
131 	check = MyStrcmp(regptr->result, sptr->result);
132     }
133     backRegister(regptr, sptr);
134     if (pivot->forward->result) {
135 	pivot = pivot->forward;
136     }
137     return(++regptr);
138 }
139 
140 static char *
141 addString(strcount, character)
142 int strcount;
143 char character;
144 {
145     static char *string = array;
146     int i;
147 
148     if (rptr->match_start == 0) {
149 	rptr->match_start = string;
150 	for (i=0; i < strcount; i++) {
151 	    *string++ = *((rptr-1)->match_start+i);
152 	}
153     }
154     *string++ = character;
155     return(string);
156 }
157 
158 static char savename[20] = " ";  /* for deciding if name is new */
159 
160 static void
161 printString(string, begin, tc_name)
162 register char *string;
163 char *begin, *tc_name;
164 {
165     register char *st1, *st2;
166     register int pchar;
167     static char suffix = 'A';
168     int new = strcmp(savename, tc_name);
169     char delim = new ? ';' : '|';
170     char *uncontrol();
171 
172     st1 = begin;
173 
174     numbchars += 5 + (new ? strlen(tc_name) : -1);
175     if (toshell && numbchars > 1011) {
176         new = 1;
177 	delim = ';';
178         numbchars = 5 + strlen(tc_name);
179         printf(";\nsetenv MAP3270%c ", suffix++);
180     }
181     if (strcmp(" ", savename)) {
182 	if (toshell) {
183 	   printf("%c%c", '\\', delim);
184 	}
185 	else {
186 	   printf("%c", delim);
187 	}
188     }
189     else {
190 	numbchars -= 2;
191     }
192     if (toshell && new) {
193         printf("%s=%c'", tc_name,'\\');
194     }
195     else if (new) {
196         printf("%s='", tc_name);
197     }
198     else if (toshell) {
199 	printf("%c'", '\\');
200     }
201     else {
202 	printf("'");
203     }
204     (void) strcpy(savename, tc_name);
205     while (st1 != string) {
206 	if (toshell && numbchars >= 1016) { /* leave room for ctrl and delim */
207 	   numbchars = 0;
208            printf(";\nsetenv MAP3270%c ", suffix++);
209 	}
210 	pchar = 0xff&(*st1++);
211 	switch (pchar) {
212 	case '"':
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 	    numbchars += 2;
226 	    if (toshell) {
227 	       printf("%c%c", '\\', pchar);
228 	    }
229 	    else {
230 	       printf("%c", pchar);
231 	    }
232 	    break;
233 	case '\\':
234 	case '\'':
235 	    numbchars += 4;
236 	    if (toshell) {
237 	       printf("%c%c%c%c", '\\', '\\', '\\', pchar);
238 	    }
239 	    else {
240 	       printf("%c%c", '\\', pchar);
241 	    }
242 	    break;
243 	case '^':
244 	    numbchars += 3;
245 	    if (toshell) {
246 	       printf("%c%c%c", '\\', '\\', pchar);
247 	    }
248 	    else {
249 	       printf("%c%c", '\\', pchar);
250 	    }
251 	    break;
252 	default:
253 	    st2 = uncontrol(pchar);
254 	    while ((pchar = *st2++) != 0) {
255 		switch (pchar) {
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 		case '\\':
270 		case '\'':
271 		   if (toshell) {
272 	    	      numbchars += 2;
273 	    	      printf("%c%c", '\\', pchar);
274 		   }
275 		   else {
276 		      printf("%c", pchar);
277 		   }
278 		   break;
279 		default:
280 		   numbchars++;
281 	    	   printf("%c", pchar);
282 		   break;
283 		}
284 	    }
285 	    break;
286 	}
287     }
288     numbchars += 2;
289     if (toshell) {
290        printf("%c'", '\\');
291     }
292     else {
293        printf("'");
294     }
295 }
296 
297 static void
298 recurse(strcount, head)
299 state *head;
300 int strcount;
301 {
302 		/*	if there is a left,
303 		 *	    recurse on left,
304 		 *	if there is no down,
305 		 *	    print the string to here
306 		 *	else,
307 		 *	     add the current match to the string,
308 		 *	     recurse.
309 		 *	exit.
310 		 */
311 
312     if (head->next) {
313 	recurse(strcount, head->next);
314     }
315     if (head->result != STATE_GOTO) {
316 	rptr->match_end = addString(strcount, head->match);
317 	rptr->result = astosc[head->result].name;
318 	rptr = doRegister(rptr);
319     } else {
320 	(void) addString(strcount, head->match);
321 	recurse(strcount+1, head->address);
322 	strcount--;
323     }
324     return;
325 }
326 
327 
328 main(argc, argv)
329 int argc;
330 char *argv[];
331 {
332     state *head;
333     char *keybdPointer = (char *) 0;
334     char *commandName = argv[0];
335     extern char *getenv();
336     int picky = 0;
337 
338     while ((argc > 1) && (argv[1][0] == '-')) {
339 	if (!strcmp(argv[1], "-picky")) {
340 	    picky++;
341 	} else if (!strcmp(argv[1], "-shell")) {
342 	    toshell++;
343 	} else {
344 	    fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
345 		commandName);
346 	    exit(1);
347 	    /*NOTREACHED*/
348 	}
349 	argv++;
350 	argc--;
351     }
352     if (argc == 2) {
353         keybdPointer = argv[1];
354     } else if (argc > 2) {
355 	fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
356 		commandName);
357 	exit(1);
358 	/*NOTREACHED*/
359     }
360     head = InitControl(keybdPointer, picky, ascii_to_index);
361     if (!head) {
362 	return(1);
363     }
364     if (keybdPointer == 0) {
365         keybdPointer = getenv("KEYBD");
366     }
367     if (keybdPointer == 0) {
368 	keybdPointer = getenv("TERM");
369     }
370     if (keybdPointer == 0) {
371 	keybdPointer = "3a";	/* use 3a as the terminal */
372     }
373     if (toshell) {
374        printf("set noglob;\nsetenv MAP3270 ");
375     }
376     printf("%s{", keybdPointer);
377     numbchars = 2 + strlen(keybdPointer);
378     /* now, run through the table registering entries */
379     rptr = regstates + 2;
380     recurse(0, head);
381     /* now print them out */
382     for (rptr = regstates[0].forward; rptr->result != 0;
383 	 rptr = rptr->forward) {
384 	printString(rptr->match_end, rptr->match_start, rptr->result);
385     }
386     if (toshell) {
387        printf("%c;};\nunset noglob;\n", '\\');
388     }
389     else {
390       printf(";}\n");
391     }
392     return(0);
393 }
394