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 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 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 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 * 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 * 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 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 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 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