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