1 1.30 joe /* $NetBSD: mkheaders.c,v 1.30 2025/01/07 14:21:11 joe Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.1 thorpej * Copyright (c) 1992, 1993 5 1.1 thorpej * The Regents of the University of California. All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * This software was developed by the Computer Systems Engineering group 8 1.1 thorpej * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 1.1 thorpej * contributed to Berkeley. 10 1.1 thorpej * 11 1.1 thorpej * All advertising materials mentioning features or use of this software 12 1.1 thorpej * must display the following acknowledgement: 13 1.1 thorpej * This product includes software developed by the University of 14 1.1 thorpej * California, Lawrence Berkeley Laboratories. 15 1.1 thorpej * 16 1.1 thorpej * Redistribution and use in source and binary forms, with or without 17 1.1 thorpej * modification, are permitted provided that the following conditions 18 1.1 thorpej * are met: 19 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 20 1.1 thorpej * notice, this list of conditions and the following disclaimer. 21 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 22 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 23 1.1 thorpej * documentation and/or other materials provided with the distribution. 24 1.1 thorpej * 3. Neither the name of the University nor the names of its contributors 25 1.1 thorpej * may be used to endorse or promote products derived from this software 26 1.1 thorpej * without specific prior written permission. 27 1.1 thorpej * 28 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 1.1 thorpej * SUCH DAMAGE. 39 1.1 thorpej * 40 1.1 thorpej * from: @(#)mkheaders.c 8.1 (Berkeley) 6/6/93 41 1.1 thorpej */ 42 1.1 thorpej 43 1.1 thorpej #if HAVE_NBTOOL_CONFIG_H 44 1.1 thorpej #include "nbtool_config.h" 45 1.1 thorpej #endif 46 1.1 thorpej 47 1.22 christos #include <sys/cdefs.h> 48 1.30 joe __RCSID("$NetBSD: mkheaders.c,v 1.30 2025/01/07 14:21:11 joe Exp $"); 49 1.22 christos 50 1.1 thorpej #include <sys/param.h> 51 1.1 thorpej #include <ctype.h> 52 1.1 thorpej #include <errno.h> 53 1.1 thorpej #include <stdio.h> 54 1.1 thorpej #include <stdlib.h> 55 1.1 thorpej #include <string.h> 56 1.1 thorpej #include <time.h> 57 1.6 christos #include <util.h> 58 1.10 christos #include <err.h> 59 1.1 thorpej #include "defs.h" 60 1.1 thorpej 61 1.7 dsl #include <crc_extern.h> 62 1.7 dsl 63 1.1 thorpej static int emitcnt(struct nvlist *); 64 1.1 thorpej static int emitopts(void); 65 1.1 thorpej static int emittime(void); 66 1.1 thorpej static int herr(const char *, const char *, FILE *); 67 1.21 dholland static int defopts_print(const char *, struct defoptlist *, void *); 68 1.1 thorpej static char *cntname(const char *); 69 1.1 thorpej 70 1.12 dsl /* 71 1.12 dsl * We define a global symbol with the name of each option and its value. 72 1.12 dsl * This should stop code compiled with different options being linked together. 73 1.12 dsl */ 74 1.12 dsl 75 1.12 dsl /* Unlikely constant for undefined options */ 76 1.15 lukem #define UNDEFINED ('n' << 24 | 0 << 20 | 't' << 12 | 0xdefU) 77 1.12 dsl /* Value for defined options with value UNDEFINED */ 78 1.15 lukem #define DEFINED (0xdef1U << 16 | 'n' << 8 | 0xed) 79 1.7 dsl 80 1.1 thorpej /* 81 1.1 thorpej * Make the various config-generated header files. 82 1.1 thorpej */ 83 1.1 thorpej int 84 1.1 thorpej mkheaders(void) 85 1.1 thorpej { 86 1.1 thorpej struct files *fi; 87 1.1 thorpej 88 1.1 thorpej /* 89 1.1 thorpej * Make headers containing counts, as needed. 90 1.1 thorpej */ 91 1.1 thorpej TAILQ_FOREACH(fi, &allfiles, fi_next) { 92 1.1 thorpej if (fi->fi_flags & FI_HIDDEN) 93 1.1 thorpej continue; 94 1.1 thorpej if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) && 95 1.1 thorpej emitcnt(fi->fi_optf)) 96 1.1 thorpej return (1); 97 1.1 thorpej } 98 1.1 thorpej 99 1.16 cube if (emitopts() || emitlocs() || emitioconfh()) 100 1.16 cube return (1); 101 1.16 cube 102 1.16 cube /* 103 1.16 cube * If the minimum required version is ever bumped beyond 20090513, 104 1.16 cube * emittime() can be removed. 105 1.16 cube */ 106 1.16 cube if (version <= 20090513 && emittime()) 107 1.1 thorpej return (1); 108 1.1 thorpej 109 1.1 thorpej return (0); 110 1.1 thorpej } 111 1.1 thorpej 112 1.9 dsl static void 113 1.14 christos fprint_global(FILE *fp, const char *name, long long value) 114 1.7 dsl { 115 1.12 dsl /* 116 1.12 dsl * We have to doubt the founding fathers here. 117 1.12 dsl * The gas syntax for hppa is 'var .equ value', for all? other 118 1.12 dsl * instruction sets it is ' .equ var,value'. both have been used in 119 1.12 dsl * various assemblers, but supporting a common syntax would be good. 120 1.12 dsl * Fortunately we can use .equiv since it has a consistent syntax, 121 1.12 dsl * but requires us to detect multiple assignments - event with the 122 1.12 dsl * same value. 123 1.12 dsl */ 124 1.9 dsl fprintf(fp, "#ifdef _LOCORE\n" 125 1.12 dsl " .ifndef _KERNEL_OPT_%s\n" 126 1.7 dsl " .global _KERNEL_OPT_%s\n" 127 1.14 christos " .equiv _KERNEL_OPT_%s,0x%llx\n" 128 1.12 dsl " .endif\n" 129 1.7 dsl "#else\n" 130 1.12 dsl "__asm(\" .ifndef _KERNEL_OPT_%s\\n" 131 1.12 dsl " .global _KERNEL_OPT_%s\\n" 132 1.14 christos " .equiv _KERNEL_OPT_%s,0x%llx\\n" 133 1.12 dsl " .endif\");\n" 134 1.7 dsl "#endif\n", 135 1.12 dsl name, name, name, value, 136 1.12 dsl name, name, name, value); 137 1.7 dsl } 138 1.7 dsl 139 1.7 dsl /* Convert the option argument to a 32bit numder */ 140 1.7 dsl static unsigned int 141 1.7 dsl global_hash(const char *str) 142 1.7 dsl { 143 1.24 christos unsigned long h; 144 1.7 dsl char *ep; 145 1.7 dsl 146 1.24 christos /* 147 1.24 christos * If the value is a valid numeric, just use it 148 1.24 christos * We don't care about negative values here, we 149 1.24 christos * just use the value as a hash. 150 1.24 christos */ 151 1.7 dsl h = strtoul(str, &ep, 0); 152 1.7 dsl if (*ep != 0) 153 1.7 dsl /* Otherwise shove through a 32bit CRC function */ 154 1.7 dsl h = crc_buf(0, str, strlen(str)); 155 1.7 dsl 156 1.7 dsl /* Avoid colliding with the value used for undefined options. */ 157 1.7 dsl /* At least until I stop any options being set to zero */ 158 1.22 christos return (unsigned int)(h != UNDEFINED ? h : DEFINED); 159 1.7 dsl } 160 1.1 thorpej 161 1.9 dsl static void 162 1.1 thorpej fprintcnt(FILE *fp, struct nvlist *nv) 163 1.1 thorpej { 164 1.7 dsl const char *name = cntname(nv->nv_name); 165 1.7 dsl 166 1.14 christos fprintf(fp, "#define\t%s\t%lld\n", name, nv->nv_num); 167 1.14 christos fprint_global(fp, name, nv->nv_num); 168 1.1 thorpej } 169 1.1 thorpej 170 1.1 thorpej static int 171 1.1 thorpej emitcnt(struct nvlist *head) 172 1.1 thorpej { 173 1.1 thorpej char nfname[BUFSIZ], tfname[BUFSIZ]; 174 1.1 thorpej struct nvlist *nv; 175 1.1 thorpej FILE *fp; 176 1.1 thorpej 177 1.1 thorpej (void)snprintf(nfname, sizeof(nfname), "%s.h", head->nv_name); 178 1.1 thorpej (void)snprintf(tfname, sizeof(tfname), "tmp_%s", nfname); 179 1.1 thorpej 180 1.1 thorpej if ((fp = fopen(tfname, "w")) == NULL) 181 1.1 thorpej return (herr("open", tfname, NULL)); 182 1.1 thorpej 183 1.1 thorpej for (nv = head; nv != NULL; nv = nv->nv_next) 184 1.9 dsl fprintcnt(fp, nv); 185 1.9 dsl 186 1.9 dsl fflush(fp); 187 1.9 dsl if (ferror(fp)) 188 1.9 dsl return herr("writ", tfname, fp); 189 1.1 thorpej 190 1.1 thorpej if (fclose(fp) == EOF) 191 1.1 thorpej return (herr("clos", tfname, NULL)); 192 1.1 thorpej 193 1.1 thorpej return (moveifchanged(tfname, nfname)); 194 1.1 thorpej } 195 1.1 thorpej 196 1.1 thorpej /* 197 1.1 thorpej * Output a string, preceded by a tab and possibly unescaping any quotes. 198 1.1 thorpej * The argument will be output as is if it doesn't start with \". 199 1.1 thorpej * Otherwise the first backslash in a \? sequence will be dropped. 200 1.1 thorpej */ 201 1.9 dsl static void 202 1.1 thorpej fprintstr(FILE *fp, const char *str) 203 1.1 thorpej { 204 1.1 thorpej 205 1.10 christos if (strncmp(str, "\\\"", 2) != 0) { 206 1.10 christos (void)fprintf(fp, "\t%s", str); 207 1.9 dsl return; 208 1.9 dsl } 209 1.1 thorpej 210 1.10 christos (void)fputc('\t', fp); 211 1.30 joe 212 1.9 dsl for (; *str; str++) { 213 1.1 thorpej switch (*str) { 214 1.1 thorpej case '\\': 215 1.1 thorpej if (!*++str) /* XXX */ 216 1.1 thorpej str--; 217 1.10 christos /*FALLTHROUGH*/ 218 1.1 thorpej default: 219 1.10 christos (void)fputc(*str, fp); 220 1.1 thorpej break; 221 1.1 thorpej } 222 1.1 thorpej } 223 1.1 thorpej } 224 1.1 thorpej 225 1.1 thorpej /* 226 1.1 thorpej * Callback function for walking the option file hash table. We write out 227 1.1 thorpej * the options defined for this file. 228 1.1 thorpej */ 229 1.1 thorpej static int 230 1.10 christos /*ARGSUSED*/ 231 1.21 dholland defopts_print(const char *name, struct defoptlist *value, void *arg) 232 1.1 thorpej { 233 1.1 thorpej char tfname[BUFSIZ]; 234 1.21 dholland struct nvlist *option; 235 1.21 dholland struct defoptlist *dl; 236 1.7 dsl const char *opt_value; 237 1.1 thorpej int isfsoption; 238 1.1 thorpej FILE *fp; 239 1.1 thorpej 240 1.1 thorpej (void)snprintf(tfname, sizeof(tfname), "tmp_%s", name); 241 1.1 thorpej if ((fp = fopen(tfname, "w")) == NULL) 242 1.1 thorpej return (herr("open", tfname, NULL)); 243 1.1 thorpej 244 1.21 dholland for (dl = value; dl != NULL; dl = dl->dl_next) { 245 1.21 dholland isfsoption = OPT_FSOPT(dl->dl_name); 246 1.1 thorpej 247 1.21 dholland if (dl->dl_obsolete) { 248 1.9 dsl fprintf(fp, "/* %s `%s' is obsolete */\n", 249 1.1 thorpej isfsoption ? "file system" : "option", 250 1.21 dholland dl->dl_name); 251 1.21 dholland fprint_global(fp, dl->dl_name, 0xdeadbeef); 252 1.7 dsl continue; 253 1.7 dsl } 254 1.7 dsl 255 1.21 dholland if (((option = ht_lookup(opttab, dl->dl_name)) == NULL && 256 1.21 dholland (option = ht_lookup(fsopttab, dl->dl_name)) == NULL) && 257 1.21 dholland (dl->dl_value == NULL)) { 258 1.9 dsl fprintf(fp, "/* %s `%s' not defined */\n", 259 1.7 dsl isfsoption ? "file system" : "option", 260 1.21 dholland dl->dl_name); 261 1.21 dholland fprint_global(fp, dl->dl_name, UNDEFINED); 262 1.7 dsl continue; 263 1.1 thorpej } 264 1.7 dsl 265 1.21 dholland opt_value = option != NULL ? option->nv_str : dl->dl_value; 266 1.7 dsl if (isfsoption == 1) 267 1.7 dsl /* For filesysteme we'd output the lower case name */ 268 1.7 dsl opt_value = NULL; 269 1.7 dsl 270 1.21 dholland fprintf(fp, "#define\t%s", dl->dl_name); 271 1.9 dsl if (opt_value != NULL) 272 1.9 dsl fprintstr(fp, opt_value); 273 1.13 cube else if (!isfsoption) 274 1.13 cube fprintstr(fp, "1"); 275 1.9 dsl fputc('\n', fp); 276 1.21 dholland fprint_global(fp, dl->dl_name, 277 1.9 dsl opt_value == NULL ? 1 : global_hash(opt_value)); 278 1.1 thorpej } 279 1.1 thorpej 280 1.9 dsl fflush(fp); 281 1.9 dsl if (ferror(fp)) 282 1.9 dsl return herr("writ", tfname, fp); 283 1.9 dsl 284 1.1 thorpej if (fclose(fp) == EOF) 285 1.1 thorpej return (herr("clos", tfname, NULL)); 286 1.1 thorpej 287 1.1 thorpej return (moveifchanged(tfname, name)); 288 1.1 thorpej } 289 1.1 thorpej 290 1.1 thorpej /* 291 1.1 thorpej * Emit the option header files. 292 1.1 thorpej */ 293 1.1 thorpej static int 294 1.1 thorpej emitopts(void) 295 1.1 thorpej { 296 1.1 thorpej 297 1.21 dholland return (dlhash_enumerate(optfiletab, defopts_print, NULL)); 298 1.1 thorpej } 299 1.1 thorpej 300 1.1 thorpej /* 301 1.1 thorpej * A callback function for walking the attribute hash table. 302 1.1 thorpej * Emit CPP definitions of manifest constants for the locators on the 303 1.1 thorpej * "name" attribute node (passed as the "value" parameter). 304 1.1 thorpej */ 305 1.1 thorpej static int 306 1.1 thorpej locators_print(const char *name, void *value, void *arg) 307 1.1 thorpej { 308 1.1 thorpej struct attr *a; 309 1.19 dholland struct loclist *ll; 310 1.1 thorpej int i; 311 1.1 thorpej char *locdup, *namedup; 312 1.1 thorpej char *cp; 313 1.1 thorpej FILE *fp = arg; 314 1.1 thorpej 315 1.1 thorpej a = value; 316 1.1 thorpej if (a->a_locs) { 317 1.1 thorpej if (strchr(name, ' ') != NULL || strchr(name, '\t') != NULL) 318 1.1 thorpej /* 319 1.1 thorpej * name contains a space; we can't generate 320 1.1 thorpej * usable defines, so ignore it. 321 1.1 thorpej */ 322 1.1 thorpej return 0; 323 1.1 thorpej locdup = estrdup(name); 324 1.1 thorpej for (cp = locdup; *cp; cp++) 325 1.1 thorpej if (islower((unsigned char)*cp)) 326 1.25 joerg *cp = (char)toupper((unsigned char)*cp); 327 1.19 dholland for (i = 0, ll = a->a_locs; ll; ll = ll->ll_next, i++) { 328 1.19 dholland if (strchr(ll->ll_name, ' ') != NULL || 329 1.19 dholland strchr(ll->ll_name, '\t') != NULL) 330 1.1 thorpej /* 331 1.1 thorpej * name contains a space; we can't generate 332 1.1 thorpej * usable defines, so ignore it. 333 1.1 thorpej */ 334 1.1 thorpej continue; 335 1.19 dholland namedup = estrdup(ll->ll_name); 336 1.1 thorpej for (cp = namedup; *cp; cp++) 337 1.1 thorpej if (islower((unsigned char)*cp)) 338 1.25 joerg *cp = (char)toupper((unsigned char)*cp); 339 1.1 thorpej else if (*cp == ARRCHR) 340 1.1 thorpej *cp = '_'; 341 1.9 dsl fprintf(fp, "#define %sCF_%s %d\n", locdup, namedup, i); 342 1.19 dholland if (ll->ll_string != NULL) 343 1.9 dsl fprintf(fp, "#define %sCF_%s_DEFAULT %s\n", 344 1.19 dholland locdup, namedup, ll->ll_string); 345 1.1 thorpej free(namedup); 346 1.1 thorpej } 347 1.3 drochner /* assert(i == a->a_loclen) */ 348 1.9 dsl fprintf(fp, "#define %sCF_NLOCS %d\n", locdup, a->a_loclen); 349 1.1 thorpej free(locdup); 350 1.1 thorpej } 351 1.1 thorpej return 0; 352 1.1 thorpej } 353 1.1 thorpej 354 1.1 thorpej /* 355 1.1 thorpej * Build the "locators.h" file with manifest constants for all potential 356 1.1 thorpej * locators in the configuration. Do this by enumerating the attribute 357 1.1 thorpej * hash table and emitting all the locators for each attribute. 358 1.1 thorpej */ 359 1.17 pooka int 360 1.1 thorpej emitlocs(void) 361 1.1 thorpej { 362 1.15 lukem const char *tfname; 363 1.1 thorpej int rval; 364 1.1 thorpej FILE *tfp; 365 1.30 joe 366 1.1 thorpej tfname = "tmp_locators.h"; 367 1.1 thorpej if ((tfp = fopen(tfname, "w")) == NULL) 368 1.1 thorpej return (herr("open", tfname, NULL)); 369 1.1 thorpej 370 1.1 thorpej rval = ht_enumerate(attrtab, locators_print, tfp); 371 1.9 dsl 372 1.9 dsl fflush(tfp); 373 1.9 dsl if (ferror(tfp)) 374 1.9 dsl return (herr("writ", tfname, NULL)); 375 1.1 thorpej if (fclose(tfp) == EOF) 376 1.1 thorpej return (herr("clos", tfname, NULL)); 377 1.1 thorpej if (rval) 378 1.1 thorpej return (rval); 379 1.1 thorpej return (moveifchanged(tfname, "locators.h")); 380 1.1 thorpej } 381 1.1 thorpej 382 1.1 thorpej /* 383 1.1 thorpej * Build the "ioconf.h" file with extern declarations for all configured 384 1.1 thorpej * cfdrivers. 385 1.1 thorpej */ 386 1.18 pooka int 387 1.1 thorpej emitioconfh(void) 388 1.1 thorpej { 389 1.1 thorpej const char *tfname; 390 1.1 thorpej FILE *tfp; 391 1.1 thorpej struct devbase *d; 392 1.27 christos struct devi *i; 393 1.1 thorpej 394 1.1 thorpej tfname = "tmp_ioconf.h"; 395 1.1 thorpej if ((tfp = fopen(tfname, "w")) == NULL) 396 1.1 thorpej return (herr("open", tfname, NULL)); 397 1.1 thorpej 398 1.27 christos fputs("\n/* pseudo-devices */\n", tfp); 399 1.27 christos TAILQ_FOREACH(i, &allpseudo, i_next) { 400 1.27 christos fprintf(tfp, "void %sattach(int);\n", 401 1.27 christos i->i_base->d_name); 402 1.27 christos } 403 1.27 christos 404 1.27 christos fputs("\n/* driver structs */\n", tfp); 405 1.1 thorpej TAILQ_FOREACH(d, &allbases, d_next) { 406 1.1 thorpej if (!devbase_has_instances(d, WILD)) 407 1.1 thorpej continue; 408 1.9 dsl fprintf(tfp, "extern struct cfdriver %s_cd;\n", d->d_name); 409 1.1 thorpej } 410 1.1 thorpej 411 1.9 dsl fflush(tfp); 412 1.9 dsl if (ferror(tfp)) 413 1.9 dsl return herr("writ", tfname, tfp); 414 1.9 dsl 415 1.1 thorpej if (fclose(tfp) == EOF) 416 1.1 thorpej return (herr("clos", tfname, NULL)); 417 1.1 thorpej 418 1.29 uebayasi return (moveifchanged(tfname, "ioconf.h")); 419 1.1 thorpej } 420 1.1 thorpej 421 1.1 thorpej /* 422 1.1 thorpej * Make a file that config_time.h can use as a source, if required. 423 1.1 thorpej */ 424 1.1 thorpej static int 425 1.1 thorpej emittime(void) 426 1.1 thorpej { 427 1.1 thorpej FILE *fp; 428 1.1 thorpej time_t t; 429 1.1 thorpej struct tm *tm; 430 1.1 thorpej char buf[128]; 431 1.1 thorpej 432 1.1 thorpej t = time(NULL); 433 1.1 thorpej tm = gmtime(&t); 434 1.1 thorpej 435 1.1 thorpej if ((fp = fopen("config_time.src", "w")) == NULL) 436 1.1 thorpej return (herr("open", "config_time.src", NULL)); 437 1.1 thorpej 438 1.1 thorpej if (strftime(buf, sizeof(buf), "%c %Z", tm) == 0) 439 1.4 cube return (herr("strftime", "config_time.src", fp)); 440 1.1 thorpej 441 1.9 dsl fprintf(fp, "/* %s */\n" 442 1.1 thorpej "#define CONFIG_TIME\t%2lld\n" 443 1.1 thorpej "#define CONFIG_YEAR\t%2d\n" 444 1.1 thorpej "#define CONFIG_MONTH\t%2d\n" 445 1.1 thorpej "#define CONFIG_DATE\t%2d\n" 446 1.1 thorpej "#define CONFIG_HOUR\t%2d\n" 447 1.30 joe "#define CONFIG_MINS\t%2d\n" 448 1.1 thorpej "#define CONFIG_SECS\t%2d\n", 449 1.30 joe buf, (long long)t, 450 1.1 thorpej tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 451 1.9 dsl tm->tm_hour, tm->tm_min, tm->tm_sec); 452 1.9 dsl 453 1.9 dsl fflush(fp); 454 1.9 dsl if (ferror(fp)) 455 1.4 cube return (herr("fprintf", "config_time.src", fp)); 456 1.1 thorpej 457 1.1 thorpej if (fclose(fp) != 0) 458 1.9 dsl return (herr("clos", "config_time.src", NULL)); 459 1.1 thorpej 460 1.1 thorpej /* 461 1.1 thorpej * *Don't* moveifchanged this file. Makefile.kern.inc will 462 1.1 thorpej * handle that if it determines such a move is necessary. 463 1.1 thorpej */ 464 1.1 thorpej return (0); 465 1.1 thorpej } 466 1.1 thorpej 467 1.1 thorpej /* 468 1.1 thorpej * Compare two files. If nfname doesn't exist, or is different from 469 1.1 thorpej * tfname, move tfname to nfname. Otherwise, delete tfname. 470 1.1 thorpej */ 471 1.1 thorpej int 472 1.1 thorpej moveifchanged(const char *tfname, const char *nfname) 473 1.1 thorpej { 474 1.1 thorpej char tbuf[BUFSIZ], nbuf[BUFSIZ]; 475 1.1 thorpej FILE *tfp, *nfp; 476 1.1 thorpej 477 1.1 thorpej if ((tfp = fopen(tfname, "r")) == NULL) 478 1.1 thorpej return (herr("open", tfname, NULL)); 479 1.1 thorpej 480 1.1 thorpej if ((nfp = fopen(nfname, "r")) == NULL) 481 1.1 thorpej goto moveit; 482 1.1 thorpej 483 1.1 thorpej while (fgets(tbuf, sizeof(tbuf), tfp) != NULL) { 484 1.1 thorpej if (fgets(nbuf, sizeof(nbuf), nfp) == NULL) { 485 1.1 thorpej /* 486 1.1 thorpej * Old file has fewer lines. 487 1.1 thorpej */ 488 1.1 thorpej goto moveit; 489 1.1 thorpej } 490 1.1 thorpej if (strcmp(tbuf, nbuf) != 0) 491 1.1 thorpej goto moveit; 492 1.1 thorpej } 493 1.1 thorpej 494 1.1 thorpej /* 495 1.1 thorpej * We've reached the end of the new file. Check to see if new file 496 1.1 thorpej * has fewer lines than old. 497 1.1 thorpej */ 498 1.1 thorpej if (fgets(nbuf, sizeof(nbuf), nfp) != NULL) { 499 1.1 thorpej /* 500 1.1 thorpej * New file has fewer lines. 501 1.1 thorpej */ 502 1.1 thorpej goto moveit; 503 1.1 thorpej } 504 1.1 thorpej 505 1.1 thorpej (void) fclose(nfp); 506 1.1 thorpej (void) fclose(tfp); 507 1.1 thorpej if (remove(tfname) == -1) 508 1.1 thorpej return(herr("remov", tfname, NULL)); 509 1.1 thorpej return (0); 510 1.1 thorpej 511 1.1 thorpej moveit: 512 1.1 thorpej /* 513 1.1 thorpej * They're different, or the file doesn't exist. 514 1.1 thorpej */ 515 1.1 thorpej if (nfp) 516 1.1 thorpej (void) fclose(nfp); 517 1.1 thorpej if (tfp) 518 1.1 thorpej (void) fclose(tfp); 519 1.1 thorpej if (rename(tfname, nfname) == -1) 520 1.1 thorpej return (herr("renam", tfname, NULL)); 521 1.1 thorpej return (0); 522 1.1 thorpej } 523 1.1 thorpej 524 1.1 thorpej static int 525 1.1 thorpej herr(const char *what, const char *fname, FILE *fp) 526 1.1 thorpej { 527 1.1 thorpej 528 1.10 christos warn("error %sing %s", what, fname); 529 1.1 thorpej if (fp) 530 1.1 thorpej (void)fclose(fp); 531 1.1 thorpej return (1); 532 1.1 thorpej } 533 1.1 thorpej 534 1.1 thorpej static char * 535 1.1 thorpej cntname(const char *src) 536 1.1 thorpej { 537 1.1 thorpej char *dst; 538 1.22 christos char c; 539 1.1 thorpej static char buf[100]; 540 1.1 thorpej 541 1.1 thorpej dst = buf; 542 1.1 thorpej *dst++ = 'N'; 543 1.1 thorpej while ((c = *src++) != 0) 544 1.26 christos *dst++ = (char)(islower((u_char)c) ? toupper((u_char)c) : c); 545 1.1 thorpej *dst = 0; 546 1.1 thorpej return (buf); 547 1.1 thorpej } 548