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 * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3127648Scharnierstatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 361590Srgrimes#ifndef lint 3727648Scharnier#if 0 381590Srgrimesstatic char sccsid[] = "@(#)mkstr.c 8.1 (Berkeley) 6/6/93"; 3927648Scharnier#endif 401590Srgrimes#endif /* not lint */ 411590Srgrimes 4294503Scharnier#include <sys/cdefs.h> 4394503Scharnier__FBSDID("$FreeBSD$"); 4494503Scharnier 4527648Scharnier#include <err.h> 46106293Stjr#include <errno.h> 471590Srgrimes#include <stdio.h> 4827648Scharnier#include <stdlib.h> 4933648Sjb#include <string.h> 501590Srgrimes 511590Srgrimes#define ungetchar(c) ungetc(c, stdin) 521590Srgrimes 531590Srgrimes/* 541590Srgrimes * mkstr - create a string error message file by massaging C source 551590Srgrimes * 561590Srgrimes * Bill Joy UCB August 1977 571590Srgrimes * 581590Srgrimes * Modified March 1978 to hash old messages to be able to recompile 591590Srgrimes * without addding messages to the message file (usually) 601590Srgrimes * 611590Srgrimes * Based on an earlier program conceived by Bill Joy and Chuck Haley 621590Srgrimes * 631590Srgrimes * Program to create a string error message file 641590Srgrimes * from a group of C programs. Arguments are the name 651590Srgrimes * of the file where the strings are to be placed, the 661590Srgrimes * prefix of the new files where the processed source text 671590Srgrimes * is to be placed, and the files to be processed. 681590Srgrimes * 691590Srgrimes * The program looks for 'error("' in the source stream. 701590Srgrimes * Whenever it finds this, the following characters from the '"' 711590Srgrimes * to a '"' are replaced by 'seekpt' where seekpt is a 721590Srgrimes * pointer into the error message file. 731590Srgrimes * If the '(' is not immediately followed by a '"' no change occurs. 741590Srgrimes * 751590Srgrimes * The optional '-' causes strings to be added at the end of the 761590Srgrimes * existing error message file for recompilation of single routines. 771590Srgrimes */ 781590Srgrimes 791590SrgrimesFILE *mesgread, *mesgwrite; 801590Srgrimeschar name[100], *np; 811590Srgrimes 8292921Simpvoid copystr(void); 8392921Simpint fgetNUL(char *, int, FILE *); 8495642Smarkmunsigned hashit(char *, int, unsigned); 8592921Simpvoid inithash(void); 8692921Simpint match(const char *); 8792921Simpint octdigit(char); 8892921Simpvoid process(void); 8995642Smarkmvoid usage(void); 9027648Scharnier 9127648Scharnierint 9295642Smarkmmain(int argc, char *argv[]) 931590Srgrimes{ 941590Srgrimes char addon = 0; 95106293Stjr size_t namelen; 961590Srgrimes 9727648Scharnier argc--, argv++; 981590Srgrimes if (argc > 1 && argv[0][0] == '-') 991590Srgrimes addon++, argc--, argv++; 1001590Srgrimes if (argc < 3) 10127648Scharnier usage(); 1021590Srgrimes mesgwrite = fopen(argv[0], addon ? "a" : "w"); 1031590Srgrimes if (mesgwrite == NULL) 10427648Scharnier err(1, "%s", argv[0]); 1051590Srgrimes mesgread = fopen(argv[0], "r"); 1061590Srgrimes if (mesgread == NULL) 10727648Scharnier err(1, "%s", argv[0]); 1081590Srgrimes inithash(); 1091590Srgrimes argc--, argv++; 110106293Stjr namelen = strlcpy(name, argv[0], sizeof(name)); 111106293Stjr if (namelen >= sizeof(name)) { 112106293Stjr errno = ENAMETOOLONG; 113106293Stjr err(1, "%s", argv[0]); 114106293Stjr } 115106293Stjr np = name + namelen; 1161590Srgrimes argc--, argv++; 1171590Srgrimes do { 118106293Stjr if (strlcpy(np, argv[0], sizeof(name) - namelen) >= 119106293Stjr sizeof(name) - namelen) { 120106293Stjr errno = ENAMETOOLONG; 121106293Stjr err(1, "%s%s", name, argv[0]); 122106293Stjr } 1231590Srgrimes if (freopen(name, "w", stdout) == NULL) 12427648Scharnier err(1, "%s", name); 1251590Srgrimes if (freopen(argv[0], "r", stdin) == NULL) 12627648Scharnier err(1, "%s", argv[0]); 1271590Srgrimes process(); 1281590Srgrimes argc--, argv++; 1291590Srgrimes } while (argc > 0); 1301590Srgrimes exit(0); 1311590Srgrimes} 1321590Srgrimes 13395642Smarkmvoid 13495642Smarkmusage(void) 13527648Scharnier{ 13694503Scharnier fprintf(stderr, "usage: mkstr [-] mesgfile prefix file ...\n"); 13727648Scharnier exit(1); 13827648Scharnier} 13927648Scharnier 14027648Scharniervoid 14195642Smarkmprocess(void) 1421590Srgrimes{ 14387289Sdwmalone int c; 1441590Srgrimes 1451590Srgrimes for (;;) { 1461590Srgrimes c = getchar(); 1471590Srgrimes if (c == EOF) 1481590Srgrimes return; 1491590Srgrimes if (c != 'e') { 1501590Srgrimes putchar(c); 1511590Srgrimes continue; 1521590Srgrimes } 1531590Srgrimes if (match("error(")) { 1541590Srgrimes printf("error("); 1551590Srgrimes c = getchar(); 1561590Srgrimes if (c != '"') 1571590Srgrimes putchar(c); 1581590Srgrimes else 1591590Srgrimes copystr(); 1601590Srgrimes } 1611590Srgrimes } 1621590Srgrimes} 1631590Srgrimes 16427648Scharnierint 16595642Smarkmmatch(const char *ocp) 1661590Srgrimes{ 16787289Sdwmalone const char *cp; 16887289Sdwmalone int c; 1691590Srgrimes 1701590Srgrimes for (cp = ocp + 1; *cp; cp++) { 1711590Srgrimes c = getchar(); 1721590Srgrimes if (c != *cp) { 1731590Srgrimes while (ocp < cp) 1741590Srgrimes putchar(*ocp++); 1751590Srgrimes ungetchar(c); 1761590Srgrimes return (0); 1771590Srgrimes } 1781590Srgrimes } 1791590Srgrimes return (1); 1801590Srgrimes} 1811590Srgrimes 18227648Scharniervoid 18395642Smarkmcopystr(void) 1841590Srgrimes{ 18587289Sdwmalone int c, ch; 1861590Srgrimes char buf[512]; 18795642Smarkm char *cp = buf; 1881590Srgrimes 1891590Srgrimes for (;;) { 190106294Stjr if (cp == buf + sizeof(buf) - 2) 191106294Stjr errx(1, "message too long"); 1921590Srgrimes c = getchar(); 1931590Srgrimes if (c == EOF) 1941590Srgrimes break; 1951590Srgrimes switch (c) { 1961590Srgrimes 1971590Srgrimes case '"': 1981590Srgrimes *cp++ = 0; 1991590Srgrimes goto out; 2001590Srgrimes case '\\': 2011590Srgrimes c = getchar(); 2021590Srgrimes switch (c) { 2031590Srgrimes 2041590Srgrimes case 'b': 2051590Srgrimes c = '\b'; 2061590Srgrimes break; 2071590Srgrimes case 't': 2081590Srgrimes c = '\t'; 2091590Srgrimes break; 2101590Srgrimes case 'r': 2111590Srgrimes c = '\r'; 2121590Srgrimes break; 2131590Srgrimes case 'n': 2141590Srgrimes c = '\n'; 2151590Srgrimes break; 2161590Srgrimes case '\n': 2171590Srgrimes continue; 2181590Srgrimes case 'f': 2191590Srgrimes c = '\f'; 2201590Srgrimes break; 2211590Srgrimes case '0': 2221590Srgrimes c = 0; 2231590Srgrimes break; 2241590Srgrimes case '\\': 2251590Srgrimes break; 2261590Srgrimes default: 2271590Srgrimes if (!octdigit(c)) 2281590Srgrimes break; 2291590Srgrimes c -= '0'; 2301590Srgrimes ch = getchar(); 2311590Srgrimes if (!octdigit(ch)) 2321590Srgrimes break; 2331590Srgrimes c <<= 7, c += ch - '0'; 2341590Srgrimes ch = getchar(); 2351590Srgrimes if (!octdigit(ch)) 2361590Srgrimes break; 2371590Srgrimes c <<= 3, c+= ch - '0', ch = -1; 2381590Srgrimes break; 2391590Srgrimes } 2401590Srgrimes } 2411590Srgrimes *cp++ = c; 2421590Srgrimes } 2431590Srgrimesout: 2441590Srgrimes *cp = 0; 245126960Sbde printf("%d", hashit(buf, 1, 0)); 2461590Srgrimes} 2471590Srgrimes 24827648Scharnierint 24995642Smarkmoctdigit(char c) 2501590Srgrimes{ 2511590Srgrimes 2521590Srgrimes return (c >= '0' && c <= '7'); 2531590Srgrimes} 2541590Srgrimes 25527648Scharniervoid 25695642Smarkminithash(void) 2571590Srgrimes{ 2581590Srgrimes char buf[512]; 2591590Srgrimes int mesgpt = 0; 2601590Srgrimes 2611590Srgrimes rewind(mesgread); 26227648Scharnier while (fgetNUL(buf, sizeof buf, mesgread) != 0) { 2631590Srgrimes hashit(buf, 0, mesgpt); 2641590Srgrimes mesgpt += strlen(buf) + 2; 2651590Srgrimes } 2661590Srgrimes} 2671590Srgrimes 2681590Srgrimes#define NBUCKETS 511 2691590Srgrimes 2701590Srgrimesstruct hash { 2711590Srgrimes long hval; 2721590Srgrimes unsigned hpt; 2731590Srgrimes struct hash *hnext; 2741590Srgrimes} *bucket[NBUCKETS]; 2751590Srgrimes 27627648Scharnierunsigned 27795642Smarkmhashit(char *str, int really, unsigned fakept) 2781590Srgrimes{ 2791590Srgrimes int i; 28095642Smarkm struct hash *hp; 2811590Srgrimes char buf[512]; 2821590Srgrimes long hashval = 0; 28395642Smarkm char *cp; 2841590Srgrimes 2851590Srgrimes if (really) 2861590Srgrimes fflush(mesgwrite); 2871590Srgrimes for (cp = str; *cp;) 2881590Srgrimes hashval = (hashval << 1) + *cp++; 2891590Srgrimes i = hashval % NBUCKETS; 2901590Srgrimes if (i < 0) 2911590Srgrimes i += NBUCKETS; 2921590Srgrimes if (really != 0) 2931590Srgrimes for (hp = bucket[i]; hp != 0; hp = hp->hnext) 2941590Srgrimes if (hp->hval == hashval) { 2951590Srgrimes fseek(mesgread, (long) hp->hpt, 0); 2961590Srgrimes fgetNUL(buf, sizeof buf, mesgread); 2971590Srgrimes/* 2981590Srgrimes fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf); 2991590Srgrimes*/ 3001590Srgrimes if (strcmp(buf, str) == 0) 3011590Srgrimes break; 3021590Srgrimes } 3031590Srgrimes if (!really || hp == 0) { 3041590Srgrimes hp = (struct hash *) calloc(1, sizeof *hp); 30594503Scharnier if (hp == NULL) 30694503Scharnier err(1, NULL); 3071590Srgrimes hp->hnext = bucket[i]; 3081590Srgrimes hp->hval = hashval; 3091590Srgrimes hp->hpt = really ? ftell(mesgwrite) : fakept; 3101590Srgrimes if (really) { 3111590Srgrimes fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite); 3121590Srgrimes fwrite("\n", sizeof (char), 1, mesgwrite); 3131590Srgrimes } 3141590Srgrimes bucket[i] = hp; 3151590Srgrimes } 3161590Srgrimes/* 3171590Srgrimes fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt); 3181590Srgrimes*/ 3191590Srgrimes return (hp->hpt); 3201590Srgrimes} 3211590Srgrimes 32227648Scharnierint 32395642SmarkmfgetNUL(char *obuf, int rmdr, FILE *file) 3241590Srgrimes{ 32587289Sdwmalone int c; 32695642Smarkm char *buf = obuf; 3271590Srgrimes 3281590Srgrimes while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF) 3291590Srgrimes *buf++ = c; 3301590Srgrimes *buf++ = 0; 3311590Srgrimes getc(file); 33227648Scharnier return ((feof(file) || ferror(file)) ? 0 : 1); 3331590Srgrimes} 334