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