xstr.c revision 28855
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3528855Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4128855Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)xstr.c 8.1 (Berkeley) 6/9/93"; 4328855Scharnier#endif 4428855Scharnierstatic const char rcsid[] = 4528855Scharnier "$Id$"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes#include <sys/types.h> 4928855Scharnier#include <ctype.h> 5028855Scharnier#include <err.h> 5128855Scharnier#include <stdio.h> 5228855Scharnier#include <stdlib.h> 531590Srgrimes#include <signal.h> 5428855Scharnier#include <string.h> 551590Srgrimes#include <unistd.h> 561590Srgrimes#include "pathnames.h" 571590Srgrimes 581590Srgrimes/* 591590Srgrimes * xstr - extract and hash strings in a C program 601590Srgrimes * 611590Srgrimes * Bill Joy UCB 621590Srgrimes * November, 1978 631590Srgrimes */ 641590Srgrimes 651590Srgrimes#define ignore(a) ((void) a) 661590Srgrimes 671590Srgrimesoff_t tellpt; 681590Srgrimesoff_t hashit(); 691590Srgrimesvoid onintr(); 701590Srgrimeschar *savestr(); 711590Srgrimesoff_t yankstr(); 721590Srgrimes 731590Srgrimesoff_t mesgpt; 741590Srgrimeschar *strings = "strings"; 751590Srgrimes 761590Srgrimesint cflg; 771590Srgrimesint vflg; 781590Srgrimesint readstd; 791590Srgrimes 8028855Scharnierstatic void usage __P((void)); 8128855Scharnierint istail __P((char *, char *)); 8228855Scharnierchar lastchr __P((char *)); 8328855Scharniervoid xsdotc __P((void)); 8428855Scharniervoid prstr __P((char *)); 8528855Scharniervoid found __P((int, off_t, char *)); 8628855Scharniervoid flushsh __P((void)); 8728855Scharnierint xgetc __P((FILE *)); 8828855Scharnierint fgetNUL __P((char *, int, FILE *)); 8928855Scharniervoid inithash __P((void)); 9028855Scharnierint octdigit __P((char)); 9128855Scharniervoid process __P((char *)); 9228855Scharnier 9328855Scharnierint 941590Srgrimesmain(argc, argv) 951590Srgrimes int argc; 961590Srgrimes char *argv[]; 971590Srgrimes{ 9828855Scharnier int c; 991590Srgrimes 10028855Scharnier while ((c = getopt(argc, argv, "-cv")) != -1) 10128855Scharnier switch (c) { 10228855Scharnier case '-': 1031590Srgrimes readstd++; 10428855Scharnier break; 1051590Srgrimes case 'c': 1061590Srgrimes cflg++; 10728855Scharnier break; 1081590Srgrimes case 'v': 1091590Srgrimes vflg++; 11028855Scharnier break; 1111590Srgrimes default: 11228855Scharnier usage(); 11328855Scharnier } 11428855Scharnier argc -= optind; 11528855Scharnier argv += optind; 11628855Scharnier 1171590Srgrimes if (signal(SIGINT, SIG_IGN) == SIG_DFL) 1181590Srgrimes signal(SIGINT, onintr); 11928855Scharnier if (cflg || (argc == 0 && !readstd)) 1201590Srgrimes inithash(); 1211590Srgrimes else 1221590Srgrimes strings = mktemp(strdup(_PATH_TMP)); 1231590Srgrimes while (readstd || argc > 0) { 1241590Srgrimes if (freopen("x.c", "w", stdout) == NULL) 12528855Scharnier err(1, "x.c"); 1261590Srgrimes if (!readstd && freopen(argv[0], "r", stdin) == NULL) 12728855Scharnier err(2, "%s", argv[0]); 1281590Srgrimes process("x.c"); 1291590Srgrimes if (readstd == 0) 1301590Srgrimes argc--, argv++; 1311590Srgrimes else 1321590Srgrimes readstd = 0; 1331590Srgrimes }; 1341590Srgrimes flushsh(); 1351590Srgrimes if (cflg == 0) 1361590Srgrimes xsdotc(); 1371590Srgrimes if (strings[0] == '/') 1381590Srgrimes ignore(unlink(strings)); 1391590Srgrimes exit(0); 1401590Srgrimes} 1411590Srgrimes 14228855Scharnierstatic void 14328855Scharnierusage() 14428855Scharnier{ 14528855Scharnier fprintf(stderr, "usage: xstr [-v] [-c] [-] [name ...]\n"); 14628855Scharnier exit (1); 14728855Scharnier} 14828855Scharnier 1491590Srgrimeschar linebuf[BUFSIZ]; 1501590Srgrimes 15128855Scharniervoid 1521590Srgrimesprocess(name) 1531590Srgrimes char *name; 1541590Srgrimes{ 1551590Srgrimes char *cp; 1561590Srgrimes register int c; 1571590Srgrimes register int incomm = 0; 1581590Srgrimes int ret; 1591590Srgrimes 1601590Srgrimes printf("extern char\txstr[];\n"); 1611590Srgrimes for (;;) { 1621590Srgrimes if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { 16328855Scharnier if (ferror(stdin)) 16428855Scharnier err(3, "%s", name); 1651590Srgrimes break; 1661590Srgrimes } 1671590Srgrimes if (linebuf[0] == '#') { 1681590Srgrimes if (linebuf[1] == ' ' && isdigit(linebuf[2])) 1691590Srgrimes printf("#line%s", &linebuf[1]); 1701590Srgrimes else 1711590Srgrimes printf("%s", linebuf); 1721590Srgrimes continue; 1731590Srgrimes } 17428855Scharnier for (cp = linebuf; (c = *cp++);) switch (c) { 1758874Srgrimes 1761590Srgrimes case '"': 1771590Srgrimes if (incomm) 1781590Srgrimes goto def; 1791590Srgrimes if ((ret = (int) yankstr(&cp)) == -1) 1801590Srgrimes goto out; 1811590Srgrimes printf("(&xstr[%d])", ret); 1821590Srgrimes break; 1831590Srgrimes 1841590Srgrimes case '\'': 1851590Srgrimes if (incomm) 1861590Srgrimes goto def; 1871590Srgrimes putchar(c); 1881590Srgrimes if (*cp) 1891590Srgrimes putchar(*cp++); 1901590Srgrimes break; 1911590Srgrimes 1921590Srgrimes case '/': 1931590Srgrimes if (incomm || *cp != '*') 1941590Srgrimes goto def; 1951590Srgrimes incomm = 1; 1961590Srgrimes cp++; 1971590Srgrimes printf("/*"); 1981590Srgrimes continue; 1991590Srgrimes 2001590Srgrimes case '*': 2011590Srgrimes if (incomm && *cp == '/') { 2021590Srgrimes incomm = 0; 2031590Srgrimes cp++; 2041590Srgrimes printf("*/"); 2051590Srgrimes continue; 2061590Srgrimes } 2071590Srgrimes goto def; 2088874Srgrimes 2091590Srgrimesdef: 2101590Srgrimes default: 2111590Srgrimes putchar(c); 2121590Srgrimes break; 2131590Srgrimes } 2141590Srgrimes } 2151590Srgrimesout: 2161590Srgrimes if (ferror(stdout)) 21728855Scharnier warn("x.c"), onintr(); 2181590Srgrimes} 2191590Srgrimes 2201590Srgrimesoff_t 2211590Srgrimesyankstr(cpp) 2221590Srgrimes register char **cpp; 2231590Srgrimes{ 2241590Srgrimes register char *cp = *cpp; 2251590Srgrimes register int c, ch; 2261590Srgrimes char dbuf[BUFSIZ]; 2271590Srgrimes register char *dp = dbuf; 2281590Srgrimes register char *tp; 2291590Srgrimes 23028855Scharnier while ((c = *cp++)) { 2311590Srgrimes switch (c) { 2321590Srgrimes 2331590Srgrimes case '"': 2341590Srgrimes cp++; 2351590Srgrimes goto out; 2361590Srgrimes 2371590Srgrimes case '\\': 2381590Srgrimes c = *cp++; 2391590Srgrimes if (c == 0) 2401590Srgrimes break; 2411590Srgrimes if (c == '\n') { 2428874Srgrimes if (fgets(linebuf, sizeof linebuf, stdin) 2431590Srgrimes == NULL) { 24428855Scharnier if (ferror(stdin)) 24528855Scharnier err(3, "x.c"); 2461590Srgrimes return(-1); 2471590Srgrimes } 2481590Srgrimes cp = linebuf; 2491590Srgrimes continue; 2501590Srgrimes } 25128855Scharnier for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; (ch = *tp++); tp++) 2521590Srgrimes if (c == ch) { 2531590Srgrimes c = *tp; 2541590Srgrimes goto gotc; 2551590Srgrimes } 2561590Srgrimes if (!octdigit(c)) { 2571590Srgrimes *dp++ = '\\'; 2581590Srgrimes break; 2591590Srgrimes } 2601590Srgrimes c -= '0'; 2611590Srgrimes if (!octdigit(*cp)) 2621590Srgrimes break; 2631590Srgrimes c <<= 3, c += *cp++ - '0'; 2641590Srgrimes if (!octdigit(*cp)) 2651590Srgrimes break; 2661590Srgrimes c <<= 3, c += *cp++ - '0'; 2671590Srgrimes break; 2681590Srgrimes } 2691590Srgrimesgotc: 2701590Srgrimes *dp++ = c; 2711590Srgrimes } 2721590Srgrimesout: 2731590Srgrimes *cpp = --cp; 2741590Srgrimes *dp = 0; 2751590Srgrimes return (hashit(dbuf, 1)); 2761590Srgrimes} 2771590Srgrimes 27828855Scharnierint 2791590Srgrimesoctdigit(c) 2801590Srgrimes char c; 2811590Srgrimes{ 2821590Srgrimes return (isdigit(c) && c != '8' && c != '9'); 2831590Srgrimes} 2841590Srgrimes 28528855Scharniervoid 2861590Srgrimesinithash() 2871590Srgrimes{ 2881590Srgrimes char buf[BUFSIZ]; 2891590Srgrimes register FILE *mesgread = fopen(strings, "r"); 2901590Srgrimes 2911590Srgrimes if (mesgread == NULL) 2921590Srgrimes return; 2931590Srgrimes for (;;) { 2941590Srgrimes mesgpt = tellpt; 29528855Scharnier if (fgetNUL(buf, sizeof buf, mesgread) == 0) 2961590Srgrimes break; 2971590Srgrimes ignore(hashit(buf, 0)); 2981590Srgrimes } 2991590Srgrimes ignore(fclose(mesgread)); 3001590Srgrimes} 3011590Srgrimes 30228855Scharnierint 3031590SrgrimesfgetNUL(obuf, rmdr, file) 3041590Srgrimes char *obuf; 3051590Srgrimes register int rmdr; 3061590Srgrimes FILE *file; 3071590Srgrimes{ 3081590Srgrimes register c; 3091590Srgrimes register char *buf = obuf; 3101590Srgrimes 3111590Srgrimes while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF) 3121590Srgrimes *buf++ = c; 3131590Srgrimes *buf++ = 0; 31428855Scharnier return ((feof(file) || ferror(file)) ? 0 : 1); 3151590Srgrimes} 3161590Srgrimes 31728855Scharnierint 3181590Srgrimesxgetc(file) 3191590Srgrimes FILE *file; 3201590Srgrimes{ 3211590Srgrimes 3221590Srgrimes tellpt++; 3231590Srgrimes return (getc(file)); 3241590Srgrimes} 3251590Srgrimes 3261590Srgrimes#define BUCKETS 128 3271590Srgrimes 3281590Srgrimesstruct hash { 3291590Srgrimes off_t hpt; 3301590Srgrimes char *hstr; 3311590Srgrimes struct hash *hnext; 3321590Srgrimes short hnew; 3331590Srgrimes} bucket[BUCKETS]; 3341590Srgrimes 3351590Srgrimesoff_t 3361590Srgrimeshashit(str, new) 3371590Srgrimes char *str; 3381590Srgrimes int new; 3391590Srgrimes{ 3401590Srgrimes int i; 3411590Srgrimes register struct hash *hp, *hp0; 3421590Srgrimes 3431590Srgrimes hp = hp0 = &bucket[lastchr(str) & 0177]; 3441590Srgrimes while (hp->hnext) { 3451590Srgrimes hp = hp->hnext; 3461590Srgrimes i = istail(str, hp->hstr); 3471590Srgrimes if (i >= 0) 3481590Srgrimes return (hp->hpt + i); 3491590Srgrimes } 35028855Scharnier if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) 35128855Scharnier errx(8, "calloc"); 3521590Srgrimes hp->hpt = mesgpt; 35328855Scharnier if (!(hp->hstr = strdup(str))) 35428855Scharnier err(1, NULL); 3551590Srgrimes mesgpt += strlen(hp->hstr) + 1; 3561590Srgrimes hp->hnext = hp0->hnext; 3571590Srgrimes hp->hnew = new; 3581590Srgrimes hp0->hnext = hp; 3591590Srgrimes return (hp->hpt); 3601590Srgrimes} 3611590Srgrimes 36228855Scharniervoid 3631590Srgrimesflushsh() 3641590Srgrimes{ 3651590Srgrimes register int i; 3661590Srgrimes register struct hash *hp; 3671590Srgrimes register FILE *mesgwrit; 3681590Srgrimes register int old = 0, new = 0; 3691590Srgrimes 3701590Srgrimes for (i = 0; i < BUCKETS; i++) 3711590Srgrimes for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) 3721590Srgrimes if (hp->hnew) 3731590Srgrimes new++; 3741590Srgrimes else 3751590Srgrimes old++; 3761590Srgrimes if (new == 0 && old != 0) 3771590Srgrimes return; 3781590Srgrimes mesgwrit = fopen(strings, old ? "r+" : "w"); 3791590Srgrimes if (mesgwrit == NULL) 3801590Srgrimes perror(strings), exit(4); 3811590Srgrimes for (i = 0; i < BUCKETS; i++) 3821590Srgrimes for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) { 3831590Srgrimes found(hp->hnew, hp->hpt, hp->hstr); 3841590Srgrimes if (hp->hnew) { 3851590Srgrimes fseek(mesgwrit, hp->hpt, 0); 3861590Srgrimes ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit)); 3871590Srgrimes if (ferror(mesgwrit)) 38828855Scharnier err(4, "%s", strings); 3891590Srgrimes } 3901590Srgrimes } 3911590Srgrimes if (fclose(mesgwrit) == EOF) 39228855Scharnier err(4, "%s", strings); 3931590Srgrimes} 3941590Srgrimes 39528855Scharniervoid 3961590Srgrimesfound(new, off, str) 3971590Srgrimes int new; 3981590Srgrimes off_t off; 3991590Srgrimes char *str; 4001590Srgrimes{ 4011590Srgrimes if (vflg == 0) 4021590Srgrimes return; 4031590Srgrimes if (!new) 4041590Srgrimes fprintf(stderr, "found at %d:", (int) off); 4051590Srgrimes else 4061590Srgrimes fprintf(stderr, "new at %d:", (int) off); 4071590Srgrimes prstr(str); 4081590Srgrimes fprintf(stderr, "\n"); 4091590Srgrimes} 4101590Srgrimes 41128855Scharniervoid 4121590Srgrimesprstr(cp) 4131590Srgrimes register char *cp; 4141590Srgrimes{ 4151590Srgrimes register int c; 4161590Srgrimes 41728855Scharnier while ((c = (*cp++ & 0377))) 4181590Srgrimes if (c < ' ') 4191590Srgrimes fprintf(stderr, "^%c", c + '`'); 4201590Srgrimes else if (c == 0177) 4211590Srgrimes fprintf(stderr, "^?"); 4221590Srgrimes else if (c > 0200) 4231590Srgrimes fprintf(stderr, "\\%03o", c); 4241590Srgrimes else 4251590Srgrimes fprintf(stderr, "%c", c); 4261590Srgrimes} 4271590Srgrimes 42828855Scharniervoid 4291590Srgrimesxsdotc() 4301590Srgrimes{ 4311590Srgrimes register FILE *strf = fopen(strings, "r"); 4321590Srgrimes register FILE *xdotcf; 4331590Srgrimes 4341590Srgrimes if (strf == NULL) 43528855Scharnier err(5, "%s", strings); 4361590Srgrimes xdotcf = fopen("xs.c", "w"); 4371590Srgrimes if (xdotcf == NULL) 43828855Scharnier err(6, "xs.c"); 4391590Srgrimes fprintf(xdotcf, "char\txstr[] = {\n"); 4401590Srgrimes for (;;) { 4411590Srgrimes register int i, c; 4421590Srgrimes 4431590Srgrimes for (i = 0; i < 8; i++) { 4441590Srgrimes c = getc(strf); 4451590Srgrimes if (ferror(strf)) { 44628855Scharnier warn("%s", strings); 4471590Srgrimes onintr(); 4481590Srgrimes } 4491590Srgrimes if (feof(strf)) { 4501590Srgrimes fprintf(xdotcf, "\n"); 4511590Srgrimes goto out; 4521590Srgrimes } 4531590Srgrimes fprintf(xdotcf, "0x%02x,", c); 4541590Srgrimes } 4551590Srgrimes fprintf(xdotcf, "\n"); 4561590Srgrimes } 4571590Srgrimesout: 4581590Srgrimes fprintf(xdotcf, "};\n"); 4591590Srgrimes ignore(fclose(xdotcf)); 4601590Srgrimes ignore(fclose(strf)); 4611590Srgrimes} 4621590Srgrimes 46328855Scharnierchar 4641590Srgrimeslastchr(cp) 4651590Srgrimes register char *cp; 4661590Srgrimes{ 4671590Srgrimes 4681590Srgrimes while (cp[0] && cp[1]) 4691590Srgrimes cp++; 4701590Srgrimes return (*cp); 4711590Srgrimes} 4721590Srgrimes 47328855Scharnierint 4741590Srgrimesistail(str, of) 4751590Srgrimes register char *str, *of; 4761590Srgrimes{ 4771590Srgrimes register int d = strlen(of) - strlen(str); 4781590Srgrimes 4791590Srgrimes if (d < 0 || strcmp(&of[d], str) != 0) 4801590Srgrimes return (-1); 4811590Srgrimes return (d); 4821590Srgrimes} 4831590Srgrimes 4841590Srgrimesvoid 4851590Srgrimesonintr() 4861590Srgrimes{ 4871590Srgrimes 4881590Srgrimes ignore(signal(SIGINT, SIG_IGN)); 4891590Srgrimes if (strings[0] == '/') 4901590Srgrimes ignore(unlink(strings)); 4911590Srgrimes ignore(unlink("x.c")); 4921590Srgrimes ignore(unlink("xs.c")); 4931590Srgrimes exit(7); 4941590Srgrimes} 495