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