1: /* 2: * Produce a set of preprocessor defines which guarantee that all identifiers 3: * in the files are unique in the first symlen (default 7) characters. 4: * Include the output into each file (or into a common header file). Since 5: * the symbols being redefined are ambiguous within symlen chars (that was the 6: * problem in the first place), the files must be compiled using a flexnames 7: * version of cpp. 8: * 9: * Lacking that, turn the output into a sed script and massage the source 10: * files. In this case, you may need to specify -p to parse preprocessor 11: * lines, but watch for things like include-file names. If using cpp, 12: * preprocessor symbols should be weeded out by hand; otherwise they will 13: * cause (innocuous) redefinition messages. 14: * 15: * Hacked by m.d. marquez to allow pipe into stdin and add -s (sed) option. 16: */ 17: 18: #if !defined(lint) && !defined(pdp11) 19: static char rcsid[] = 20: "$Header: shortc.c,v 1.2 88/09/06 01:30:58 bin Exp Locker: bin $"; 21: #endif 22: 23: #include <stdio.h> 24: #include <ctype.h> 25: #include <strings.h> 26: 27: #define SYMLEN 7 /* symbols must be unique within ... chars */ 28: #define MAXLEN 128 /* need a limit for tokenizing */ 29: #define HASHSIZ 512 /* power of 2; not an upper limit */ 30: 31: typedef struct Symbol symbol; 32: struct Symbol { 33: symbol *link; /* hash chain */ 34: union { 35: char *xprefix; /* prefix for mapped name if flag > SEEN */ 36: symbol *xtrunc; /* symbol which truncates to this one 37: if flag == TRUNC */ 38: } x; 39: char flag; 40: char inname[1]; 41: }; 42: #define prefix x.xprefix 43: #define trunc x.xtrunc 44: #define NOTSEEN 0 /* symbol never seen */ 45: #define TRUNC 1 /* trunc points to symbol which truncates to 46: this one */ 47: #define SEEN 2 /* there is no conflict with this symbol */ 48: /* > SEEN */ /* prefix must be added to resolve conflict */ 49: 50: symbol *symtab[HASHSIZ]; 51: 52: int symlen = SYMLEN; 53: char parsepp; /* if set, parse preprocessor lines */ 54: int sedout = 0; /* want sed output */ 55: int read_file = 0; /* flag if read file arguments */ 56: 57: symbol *lookup(); 58: char *token(), *truncname(), *curarg = "stdin"; 59: char *myalloc(); 60: 61: extern char *malloc(); 62: extern int errno; 63: 64: /* 65: * entry point 66: */ 67: main(argc, argv) 68: register argc; 69: register char **argv; 70: { 71: char obuf[BUFSIZ]; 72: 73: setbuf(stdout, obuf); 74: 75: while (--argc > 0) 76: doarg(*++argv); 77: 78: if (!read_file) 79: process(); 80: 81: dump(); 82: exit(0); 83: } 84: 85: /* 86: * process one file or flag arg 87: */ 88: doarg(arg) 89: char *arg; 90: { 91: char ibuf[BUFSIZ]; 92: 93: if (*arg == '-') { 94: arg++; 95: if (isdigit(*arg)) 96: symlen = atoi(arg); 97: else if (*arg == 'p') 98: parsepp = 1; 99: else if (*arg == 's') 100: sedout = 1; 101: else { 102: fputs("usage: shortc [-symlen] [-s] [-p] file ...\n", stderr); 103: exit(1); 104: } 105: return; 106: } 107: 108: if (freopen(arg, "r", stdin) == NULL) { 109: fprintf(stderr, "freopen(%s) err: %d\n", errno); 110: return; 111: } 112: setbuf(stdin, ibuf); 113: 114: curarg = arg; 115: process(); 116: 117: read_file++; 118: } 119: 120: process() 121: { 122: register char *s; 123: register symbol *y; 124: 125: while (s = token()) 126: if ((y = lookup(s))->flag < SEEN) 127: newname(y); 128: } 129: 130: /* 131: * pick a new non-colliding name 132: */ 133: newname(y) 134: register symbol *y; 135: { 136: register symbol *a; 137: 138: /* repeat until no collision */ 139: for (;;) { 140: /* pick another name */ 141: nextname(y); 142: /* check its truncation for conflicts */ 143: a = lookup(truncname(y)); 144: if (a->flag == NOTSEEN) 145: break; 146: /* 147: * if this is an original symbol and it collides with another 148: * (maybe modified) symbol, fix the other one instead of this one 149: */ 150: if (a->flag == TRUNC && y->flag == SEEN) { 151: newname(a->trunc); 152: break; 153: } 154: /* if already a short name, ok */ 155: if (a == y) 156: return; 157: } 158: /* flag what this truncates to */ 159: a->trunc = y; 160: a->flag = TRUNC; 161: } 162: 163: /* 164: * find next possible name for this symbol 165: */ 166: nextname(y) 167: register symbol *y; 168: { 169: register char *s, *p; 170: register n; 171: 172: switch (y->flag) { 173: case TRUNC: 174: /* if another symbol truncates to this one, fix it not to */ 175: newname(y->trunc); 176: case NOTSEEN: 177: /* this symbol's name is available, so use it */ 178: y->flag = SEEN; 179: return; 180: } 181: /* prefix++ in base 26 */ 182: for (n = y->flag-SEEN, p = y->prefix, s = p+n; s > p; *s = 'A') 183: if (++*--s <= 'Z') /* love that syntax */ 184: return; 185: 186: /* overflow; need new digit */ 187: y->prefix = s = myalloc(n+2); 188: *s++ = 'A'; 189: if (y->flag++ == SEEN) 190: *s = '\0'; 191: else { 192: strcpy(s, p); 193: free(p); 194: } 195: } 196: 197: /* 198: * return symbol name truncated to symlen chars 199: */ 200: char * 201: truncname(y) 202: register symbol *y; 203: { 204: static char buf[MAXLEN+10]; 205: register n = y->flag-SEEN; 206: 207: /* 208: * sprintf(buf, "%.*s%.*s", n, y->prefix, symlen-n, y->inname); 209: */ 210: 211: strncpy(buf, y->prefix, n); 212: buf[n] = '\0'; 213: strncat(buf, y->inname, symlen - n); 214: 215: return buf; 216: } 217: 218: /* 219: * find name in symbol table 220: */ 221: symbol * 222: lookup(s) 223: char *s; 224: { 225: register h; 226: 227: { 228: register char *p; 229: register c; 230: 231: for (h = 0, p = s; (c = *p++);) 232: h += h + c; 233: } 234: { 235: register symbol *y, **yy; 236: 237: for (y = *(yy = &symtab[h & HASHSIZ-1]);; y = y->link) { 238: if (!y) { 239: y = (symbol *)myalloc(sizeof *y + strlen(s)); 240: strcpy(y->inname, s); 241: y->flag = NOTSEEN; 242: y->link = *yy; 243: *yy = y; 244: break; 245: } 246: 247: if (strcmp(y->inname, s) == 0) 248: break; 249: } 250: return y; 251: } 252: } 253: 254: /* 255: * output all mappings 256: */ 257: dump() 258: { 259: register symbol *y; 260: register n; 261: 262: for (n = HASHSIZ; --n >= 0;) 263: for (y = symtab[n]; y; y = y->link) 264: if (y->flag > SEEN) { 265: if (sedout) 266: printf("/%s/s//%s%s/g\n", y->inname, 267: y->prefix, y->inname); 268: else 269: printf("#define %s %s%s\n", y->inname, 270: y->prefix, y->inname); 271: } 272: } 273: 274: /* 275: * return next interesting identifier 276: */ 277: char * 278: token() 279: { 280: register c, state = 0; 281: register char *p; 282: static char buf[MAXLEN+1]; 283: 284: for (p = buf; (c = getchar()) != EOF;) { 285: if (state) 286: switch (state) { 287: case '/': 288: if (c != '*') { 289: state = 0; 290: break; 291: } 292: state = c; 293: continue; 294: 295: case 'S': 296: if (c == '/') 297: state = 0; 298: else 299: state = '*'; 300: case '*': 301: if (c == state) 302: state = 'S'; 303: continue; 304: 305: default: 306: if (c == '\\') 307: (void) getchar(); 308: else if (c == state) 309: state = 0; 310: continue; 311: } 312: if (isalnum(c) || c == '_') { 313: if (p < &buf[sizeof buf - 1]) 314: *p++ = c; 315: continue; 316: } 317: if (p > buf) { 318: if (p-buf >= symlen && !isdigit(*buf)) { 319: *p = '\0'; 320: ungetc(c, stdin); 321: return buf; 322: } 323: p = buf; 324: } 325: if (c == '"' || c == '\'' || c == '/') 326: state = c; 327: else if (c == '#' && !parsepp) 328: state = '\n'; 329: } 330: return NULL; 331: } 332: 333: /* 334: * malloc with error detection 335: */ 336: char * 337: myalloc(n) 338: { 339: register char *p; 340: 341: if (!(p = malloc((unsigned)n))) { 342: fprintf(stderr, "Out of space in %s\n", curarg); 343: exit(1); 344: } 345: return p; 346: }