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