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