xref: /dragonfly/usr.sbin/config/mkheaders.c (revision b40e316c)
1 /*
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)mkheaders.c	8.1 (Berkeley) 6/6/93
34  * $FreeBSD: src/usr.sbin/config/mkheaders.c,v 1.14.2.2 2001/01/23 00:09:32 peter Exp $
35  * $DragonFly: src/usr.sbin/config/mkheaders.c,v 1.13 2005/01/12 00:26:03 cpressey Exp $
36  */
37 
38 /*
39  * Make all the .h files for the optional entries
40  */
41 
42 #include <ctype.h>
43 #include <err.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <sys/param.h>
47 #include "config.h"
48 #include "y.tab.h"
49 
50 static void do_header(const char *, char *, int);
51 static void do_count(const char *, char *, int);
52 static char *toheader(const char *);
53 static char *tomacro(const char *);
54 
55 void
56 headers(void)
57 {
58 	struct file_list *fl;
59 	struct device *dp;
60 
61 	for (fl = ftab; fl != NULL; fl = fl->f_next)
62 		if (fl->f_needs != NULL)
63 			do_count(fl->f_needs, fl->f_needs, 1);
64 	for (dp = dtab; dp != NULL; dp = dp->d_next) {
65 		if ((dp->d_type & TYPEMASK) == PSEUDO_DEVICE) {
66 			if (!(dp->d_type & DEVDONE)) {
67 				printf("Warning: pseudo-device \"%s\" is unknown\n",
68 				       dp->d_name);
69 				exit(1);
70 			}
71 		}
72 		if ((dp->d_type & TYPEMASK) == DEVICE) {
73 			if (!(dp->d_type & DEVDONE)) {
74 				printf("Warning: device \"%s\" is unknown\n",
75 				       dp->d_name);
76 				exit(1);
77 			}
78 		}
79 	}
80 }
81 
82 /*
83  * count all the devices of a certain type and recurse to count
84  * whatever the device is connected to
85  */
86 static void
87 do_count(const char *dev, char *hname, int search)
88 {
89 	struct device *dp;
90 	int count, hicount;
91 	const char *mp;
92 
93 	/*
94 	 * After this loop, "count" will be the actual number of units,
95 	 * and "hicount" will be the highest unit declared. do_header()
96 	 * must use the higher of these values.
97 	 */
98 	for (dp = dtab; dp != NULL; dp = dp->d_next) {
99 		if (strcmp(dp->d_name, dev) == 0) {
100 			if ((dp->d_type & TYPEMASK) == PSEUDO_DEVICE)
101 				dp->d_type |= DEVDONE;
102 			else if ((dp->d_type & TYPEMASK) == DEVICE)
103 				dp->d_type |= DEVDONE;
104 		}
105 	}
106 	for (hicount = count = 0, dp = dtab; dp != NULL; dp = dp->d_next) {
107 		if (dp->d_unit != -1 && strcmp(dp->d_name, dev) == 0) {
108 			if ((dp->d_type & TYPEMASK) == PSEUDO_DEVICE) {
109 				count =
110 				    dp->d_count != UNKNOWN ? dp->d_count : 1;
111 				break;
112 			}
113 			count++;
114 			/*
115 			 * Allow holes in unit numbering,
116 			 * assumption is unit numbering starts
117 			 * at zero.
118 			 */
119 			if (dp->d_unit + 1 > hicount)
120 				hicount = dp->d_unit + 1;
121 			if (search) {
122 				mp = dp->d_conn;
123 				if (mp != NULL && dp->d_connunit < 0)
124 					mp = NULL;
125 				if (mp != NULL && strcmp(mp, "nexus") == 0)
126 					mp = NULL;
127 				if (mp != NULL) {
128 					do_count(mp, hname, 0);
129 					search = 0;
130 				}
131 			}
132 		}
133 	}
134 	do_header(dev, hname, count > hicount ? count : hicount);
135 }
136 
137 static void
138 do_header(const char *dev, char *hname, int count)
139 {
140 	char *file, *name, *inw;
141 	struct file_list *fl, *fl_head, *tflp;
142 	FILE *inf, *outf;
143 	int inc, oldcount;
144 
145 	file = toheader(hname);
146 	name = tomacro(dev);
147 	inf = fopen(file, "r");
148 	oldcount = -1;
149 	if (inf == NULL) {
150 		outf = fopen(file, "w");
151 		if (outf == NULL)
152 			err(1, "%s", file);
153 		fprintf(outf, "#define %s %d\n", name, count);
154 		fclose(outf);
155 		return;
156 	}
157 	fl_head = NULL;
158 	for (;;) {
159 		char *cp;
160 		if ((inw = get_word(inf)) == NULL || inw == (char *)EOF)
161 			break;
162 		if ((inw = get_word(inf)) == NULL || inw == (char *)EOF)
163 			break;
164 		inw = strdup(inw);
165 		cp = get_word(inf);
166 		if (cp == NULL || cp == (char *)EOF)
167 			break;
168 		inc = atoi(cp);
169 		if (strcmp(inw, name) == 0) {
170 			oldcount = inc;
171 			inc = count;
172 		}
173 		cp = get_word(inf);
174 		if (cp == (char *)EOF)
175 			break;
176 		fl = malloc(sizeof(*fl));
177 		bzero(fl, sizeof(*fl));
178 		fl->f_fn = inw;		/* malloced */
179 		fl->f_type = inc;
180 		fl->f_next = fl_head;
181 		fl_head = fl;
182 	}
183 	fclose(inf);
184 	if (count == oldcount) {
185 		for (fl = fl_head; fl != NULL; fl = tflp) {
186 			tflp = fl->f_next;
187 			free(fl->f_fn);
188 			free(fl);
189 		}
190 		return;
191 	}
192 	if (oldcount == -1) {
193 		fl = malloc(sizeof(*fl));
194 		bzero(fl, sizeof(*fl));
195 		fl->f_fn = strdup(name);
196 		fl->f_type = count;
197 		fl->f_next = fl_head;
198 		fl_head = fl;
199 	}
200 	outf = fopen(file, "w");
201 	if (outf == 0)
202 		err(1, "%s", file);
203 	for (fl = fl_head; fl != NULL; fl = tflp) {
204 		fprintf(outf,
205 		    "#define %s %u\n", fl->f_fn, count ? fl->f_type : 0);
206 		tflp = fl->f_next;
207 		free(fl->f_fn);
208 		free(fl);
209 	}
210 	fclose(outf);
211 }
212 
213 /*
214  * convert a dev name to a .h file name
215  */
216 static char *
217 toheader(const char *dev)
218 {
219 	static char hbuf[MAXPATHLEN];
220 	static char udev[MAXPATHLEN];
221 
222 	snprintf(udev, sizeof(udev), "use_%s", dev);
223 
224 	snprintf(hbuf, sizeof(hbuf), "%s.h", path(udev));
225 	return(hbuf);
226 }
227 
228 /*
229  * convert a dev name to a macro name
230  */
231 static char *
232 tomacro(const char *dev)
233 {
234 	static char mbuf[20];
235 	char *cp;
236 
237 	cp = mbuf;
238 	*cp++ = 'N';
239 	while (*dev != 0)
240 		*cp++ = islower(*dev) ? toupper(*dev++) : *dev++;
241 	*cp++ = 0;
242 	return(mbuf);
243 }
244