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