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 * Copyright 1992 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 /* from UCB 4.1 10/01/80 */ 28 #include <stdio.h> 29 #include <locale.h> 30 31 #define ungetchar(c) ungetc(c, stdin) 32 33 long ftell(); 34 char *calloc(); 35 /* 36 * mkstr - create a string error message file by massaging C source 37 * 38 * Bill Joy UCB August 1977 39 * 40 * Modified March 1978 to hash old messages to be able to recompile 41 * without addding messages to the message file (usually) 42 * 43 * Based on an earlier program conceived by Bill Joy and Chuck Haley 44 * 45 * Program to create a string error message file 46 * from a group of C programs. Arguments are the name 47 * of the file where the strings are to be placed, the 48 * prefix of the new files where the processed source text 49 * is to be placed, and the files to be processed. 50 * 51 * The program looks for 'error("' in the source stream. 52 * Whenever it finds this, the following characters from the '"' 53 * to a '"' are replaced by 'seekpt' where seekpt is a 54 * pointer into the error message file. 55 * If the '(' is not immediately followed by a '"' no change occurs. 56 * 57 * The optional '-' causes strings to be added at the end of the 58 * existing error message file for recompilation of single routines. 59 */ 60 61 62 FILE *mesgread, *mesgwrite; 63 char *progname; 64 char usagestr[] = "usage: %s [ - ] mesgfile prefix file ...\n"; 65 char name[100], *np; 66 67 main(argc, argv) 68 int argc; 69 char *argv[]; 70 { 71 char addon = 0; 72 73 (void) setlocale(LC_ALL, ""); 74 75 #if !defined(TEXT_DOMAIN) 76 #define TEXT_DOMAIN "SYS_TEST" 77 #endif 78 (void) textdomain(TEXT_DOMAIN); 79 80 argc--, progname = *argv++; 81 if (argc > 1 && argv[0][0] == '-') 82 addon++, argc--, argv++; 83 if (argc < 3) 84 fprintf(stderr, gettext(usagestr), progname), exit(1); 85 mesgwrite = fopen(argv[0], addon ? "a" : "w"); 86 if (mesgwrite == NULL) 87 perror(argv[0]), exit(1); 88 mesgread = fopen(argv[0], "r"); 89 if (mesgread == NULL) 90 perror(argv[0]), exit(1); 91 inithash(); 92 argc--, argv++; 93 strcpy(name, argv[0]); 94 np = name + strlen(name); 95 argc--, argv++; 96 do { 97 strcpy(np, argv[0]); 98 if (freopen(name, "w", stdout) == NULL) 99 perror(name), exit(1); 100 if (freopen(argv[0], "r", stdin) == NULL) 101 perror(argv[0]), exit(1); 102 process(); 103 argc--, argv++; 104 } while (argc > 0); 105 exit(0); 106 /* NOTREACHED */ 107 } 108 109 process() 110 { 111 register char *cp; 112 register c; 113 114 for (;;) { 115 c = getchar(); 116 if (c == EOF) 117 return; 118 if (c != 'e') { 119 putchar(c); 120 continue; 121 } 122 if (match("error(")) { 123 printf(gettext("error(")); 124 c = getchar(); 125 if (c != '"') 126 putchar(c); 127 else 128 copystr(); 129 } 130 } 131 } 132 133 match(ocp) 134 char *ocp; 135 { 136 register char *cp; 137 register c; 138 139 for (cp = ocp + 1; *cp; cp++) { 140 c = getchar(); 141 if (c != *cp) { 142 while (ocp < cp) 143 putchar(*ocp++); 144 ungetchar(c); 145 return (0); 146 } 147 } 148 return (1); 149 } 150 151 copystr() 152 { 153 register c, ch; 154 char buf[512]; 155 register char *cp = buf; 156 157 for (;;) { 158 c = getchar(); 159 if (c == EOF) 160 break; 161 switch (c) { 162 163 case '"': 164 *cp++ = 0; 165 goto out; 166 case '\\': 167 c = getchar(); 168 switch (c) { 169 170 case 'b': 171 c = '\b'; 172 break; 173 case 't': 174 c = '\t'; 175 break; 176 case 'r': 177 c = '\r'; 178 break; 179 case 'n': 180 c = '\n'; 181 break; 182 case '\n': 183 continue; 184 case 'f': 185 c = '\f'; 186 break; 187 case '0': 188 c = 0; 189 break; 190 case '\\': 191 break; 192 default: 193 if (!octdigit(c)) 194 break; 195 c -= '0'; 196 ch = getchar(); 197 if (!octdigit(ch)) 198 break; 199 c <<= 7, c += ch - '0'; 200 ch = getchar(); 201 if (!octdigit(ch)) 202 break; 203 c <<= 3, c+= ch - '0', ch = -1; 204 break; 205 } 206 } 207 *cp++ = c; 208 } 209 out: 210 *cp = 0; 211 printf("%d", hashit(buf, 1, NULL)); 212 } 213 214 octdigit(c) 215 char c; 216 { 217 218 return (c >= '0' && c <= '7'); 219 } 220 221 inithash() 222 { 223 char buf[512]; 224 int mesgpt = 0; 225 226 rewind(mesgread); 227 while (fgetNUL(buf, sizeof buf, mesgread) != NULL) { 228 hashit(buf, 0, mesgpt); 229 mesgpt += strlen(buf) + 2; 230 } 231 } 232 233 #define NBUCKETS 511 234 235 struct hash { 236 long hval; 237 unsigned hpt; 238 struct hash *hnext; 239 } *bucket[NBUCKETS]; 240 241 hashit(str, really, fakept) 242 char *str; 243 char really; 244 unsigned fakept; 245 { 246 int i; 247 register struct hash *hp; 248 char buf[512]; 249 long hashval = 0; 250 register char *cp; 251 252 if (really) 253 fflush(mesgwrite); 254 for (cp = str; *cp;) 255 hashval = (hashval << 1) + *cp++; 256 i = hashval % NBUCKETS; 257 if (i < 0) 258 i += NBUCKETS; 259 if (really != 0) 260 for (hp = bucket[i]; hp != 0; hp = hp->hnext) 261 if (hp->hval == hashval) { 262 fseek(mesgread, (long) hp->hpt, 0); 263 fgetNUL(buf, sizeof buf, mesgread); 264 /* 265 fprintf(stderr, gettext("Got (from %d) %s\n"), hp->hpt, buf); 266 */ 267 if (strcmp(buf, str) == 0) 268 break; 269 } 270 if (!really || hp == 0) { 271 hp = (struct hash *) calloc(1, sizeof *hp); 272 hp->hnext = bucket[i]; 273 hp->hval = hashval; 274 hp->hpt = really ? ftell(mesgwrite) : fakept; 275 if (really) { 276 fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite); 277 fwrite("\n", sizeof (char), 1, mesgwrite); 278 } 279 bucket[i] = hp; 280 } 281 /* 282 fprintf(stderr, gettext("%s hashed to %ld at %d\n"), str, hp->hval, hp->hpt); 283 */ 284 return (hp->hpt); 285 } 286 287 #include <sys/types.h> 288 #include <sys/stat.h> 289 290 fgetNUL(obuf, rmdr, file) 291 char *obuf; 292 register int rmdr; 293 FILE *file; 294 { 295 register c; 296 register char *buf = obuf; 297 298 while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF) 299 *buf++ = c; 300 *buf++ = 0; 301 getc(file); 302 return ((feof(file) || ferror(file)) ? NULL : 1); 303 } 304