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