3 * $Id: sw_arch.c,v 1.1 1999/06/02 16:53:34 mdw Exp $
5 * Messing with architectures
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of sw-tools.
14 * sw-tools is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * sw-tools is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with sw-tools; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Revision history --------------------------------------------------*
32 * Revision 1.1 1999/06/02 16:53:34 mdw
37 /*----- Header files ------------------------------------------------------*/
47 #include <mLib/alloc.h>
48 #include <mLib/dstr.h>
49 #include <mLib/quis.h>
50 #include <mLib/report.h>
56 /*----- Static variables --------------------------------------------------*/
58 static archcons
*tab
= 0;
60 /*----- Main code ---------------------------------------------------------*/
62 /* --- @arch_readtab@ --- *
66 * Returns: The address of the archtab list.
68 * Use: Reads the archtab file (if necessary) and returns a list of
72 archcons
*arch_readtab(void)
78 /* --- Return the list if I've already got it --- */
83 /* --- Open the file --- */
85 if ((fp
= fopen(ARCHTAB
, "r")) == 0)
86 die(1, "couldn't open `%s': %s", ARCHTAB
, strerror(errno
));
88 /* --- Read it in line-by-line --- */
91 for (; dstr_putline(&d
, fp
) != EOF
; DRESET(&d
)) {
96 /* --- Pick out the architecture name --- */
98 while (isspace((unsigned char)*q
))
100 if (*q
== '#' || *q
== 0)
103 while (*q
&& !isspace((unsigned char)*q
))
108 /* --- Pick out the hostname --- */
110 while (isspace((unsigned char)*q
))
115 while (*q
&& !isspace((unsigned char)*q
))
120 /* --- Allocate a new link --- */
122 a
= xmalloc(sizeof(*a
));
123 a
->arch
= xstrdup(arch
);
124 a
->host
= xstrdup(host
);
129 if (strcmp(arch
, ARCH
) == 0)
130 a
->flags
|= archFlag_home
;
143 /* --- @arch_lookup@ --- *
145 * Arguments: @const char *arch@ = pointer to archtecture name
146 * @int abbrev@ = whether abbreviations are OK
148 * Returns: Pointer to archtab block, or null.
150 * Use: Translates an architecture name into the name of a host
151 * supporting that architecture.
154 archent
*arch_lookup(const char *arch
, int abbrev
)
156 size_t sz
= strlen(arch
);
160 for (a
= arch_readtab(); a
; a
= a
->cdr
) {
162 if (strncmp(arch
, e
->arch
, sz
) == 0) {
163 if (e
->arch
[sz
] == 0)
176 /* --- @arch_filter@ --- *
178 * Arguments: @archcons *a@ = input list to filter
179 * @const char *p@ = pointer to a textual list of architectures
180 * @unsigned and@, @unsigned xor@ = flags to look for
182 * Returns: A newly constructed architecture list containing only the
183 * listed architectures.
185 * Use: Filters the architecture list down to a few interesting
188 * If @p@ is non-null, it is a textual list of architecture
189 * names (possibly abbreviated), and separated by whitespace
190 * and/or commas: only the named architectures are included in
191 * the resulting list. If @p@ is null, all architectures are
194 * The list is further trimmed down by examining the flags words
195 * in each entry. Only entries with flags @f@ where @(f ^ xor)
196 * & and@ is zero are left in the resulting list. (To include
197 * all entries, clear @and@ to zero. To require a flag to be
198 * clear, set the corresponding bit in @and@. To require a flag
199 * to be set, set the corresponding bit in both @and@ and @xor@.
201 * (Don't try to filter on the @archFlag_touched@ flag. That
202 * flag is for the internal use of this routine.)
205 archcons
*arch_filter(archcons
*a
, const char *p
,
206 unsigned and, unsigned xor)
210 /* --- How this works --- *
212 * If I have a list of architecture names in @p@, then I scan the list and
213 * set the `touch' bit on matching entries, and clear it on nonmatching
214 * ones. Then I set the `touch' bit in the @and@ and @xor@ arguments.
215 * Otherwise I skip all of that, and clear the `touch' bit in @and@. After
216 * all that, I just scoop up the architectures with appropriate flags.
219 and &= ~archFlag_touched
;
222 /* --- Clear all the touch flags --- */
226 for (aa
= a
; aa
; aa
= aa
->cdr
)
227 aa
->car
->flags
&= ~archFlag_touched
;
230 /* --- Set flags for entries in my list --- */
233 char *q
= xstrdup(p
);
234 for (p
= strtok(q
, ", \t"); p
; p
= strtok(0, ", \t")) {
235 archent
*e
= arch_lookup(p
, 1);
237 die(1, "architecture `%s' not found", p
);
238 e
->flags
|= archFlag_touched
;
243 /* --- Only include touched entries --- */
245 and |= archFlag_touched
;
246 xor |= archFlag_touched
;
249 /* --- Now trundle through the list accumulating matching entries --- */
254 for (; a
; a
= a
->cdr
) {
255 if (((a
->car
->flags
^ xor) & and) == 0) {
256 archcons
*aa
= CREATE(archcons
);
270 /* --- @arch_free@ --- *
272 * Arguments: @archcons *a@ = pointer to a list
276 * Use: Contrary to anything you might have expected from the Lispy
277 * naming, old architecture lists don't get garbage collected.
278 * This routine throws away an old list when you don't want it
279 * any more. Don't call this on the main list! It will fail
280 * miserably, because the cons cells in the main list are
284 void arch_free(archcons
*a
)
287 archcons
*p
= a
->cdr
;
293 /* --- @arch_toText@ --- *
295 * Arguments: @dstr *d@ = pointer to dynamic string to build result in
296 * @archcons *a@ = list to write into the string
297 * @unsigned and@, @unsigned xor@ = flags to look for
301 * Use: Writes a textual list of architectures to a string. This can
302 * then be used (for example) as the `only-arch' list in the
303 * info file, by filling it into a skeleton and calling
304 * @swinfo_update@. The @and@ and @xor@ arguments work in the
305 * same way as with @arch_filter@.
308 void arch_toText(dstr
*d
, archcons
*a
, unsigned and, unsigned xor)
312 for (; a
; a
= a
->cdr
) {
314 if (((e
->flags
^ xor) & and) == 0) {
317 dstr_puts(d
, e
->arch
);
323 /*----- Subcommands -------------------------------------------------------*/
325 /* --- @sw_arch@ --- */
327 int sw_arch(int argc
, char *argv
[])
330 die(1, "Usage: arch");
335 /* --- @sw_host@ --- */
337 int sw_host(int argc
, char *argv
[])
341 die(1, "Usage: host ARCH");
342 if ((a
= arch_lookup(argv
[1], 1)) == 0)
343 die(1, "no host for architecture `%s'", argv
[1]);
348 /* --- @sw_listarch@ --- */
350 int sw_listarch(int argc
, char *argv
[])
354 die(1, "Usage: listarch");
355 for (a
= arch_readtab(); a
; a
= a
->cdr
)
360 /* --- @sw_all@ --- */
362 int sw_all(int argc
, char *argv
[])
366 die(1, "Usage: all");
367 if (swinfo_fetch(&sw
)) {
368 die(1, "couldn't read build status: %s (try running setup)",
379 /* --- @sw_only@ --- */
381 int sw_only(int argc
, char *argv
[])
385 /* --- Validate the arguments --- */
388 die(1, "Usage: only-arch ARCH,...");
390 /* --- Gather the arguments into one buffer --- */
394 for (i
= 1; i
< argc
; i
++) {
396 dstr_puts(&d
, argv
[i
]);
400 /* --- Convert into a canonical list --- */
403 archcons
*a
= arch_filter(arch_readtab(), d
.buf
, 0, 0);
405 arch_toText(&d
, a
, 0, 0);
409 /* --- Put the list into the information table --- */
414 if (swinfo_fetch(&sw
)) {
415 die(1, "couldn't read build status: %s (try running setup)",
420 skel
.only_arch
= d
.buf
;
421 swinfo_update(&sw
, &skel
);
430 /*----- That's all, folks -------------------------------------------------*/