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