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