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