#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
static int emitcnt(struct nvlist *);
static int emitopt(struct nvlist *);
static int emitwarn(const char *, char *, FILE *);
static char *cntname(const char *);
int
mkheaders(void)
{
struct files *fi;
struct nvlist *nv;
for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
if (fi->fi_flags & FI_HIDDEN)
continue;
if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) &&
emitcnt(fi->fi_optf))
return (1);
}
for (nv = defoptions; nv != NULL; nv = nv->nv_next)
if (emitopt(nv))
return (1);
return (0);
}
static int
emitcnt(struct nvlist *head)
{
struct nvlist *nv;
FILE *fp;
int cnt;
char nam[100];
char buf[BUFSIZ];
char fname[BUFSIZ];
(void)snprintf(fname, sizeof fname, "%s.h", head->nv_name);
if ((fp = fopen(fname, "r")) == NULL)
goto writeit;
nv = head;
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (nv == NULL)
goto writeit;
if (sscanf(buf, "#define %99s %d", nam, &cnt) != 2 ||
strcmp(nam, cntname(nv->nv_name)) != 0 ||
cnt != nv->nv_int)
goto writeit;
nv = nv->nv_next;
}
if (ferror(fp))
return (emitwarn("read", fname, fp));
(void)fclose(fp);
if (nv == NULL)
return (0);
writeit:
if ((fp = fopen(fname, "w")) == NULL)
return (emitwarn("writ", fname, NULL));
for (nv = head; nv != NULL; nv = nv->nv_next)
if (fprintf(fp, "#define\t%s\t%d\n",
cntname(nv->nv_name), nv->nv_int) < 0)
return (emitwarn("writ", fname, fp));
if (fclose(fp))
return (emitwarn("writ", fname, NULL));
return (0);
}
static int
emitopt(struct nvlist *nv)
{
struct nvlist *option;
char new_contents[BUFSIZ], buf[BUFSIZ];
char fname[BUFSIZ];
int totlen, nlines;
FILE *fp;
if ((option = ht_lookup(opttab, nv->nv_str)) == NULL)
totlen = snprintf(new_contents, sizeof new_contents,
"/* option `%s' not defined */\n",
nv->nv_str);
else {
if (option->nv_str != NULL)
totlen = snprintf(new_contents, sizeof new_contents,
"#define\t%s\t%s\n",
option->nv_name, option->nv_str);
else
totlen = snprintf(new_contents, sizeof new_contents,
"#define\t%s\n",
option->nv_name);
}
if (totlen < 0 || totlen >= sizeof new_contents) {
warnx("string too long");
return (1);
}
snprintf(fname, sizeof fname, "opt_%s.h", nv->nv_name);
if ((fp = fopen(fname, "r")) == NULL)
goto writeit;
nlines = 0;
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (++nlines != 1 ||
strcmp(buf, new_contents) != 0)
goto writeit;
}
if (ferror(fp))
return (emitwarn("read", fname, fp));
(void)fclose(fp);
if (nlines == 1)
return (0);
writeit:
if ((fp = fopen(fname, "w")) == NULL)
return (emitwarn("writ", fname, NULL));
if (fprintf(fp, "%s", new_contents) < 0)
return (emitwarn("writ", fname, fp));
if (fclose(fp))
return (emitwarn("writ", fname, fp));
return (0);
}
static int
emitwarn(const char *what, char *fname, FILE *fp)
{
warn("error %sing %s", what, fname);
if (fp)
(void)fclose(fp);
return (1);
}
static char *
cntname(const char *src)
{
char *dst, c;
static char buf[100];
dst = buf;
*dst++ = 'N';
while ((c = *src++) != 0)
*dst++ = islower((unsigned char)c) ?
toupper((unsigned char)c) : c;
*dst = 0;
return (buf);
}