1 /* $OpenBSD: mkheaders.c,v 1.22 2016/10/16 17:50:00 tb 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 <ctype.h> 45 #include <err.h> 46 #include <errno.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 51 #include "config.h" 52 53 static int emitcnt(struct nvlist *); 54 static int emitopt(struct nvlist *); 55 static int emitwarn(const char *, char *, FILE *); 56 static char *cntname(const char *); 57 58 /* 59 * Make headers containing counts, as needed. 60 */ 61 int 62 mkheaders(void) 63 { 64 struct files *fi; 65 struct nvlist *nv; 66 67 for (fi = allfiles; fi != NULL; fi = fi->fi_next) { 68 if (fi->fi_flags & FI_HIDDEN) 69 continue; 70 if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) && 71 emitcnt(fi->fi_optf)) 72 return (1); 73 } 74 75 for (nv = defoptions; nv != NULL; nv = nv->nv_next) 76 if (emitopt(nv)) 77 return (1); 78 79 return (0); 80 } 81 82 static int 83 emitcnt(struct nvlist *head) 84 { 85 struct nvlist *nv; 86 FILE *fp; 87 int cnt; 88 char nam[100]; 89 char buf[BUFSIZ]; 90 char fname[BUFSIZ]; 91 92 (void)snprintf(fname, sizeof fname, "%s.h", head->nv_name); 93 if ((fp = fopen(fname, "r")) == NULL) 94 goto writeit; 95 nv = head; 96 while (fgets(buf, sizeof(buf), fp) != NULL) { 97 if (nv == NULL) 98 goto writeit; 99 if (sscanf(buf, "#define %99s %d", nam, &cnt) != 2 || 100 strcmp(nam, cntname(nv->nv_name)) != 0 || 101 cnt != nv->nv_int) 102 goto writeit; 103 nv = nv->nv_next; 104 } 105 if (ferror(fp)) 106 return (emitwarn("read", fname, fp)); 107 (void)fclose(fp); 108 if (nv == NULL) 109 return (0); 110 writeit: 111 if ((fp = fopen(fname, "w")) == NULL) 112 return (emitwarn("writ", fname, NULL)); 113 for (nv = head; nv != NULL; nv = nv->nv_next) 114 if (fprintf(fp, "#define\t%s\t%d\n", 115 cntname(nv->nv_name), nv->nv_int) < 0) 116 return (emitwarn("writ", fname, fp)); 117 if (fclose(fp)) 118 return (emitwarn("writ", fname, NULL)); 119 return (0); 120 } 121 122 static int 123 emitopt(struct nvlist *nv) 124 { 125 struct nvlist *option; 126 char new_contents[BUFSIZ], buf[BUFSIZ]; 127 char fname[BUFSIZ]; 128 int totlen, nlines; 129 FILE *fp; 130 131 /* 132 * Generate the new contents of the file. 133 */ 134 if ((option = ht_lookup(opttab, nv->nv_str)) == NULL) 135 totlen = snprintf(new_contents, sizeof new_contents, 136 "/* option `%s' not defined */\n", 137 nv->nv_str); 138 else { 139 if (option->nv_str != NULL) 140 totlen = snprintf(new_contents, sizeof new_contents, 141 "#define\t%s\t%s\n", 142 option->nv_name, option->nv_str); 143 else 144 totlen = snprintf(new_contents, sizeof new_contents, 145 "#define\t%s\n", 146 option->nv_name); 147 } 148 149 if (totlen < 0 || totlen >= sizeof new_contents) { 150 warnx("string too long"); 151 return (1); 152 } 153 154 /* 155 * Compare the new file to the old. 156 */ 157 snprintf(fname, sizeof fname, "opt_%s.h", nv->nv_name); 158 if ((fp = fopen(fname, "r")) == NULL) 159 goto writeit; 160 nlines = 0; 161 while (fgets(buf, sizeof(buf), fp) != NULL) { 162 if (++nlines != 1 || 163 strcmp(buf, new_contents) != 0) 164 goto writeit; 165 } 166 if (ferror(fp)) 167 return (emitwarn("read", fname, fp)); 168 (void)fclose(fp); 169 if (nlines == 1) 170 return (0); 171 writeit: 172 /* 173 * They're different, or the file doesn't exist. 174 */ 175 if ((fp = fopen(fname, "w")) == NULL) 176 return (emitwarn("writ", fname, NULL)); 177 if (fprintf(fp, "%s", new_contents) < 0) 178 return (emitwarn("writ", fname, fp)); 179 if (fclose(fp)) 180 return (emitwarn("writ", fname, fp)); 181 return (0); 182 } 183 184 static int 185 emitwarn(const char *what, char *fname, FILE *fp) 186 { 187 188 warn("error %sing %s", what, fname); 189 if (fp) 190 (void)fclose(fp); 191 return (1); 192 } 193 194 static char * 195 cntname(const char *src) 196 { 197 char *dst, c; 198 static char buf[100]; 199 200 dst = buf; 201 *dst++ = 'N'; 202 while ((c = *src++) != 0) 203 *dst++ = islower((unsigned char)c) ? 204 toupper((unsigned char)c) : c; 205 *dst = 0; 206 return (buf); 207 } 208