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