1 /* $OpenBSD: mkheaders.c,v 1.18 2003/06/28 04:55:07 deraadt Exp $ */ 2 /* $NetBSD: mkheaders.c,v 1.12 1997/02/02 21:12:34 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by the University of 15 * California, Lawrence Berkeley Laboratories. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: @(#)mkheaders.c 8.1 (Berkeley) 6/6/93 42 */ 43 44 #include <sys/param.h> 45 #include <ctype.h> 46 #include <errno.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include "config.h" 51 52 static int emitcnt(struct nvlist *); 53 static int emitopt(struct nvlist *); 54 static int err(const char *, char *, FILE *); 55 static char *cntname(const char *); 56 57 /* 58 * Make headers containing counts, as needed. 59 */ 60 int 61 mkheaders(void) 62 { 63 struct files *fi; 64 struct nvlist *nv; 65 66 for (fi = allfiles; fi != NULL; fi = fi->fi_next) { 67 if (fi->fi_flags & FI_HIDDEN) 68 continue; 69 if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) && 70 emitcnt(fi->fi_optf)) 71 return (1); 72 } 73 74 for (nv = defoptions; nv != NULL; nv = nv->nv_next) 75 if (emitopt(nv)) 76 return (1); 77 78 return (0); 79 } 80 81 static int 82 emitcnt(struct nvlist *head) 83 { 84 struct nvlist *nv; 85 FILE *fp; 86 int cnt; 87 char nam[100]; 88 char buf[BUFSIZ]; 89 char fname[BUFSIZ]; 90 91 (void)snprintf(fname, sizeof fname, "%s.h", head->nv_name); 92 if ((fp = fopen(fname, "r")) == NULL) 93 goto writeit; 94 nv = head; 95 while (fgets(buf, sizeof(buf), fp) != NULL) { 96 if (nv == NULL) 97 goto writeit; 98 if (sscanf(buf, "#define %99s %d", nam, &cnt) != 2 || 99 strcmp(nam, cntname(nv->nv_name)) != 0 || 100 cnt != nv->nv_int) 101 goto writeit; 102 nv = nv->nv_next; 103 } 104 if (ferror(fp)) 105 return (err("read", fname, fp)); 106 (void)fclose(fp); 107 if (nv == NULL) 108 return (0); 109 writeit: 110 if ((fp = fopen(fname, "w")) == NULL) { 111 (void)fprintf(stderr, "config: cannot write %s: %s\n", 112 fname, strerror(errno)); 113 return (1); 114 } 115 for (nv = head; nv != NULL; nv = nv->nv_next) 116 if (fprintf(fp, "#define\t%s\t%d\n", 117 cntname(nv->nv_name), nv->nv_int) < 0) 118 return (err("writ", fname, fp)); 119 if (fclose(fp)) 120 return (err("writ", fname, NULL)); 121 return (0); 122 } 123 124 static int 125 emitopt(struct nvlist *nv) 126 { 127 struct nvlist *option; 128 char new_contents[BUFSIZ], buf[BUFSIZ]; 129 char fname[BUFSIZ]; 130 int totlen, nlines; 131 FILE *fp; 132 133 /* 134 * Generate the new contents of the file. 135 */ 136 if ((option = ht_lookup(opttab, nv->nv_str)) == NULL) 137 totlen = snprintf(new_contents, sizeof new_contents, 138 "/* option `%s' not defined */\n", 139 nv->nv_str); 140 else { 141 if (option->nv_str != NULL) 142 totlen = snprintf(new_contents, sizeof new_contents, 143 "#define\t%s\t%s\n", 144 option->nv_name, option->nv_str); 145 else 146 totlen = snprintf(new_contents, sizeof new_contents, 147 "#define\t%s\n", 148 option->nv_name); 149 } 150 151 if (totlen < 0 || totlen >= sizeof new_contents) { 152 fprintf(stderr, "config: string too long\n"); 153 return (1); 154 } 155 156 /* 157 * Compare the new file to the old. 158 */ 159 snprintf(fname, sizeof fname, "opt_%s.h", nv->nv_name); 160 if ((fp = fopen(fname, "r")) == NULL) 161 goto writeit; 162 nlines = 0; 163 while (fgets(buf, sizeof(buf), fp) != NULL) { 164 if (++nlines != 1 || 165 strcmp(buf, new_contents) != 0) 166 goto writeit; 167 } 168 if (ferror(fp)) 169 return (err("read", fname, fp)); 170 (void)fclose(fp); 171 if (nlines == 1) 172 return (0); 173 writeit: 174 /* 175 * They're different, or the file doesn't exist. 176 */ 177 if ((fp = fopen(fname, "w")) == NULL) { 178 (void)fprintf(stderr, "config: cannot write %s: %s\n", 179 fname, strerror(errno)); 180 return (1); 181 } 182 if (fprintf(fp, "%s", new_contents) < 0) 183 return (err("writ", fname, fp)); 184 if (fclose(fp)) 185 return (err("writ", fname, fp)); 186 return (0); 187 } 188 189 static int 190 err(const char *what, char *fname, FILE *fp) 191 { 192 193 (void)fprintf(stderr, "config: error %sing %s: %s\n", 194 what, fname, strerror(errno)); 195 if (fp) 196 (void)fclose(fp); 197 return (1); 198 } 199 200 static char * 201 cntname(const char *src) 202 { 203 char *dst, c; 204 static char buf[100]; 205 206 dst = buf; 207 *dst++ = 'N'; 208 while ((c = *src++) != 0) 209 *dst++ = islower(c) ? toupper(c) : c; 210 *dst = 0; 211 return (buf); 212 } 213