1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1999 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Copyright (c) 1999, by Sun Microsystems, Inc. 32 * All rights reserved. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /* 38 * University Copyright- Copyright (c) 1982, 1986, 1988 39 * The Regents of the University of California 40 * All Rights Reserved 41 * 42 * University Acknowledgment- Portions of this document are derived from 43 * software developed by the University of California, Berkeley, and its 44 * contributors. 45 */ 46 47 #include <stdio.h> 48 #include <ctype.h> 49 #include <sys/types.h> 50 #include <signal.h> 51 #include <stdlib.h> 52 53 /* 54 * xstr - extract and hash strings in a C program 55 */ 56 57 #define ignore(a) Ignore((char *) a) 58 59 off_t tellpt; 60 off_t hashit(); 61 void onintr(); 62 char *savestr(); 63 char *strcat(); 64 char *strcpy(); 65 off_t yankstr(); 66 void cleanup(void); 67 68 off_t mesgpt; 69 char *strings = "strings"; 70 71 int cflg; 72 int vflg; 73 int readstd; 74 int tmpfd; 75 76 main(argc, argv) 77 int argc; 78 char *argv[]; 79 { 80 81 argc--, argv++; 82 while (argc > 0 && argv[0][0] == '-') { 83 register char *cp = &(*argv++)[1]; 84 85 argc--; 86 if (*cp == 0) { 87 readstd++; 88 continue; 89 } 90 do switch (*cp++) { 91 92 case 'c': 93 cflg++; 94 continue; 95 96 case 'v': 97 vflg++; 98 continue; 99 100 default: 101 fprintf(stderr, 102 "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n"); 103 } while (*cp); 104 } 105 if (signal(SIGINT, SIG_IGN) == SIG_DFL) 106 signal(SIGINT, onintr); 107 if (cflg || argc == 0 && !readstd) 108 inithash(); 109 else { 110 strings = savestr("/tmp/xstrXXXXXX"); 111 tmpfd = mkstemp(strings); 112 if (tmpfd == -1) { 113 perror(strings); 114 (void) free(strings); 115 exit(9); 116 } 117 (void) close(tmpfd); 118 } 119 while (readstd || argc > 0) { 120 if (freopen("x.c", "w", stdout) == NULL) 121 perror("x.c"), (void) cleanup(), exit(1); 122 if (!readstd && freopen(argv[0], "r", stdin) == NULL) 123 perror(argv[0]), (void) cleanup(), exit(2); 124 process("x.c"); 125 if (readstd == 0) 126 argc--, argv++; 127 else 128 readstd = 0; 129 }; 130 flushsh(); 131 if (cflg == 0) 132 xsdotc(); 133 (void) cleanup(); 134 exit(0); 135 } 136 137 process(name) 138 char *name; 139 { 140 char *cp; 141 char linebuf[BUFSIZ]; 142 register int c; 143 register int incomm = 0; 144 145 printf("extern\tchar\txstr[];\n"); 146 for (;;) { 147 if (fgets(linebuf, sizeof (linebuf), stdin) == NULL) { 148 if (ferror(stdin)) { 149 perror(name); 150 (void) cleanup(); 151 exit(3); 152 } 153 break; 154 } 155 if (linebuf[0] == '#') { 156 if (linebuf[1] == ' ' && isdigit(linebuf[2])) 157 printf("#line%s", &linebuf[1]); 158 else 159 printf("%s", linebuf); 160 continue; 161 } 162 for (cp = linebuf; c = *cp++; ) { 163 switch (c) { 164 case '"': 165 if (incomm) 166 goto def; 167 printf("(&xstr[%d])", 168 (int) yankstr(&cp)); 169 break; 170 171 case '\'': 172 if (incomm) 173 goto def; 174 putchar(c); 175 if (*cp) 176 putchar(*cp++); 177 break; 178 179 case '/': 180 if (incomm || *cp != '*') 181 goto def; 182 incomm = 1; 183 cp++; 184 printf("/*"); 185 continue; 186 187 case '*': 188 if (incomm && *cp == '/') { 189 incomm = 0; 190 cp++; 191 printf("*/"); 192 continue; 193 } 194 goto def; 195 def: 196 default: 197 putchar(c); 198 break; 199 } 200 } 201 } 202 if (ferror(stdout)) 203 perror("x.c"), onintr(); 204 } 205 206 off_t 207 yankstr(cpp) 208 register char **cpp; 209 { 210 register char *cp = *cpp; 211 register int c, ch; 212 char dbuf[BUFSIZ]; 213 register char *dp = dbuf; 214 register char *tp; 215 216 while (c = *cp++) { 217 switch (c) { 218 219 case '"': 220 cp++; 221 goto out; 222 223 case '\\': 224 c = *cp++; 225 if (c == 0) 226 break; 227 if (c == '\n') 228 continue; 229 for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++) 230 if (c == ch) { 231 c = *tp; 232 goto gotc; 233 } 234 if (!octdigit(c)) { 235 *dp++ = '\\'; 236 break; 237 } 238 c -= '0'; 239 if (!octdigit(*cp)) 240 break; 241 c <<= 3, c += *cp++ - '0'; 242 if (!octdigit(*cp)) 243 break; 244 c <<= 3, c += *cp++ - '0'; 245 break; 246 } 247 gotc: 248 *dp++ = c; 249 } 250 out: 251 *cpp = --cp; 252 *dp = 0; 253 return (hashit(dbuf, 1)); 254 } 255 256 octdigit(c) 257 char c; 258 { 259 260 return (isdigit(c) && c != '8' && c != '9'); 261 } 262 263 inithash() 264 { 265 char buf[BUFSIZ]; 266 register FILE *mesgread = fopen(strings, "r"); 267 268 if (mesgread == NULL) 269 return; 270 for (;;) { 271 mesgpt = tellpt; 272 if (fgetNUL(buf, sizeof (buf), mesgread) == NULL) 273 break; 274 ignore(hashit(buf, 0)); 275 } 276 ignore(fclose(mesgread)); 277 } 278 279 fgetNUL(obuf, rmdr, file) 280 char *obuf; 281 register int rmdr; 282 FILE *file; 283 { 284 register c; 285 register char *buf = obuf; 286 287 while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF) 288 *buf++ = c; 289 *buf++ = 0; 290 return ((feof(file) || ferror(file)) ? NULL : 1); 291 } 292 293 xgetc(file) 294 FILE *file; 295 { 296 297 tellpt++; 298 return (getc(file)); 299 } 300 301 #define BUCKETS 128 302 303 struct hash { 304 off_t hpt; 305 char *hstr; 306 struct hash *hnext; 307 short hnew; 308 } bucket[BUCKETS]; 309 310 off_t 311 hashit(str, new) 312 char *str; 313 int new; 314 { 315 int i; 316 register struct hash *hp, *hp0; 317 318 hp = hp0 = &bucket[lastchr(str) & 0177]; 319 while (hp->hnext) { 320 hp = hp->hnext; 321 i = istail(str, hp->hstr); 322 if (i >= 0) 323 return (hp->hpt + i); 324 } 325 hp = (struct hash *) calloc(1, sizeof (*hp)); 326 hp->hpt = mesgpt; 327 hp->hstr = savestr(str); 328 mesgpt += strlen(hp->hstr) + 1; 329 hp->hnext = hp0->hnext; 330 hp->hnew = new; 331 hp0->hnext = hp; 332 return (hp->hpt); 333 } 334 335 flushsh() 336 { 337 register int i; 338 register struct hash *hp; 339 register FILE *mesgwrit; 340 register int old = 0, new = 0; 341 342 for (i = 0; i < BUCKETS; i++) 343 for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) 344 if (hp->hnew) 345 new++; 346 else 347 old++; 348 if (new == 0 && old != 0) 349 return; 350 mesgwrit = fopen(strings, old ? "r+" : "w"); 351 for (i = 0; i < BUCKETS; i++) 352 for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) { 353 found(hp->hnew, hp->hpt, hp->hstr); 354 if (hp->hnew) { 355 fseek(mesgwrit, hp->hpt, 0); 356 ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 357 1, mesgwrit)); 358 if (ferror(mesgwrit)) { 359 perror(strings); 360 (void) cleanup(); 361 exit(4); 362 } 363 } 364 } 365 ignore(fclose(mesgwrit)); 366 } 367 368 found(new, off, str) 369 int new; 370 off_t off; 371 char *str; 372 { 373 374 if (vflg == 0) 375 return; 376 if (!new) 377 fprintf(stderr, "found at %d:", (int) off); 378 else 379 fprintf(stderr, "new at %d:", (int) off); 380 prstr(str); 381 fprintf(stderr, "\n"); 382 } 383 384 prstr(cp) 385 register char *cp; 386 { 387 register int c; 388 389 while (c = (*cp++ & 0377)) 390 if (c < ' ') 391 fprintf(stderr, "^%c", c + '`'); 392 else if (c == 0177) 393 fprintf(stderr, "^?"); 394 else if (c > 0200) 395 fprintf(stderr, "\\%03o", c); 396 else 397 fprintf(stderr, "%c", c); 398 } 399 400 xsdotc() 401 { 402 register FILE *strf = fopen(strings, "r"); 403 register FILE *xdotcf; 404 405 if (strf == NULL) 406 perror(strings), exit(5); 407 xdotcf = fopen("xs.c", "w"); 408 if (xdotcf == NULL) 409 perror("xs.c"), exit(6); 410 fprintf(xdotcf, "char\txstr[] = {\n"); 411 for (;;) { 412 register int i, c; 413 414 for (i = 0; i < 8; i++) { 415 c = getc(strf); 416 if (ferror(strf)) { 417 perror(strings); 418 onintr(); 419 } 420 if (feof(strf)) { 421 fprintf(xdotcf, "\n"); 422 goto out; 423 } 424 fprintf(xdotcf, "0x%02x,", c); 425 } 426 fprintf(xdotcf, "\n"); 427 } 428 out: 429 fprintf(xdotcf, "};\n"); 430 ignore(fclose(xdotcf)); 431 ignore(fclose(strf)); 432 } 433 434 char * 435 savestr(cp) 436 register char *cp; 437 { 438 register char *dp = (char *) calloc(1, strlen(cp) + 1); 439 440 return (strcpy(dp, cp)); 441 } 442 443 Ignore(a) 444 char *a; 445 { 446 447 a = a; 448 } 449 450 ignorf(a) 451 int (*a)(); 452 { 453 454 a = a; 455 } 456 457 lastchr(cp) 458 register char *cp; 459 { 460 461 while (cp[0] && cp[1]) 462 cp++; 463 return (*cp); 464 } 465 466 istail(str, of) 467 register char *str, *of; 468 { 469 register int d = strlen(of) - strlen(str); 470 471 if (d < 0 || strcmp(&of[d], str) != 0) 472 return (-1); 473 return (d); 474 } 475 476 void 477 onintr() 478 { 479 480 ignorf(signal(SIGINT, SIG_IGN)); 481 (void) cleanup(); 482 ignore(unlink("x.c")); 483 ignore(unlink("xs.c")); 484 exit(7); 485 } 486 void 487 cleanup(void) 488 { 489 if (strings[0] == '/') { 490 ignore(unlink(strings)); 491 } 492 } 493