diff --git a/tools/build/depend-cleanup.sh b/tools/build/depend-cleanup.sh --- a/tools/build/depend-cleanup.sh +++ b/tools/build/depend-cleanup.sh @@ -119,3 +119,5 @@ # 20220126 x move from mkmakefile.c to mkmakefile.cc clean_dep usr.sbin/config mkmakefile c +clean_dep usr.sbin/config main c +clean_dep usr.sbin/config mkoptions c diff --git a/usr.sbin/config/Makefile b/usr.sbin/config/Makefile --- a/usr.sbin/config/Makefile +++ b/usr.sbin/config/Makefile @@ -5,8 +5,8 @@ PROG_CXX= config MAN= config.5 config.8 -SRCS= config.y main.c lang.l mkmakefile.cc mkheaders.c \ - mkoptions.c y.tab.h kernconf.c +SRCS= config.y main.cc lang.l mkmakefile.cc mkheaders.c \ + mkoptions.cc y.tab.h kernconf.c FILE2C?=file2c @@ -18,8 +18,6 @@ NO_WMISSING_VARIABLE_DECLARATIONS= -LIBADD= sbuf - CLEANFILES+= kernconf.c mkmakefile.o: configvers.h diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h --- a/usr.sbin/config/config.h +++ b/usr.sbin/config/config.h @@ -41,6 +41,56 @@ #include #include +#ifdef __cplusplus +#include + +class configword { +private: + std::string cw_word; + bool cw_eof; + bool cw_eol; +public: + configword() : cw_word(""), cw_eof(false), cw_eol(false) {} + configword(std::string &&word) : cw_word(word), cw_eof(false), cw_eol(false) {} + + bool eof() const { + return (cw_eof); + } + + bool eol() const { + return (cw_eol); + } + + configword &eof(bool eof) { + cw_eof = eof; + return (*this); + } + + configword &eol(bool eol) { + cw_eol = eol; + return (*this); + } + + char operator[](int idx) { + return (cw_word[idx]); + } + + operator const char*() const { + return (cw_word.c_str()); + } + + const std::string *operator->() const { + return (&cw_word); + } +}; + +/* + * Is it ugly to limit these to C++ files? Yes. + */ +configword get_word(FILE *); +configword get_quoted_word(FILE *); +#endif + __BEGIN_DECLS struct cfgfile { @@ -185,8 +235,6 @@ extern int do_trace; extern int incignore; -char *get_word(FILE *); -char *get_quoted_word(FILE *); char *path(const char *); char *raisestr(char *); void remember(const char *); diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.cc rename from usr.sbin/config/main.c rename to usr.sbin/config/main.cc --- a/usr.sbin/config/main.c +++ b/usr.sbin/config/main.cc @@ -45,19 +45,21 @@ #include #include -#include #include #include #include #include #include +#include #include +#include +#include #include #include #include #include -#include + #include "y.tab.h" #include "config.h" #include "configvers.h" @@ -111,7 +113,7 @@ struct hdr_list *h_next; } *htab; -static struct sbuf *line_buf = NULL; +static std::stringstream line_buf; /* * Config builds a set of files for building a UNIX @@ -313,24 +315,21 @@ static void init_line_buf(void) { - if (line_buf == NULL) { - line_buf = sbuf_new(NULL, NULL, 80, SBUF_AUTOEXTEND); - if (line_buf == NULL) { - errx(EXIT_FAILURE, "failed to allocate line buffer"); - } - } else { - sbuf_clear(line_buf); - } + + line_buf.str(""); } -static char * +static std::string get_line_buf(void) { - if (sbuf_finish(line_buf) != 0) { + + line_buf.flush(); + if (!line_buf.good()) { errx(EXIT_FAILURE, "failed to generate line buffer, " - "partial line = %s", sbuf_data(line_buf)); + "partial line = %s", line_buf.str().c_str()); } - return sbuf_data(line_buf); + + return line_buf.str(); } /* @@ -339,7 +338,7 @@ * NULL on end of line * pointer to the word otherwise */ -char * +configword get_word(FILE *fp) { int ch; @@ -351,7 +350,7 @@ if (ch != ' ' && ch != '\t') break; if (ch == EOF) - return ((char *)EOF); + return (configword().eof(true)); if (ch == '\\'){ escaped_nl = 1; goto begin; @@ -362,22 +361,22 @@ goto begin; } else - return (NULL); + return (configword().eol(true)); } - sbuf_putc(line_buf, ch); + line_buf << (char)ch; /* Negation operator is a word by itself. */ if (ch == '!') { - return get_line_buf(); + return (configword(get_line_buf())); } while ((ch = getc(fp)) != EOF) { if (isspace(ch)) break; - sbuf_putc(line_buf, ch); + line_buf << (char)ch; } if (ch == EOF) - return ((char *)EOF); + return (configword().eof(true)); (void) ungetc(ch, fp); - return (get_line_buf()); + return (configword(get_line_buf())); } /* @@ -385,7 +384,7 @@ * like get_word but will accept something in double or single quotes * (to allow embedded spaces). */ -char * +configword get_quoted_word(FILE *fp) { int ch; @@ -397,7 +396,7 @@ if (ch != ' ' && ch != '\t') break; if (ch == EOF) - return ((char *)EOF); + return (configword().eof(true)); if (ch == '\\'){ escaped_nl = 1; goto begin; @@ -408,7 +407,7 @@ goto begin; } else - return (NULL); + return (configword().eol(true)); } if (ch == '"' || ch == '\'') { int quote = ch; @@ -419,7 +418,7 @@ break; if (ch == '\n' && !escaped_nl) { printf("config: missing quote reading `%s'\n", - get_line_buf()); + get_line_buf().c_str()); exit(2); } if (ch == '\\' && !escaped_nl) { @@ -427,23 +426,23 @@ continue; } if (ch != quote && escaped_nl) - sbuf_putc(line_buf, '\\'); - sbuf_putc(line_buf, ch); + line_buf << "\\"; + line_buf << (char)ch; escaped_nl = 0; } } else { - sbuf_putc(line_buf, ch); + line_buf << (char)ch; while ((ch = getc(fp)) != EOF) { if (isspace(ch)) break; - sbuf_putc(line_buf, ch); + line_buf << (char)ch; } if (ch != EOF) (void) ungetc(ch, fp); } if (ch == EOF) - return ((char *)EOF); - return (get_line_buf()); + return (configword().eof(true)); + return (configword(get_line_buf())); } /* @@ -466,7 +465,7 @@ * will be able to obtain and build conifguration file with one command. */ static void -configfile_dynamic(struct sbuf *sb) +configfile_dynamic(std::ostringstream &cfg) { struct cputype *cput; struct device *d; @@ -476,38 +475,35 @@ asprintf(&lend, "\\n\\\n"); assert(lend != NULL); - sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend); - sbuf_printf(sb, "ident\t%s%s", ident, lend); - sbuf_printf(sb, "machine\t%s%s", machinename, lend); + cfg << "options\t" << OPT_AUTOGEN << lend; + cfg << "ident\t" << ident << lend; + cfg << "machine\t" << machinename << lend; SLIST_FOREACH(cput, &cputype, cpu_next) - sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend); + cfg << "cpu\t" << cput->cpu_name << lend; SLIST_FOREACH(ol, &mkopt, op_next) - sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name, - ol->op_value, lend); + cfg << "makeoptions\t" << ol->op_name << '=' << + ol->op_value << lend; SLIST_FOREACH(ol, &opt, op_next) { if (strncmp(ol->op_name, "DEV_", 4) == 0) continue; - sbuf_printf(sb, "options\t%s", ol->op_name); + cfg << "options\t" << ol->op_name; if (ol->op_value != NULL) { - sbuf_putc(sb, '='); + cfg << '='; for (i = 0; i < strlen(ol->op_value); i++) { if (ol->op_value[i] == '"') - sbuf_printf(sb, "\\%c", - ol->op_value[i]); + cfg << '\\' << ol->op_value[i]; else - sbuf_printf(sb, "%c", - ol->op_value[i]); + cfg << ol->op_value[i]; } - sbuf_printf(sb, "%s", lend); - } else { - sbuf_printf(sb, "%s", lend); } + + cfg << lend; } /* * Mark this file as containing everything we need. */ STAILQ_FOREACH(d, &dtab, d_next) - sbuf_printf(sb, "device\t%s%s", d->d_name, lend); + cfg << "device\t" << d->d_name << lend; free(lend); } @@ -515,7 +511,7 @@ * Generate file from the configuration files. */ static void -configfile_filebased(struct sbuf *sb) +configfile_filebased(std::ostringstream &cfg) { FILE *cff; struct cfgfile *cf; @@ -534,11 +530,11 @@ } while ((i = getc(cff)) != EOF) { if (i == '\n') - sbuf_printf(sb, "\\n\\\n"); + cfg << "\\n\\\n"; else if (i == '"' || i == '\'') - sbuf_printf(sb, "\\%c", i); + cfg << '\\' << i; else - sbuf_putc(sb, i); + cfg << i; } fclose(cff); } @@ -548,7 +544,7 @@ configfile(void) { FILE *fo; - struct sbuf *sb; + std::ostringstream cfg; char *p; /* Add main configuration file to the list of files to be included */ @@ -557,16 +553,14 @@ fo = fopen(p, "w"); if (!fo) err(2, "%s", p); - sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND); - assert(sb != NULL); - sbuf_clear(sb); if (filebased) { /* Is needed, can be used for backward compatibility. */ - configfile_filebased(sb); + configfile_filebased(cfg); } else { - configfile_dynamic(sb); + configfile_dynamic(cfg); } - sbuf_finish(sb); + + cfg.flush(); /* * We print first part of the template, replace our tag with * configuration files content and later continue writing our @@ -577,10 +571,9 @@ errx(EXIT_FAILURE, "Something went terribly wrong!"); *p = '\0'; fprintf(fo, "%s", kernconfstr); - fprintf(fo, "%s", sbuf_data(sb)); + fprintf(fo, "%s", cfg.str().c_str()); p += strlen(KERNCONFTAG); fprintf(fo, "%s", p); - sbuf_delete(sb); fclose(fo); moveifchanged(path("config.c.new"), path("config.c")); cfgfile_removeall(); diff --git a/usr.sbin/config/mkmakefile.cc b/usr.sbin/config/mkmakefile.cc --- a/usr.sbin/config/mkmakefile.cc +++ b/usr.sbin/config/mkmakefile.cc @@ -380,7 +380,8 @@ struct file_list *tp; struct device *dp; struct opt *op; - char *wd, *rfile, *compilewith, *depends, *clean, *warning; + configword wd; + char *rfile, *compilewith, *depends, *clean, *warning; const char *objprefix; int compile, match, nreqs, std, filetype, negate, imp_rule, no_ctfconvert, no_obj, before_depend, nowerror; @@ -400,33 +401,34 @@ * [ nowerror ] [ local ] */ wd = get_word(fp); - if (wd == (char *)EOF) { + if (wd.eof()) { (void) fclose(fp); return; } - if (wd == NULL) + if (wd.eol()) goto next; if (wd[0] == '#') { - while (((wd = get_word(fp)) != (char *)EOF) && wd) + while (!(wd = get_word(fp)).eof() && !wd.eol()) ; goto next; } if (eq(wd, "include")) { wd = get_quoted_word(fp); - if (wd == (char *)EOF || wd == NULL) + if (wd.eof() || wd.eol()) errout("%s: missing include filename.\n", fname); - (void) snprintf(ifname, sizeof(ifname), "../../%s", wd); + (void) snprintf(ifname, sizeof(ifname), "../../%s", + wd->c_str()); read_file(ifname); - while (((wd = get_word(fp)) != (char *)EOF) && wd) + while (!(wd = get_word(fp)).eof() && !wd.eol()) ; goto next; } rfile = ns(wd); wd = get_word(fp); - if (wd == (char *)EOF) + if (wd.eof()) return; - if (wd == NULL) + if (wd.eol()) errout("%s: No type for %s.\n", fname, rfile); tp = fl_lookup(rfile); compile = 0; @@ -449,9 +451,9 @@ std = 1; else if (!eq(wd, "optional")) errout("%s: \"%s\" %s must be optional or standard\n", - fname, wd, rfile); - for (wd = get_word(fp); wd; wd = get_word(fp)) { - if (wd == (char *)EOF) + fname, wd->c_str(), rfile); + for (wd = get_word(fp); !wd.eol(); wd = get_word(fp)) { + if (wd.eof()) return; if (eq(wd, "!")) { negate = 1; @@ -489,7 +491,7 @@ } if (eq(wd, "dependency")) { wd = get_quoted_word(fp); - if (wd == (char *)EOF || wd == NULL) + if (wd.eof() || wd.eol()) errout("%s: %s missing dependency string.\n", fname, rfile); depends = ns(wd); @@ -497,7 +499,7 @@ } if (eq(wd, "clean")) { wd = get_quoted_word(fp); - if (wd == (char *)EOF || wd == NULL) + if (wd.eof() || wd.eol()) errout("%s: %s missing clean file list.\n", fname, rfile); clean = ns(wd); @@ -505,7 +507,7 @@ } if (eq(wd, "compile-with")) { wd = get_quoted_word(fp); - if (wd == (char *)EOF || wd == NULL) + if (wd.eof() || wd.eol()) errout("%s: %s missing compile command string.\n", fname, rfile); compilewith = ns(wd); @@ -513,7 +515,7 @@ } if (eq(wd, "warning")) { wd = get_quoted_word(fp); - if (wd == (char *)EOF || wd == NULL) + if (wd.eof() || wd.eol()) errout("%s: %s missing warning text string.\n", fname, rfile); warning = ns(wd); @@ -521,7 +523,7 @@ } if (eq(wd, "obj-prefix")) { wd = get_quoted_word(fp); - if (wd == (char *)EOF || wd == NULL) + if (wd.eof() || wd.eol()) errout("%s: %s missing object prefix string.\n", fname, rfile); objprefix = ns(wd); @@ -542,7 +544,7 @@ nreqs++; if (std) errout("standard entry %s has optional inclusion specifier %s!\n", - rfile, wd); + rfile, wd->c_str()); STAILQ_FOREACH(dp, &dtab, d_next) if (eq(dp->d_name, wd)) { if (negate) diff --git a/usr.sbin/config/mkoptions.c b/usr.sbin/config/mkoptions.cc rename from usr.sbin/config/mkoptions.c rename to usr.sbin/config/mkoptions.cc --- a/usr.sbin/config/mkoptions.c +++ b/usr.sbin/config/mkoptions.cc @@ -141,7 +141,7 @@ static void do_option(char *name) { - char *file, *inw; + char *file; const char *basefile; struct opt_list *ol; struct opt *op; @@ -198,18 +198,17 @@ seen = 0; tidy = 0; for (;;) { - char *cp; + configword cp, inw; char *invalue; /* get the #define */ - if ((inw = get_word(inf)) == NULL || inw == (char *)EOF) + if ((inw = get_word(inf)).eol() || inw.eof()) break; /* get the option name */ - if ((inw = get_word(inf)) == NULL || inw == (char *)EOF) + if ((inw = get_word(inf)).eol() || inw.eof()) break; - inw = ns(inw); /* get the option value */ - if ((cp = get_word(inf)) == NULL || cp == (char *)EOF) + if ((cp = get_word(inf)).eol() || cp.eof()) break; /* option value */ invalue = ns(cp); /* malloced */ @@ -224,25 +223,25 @@ if (!eq(inw, name) && !ol) { fprintf(stderr, "WARNING: unknown option `%s' removed from %s\n", - inw, file); + inw->c_str(), file); tidy++; } else if (ol != NULL && !eq(basefile, ol->o_file)) { fprintf(stderr, "WARNING: option `%s' moved from %s to %s\n", - inw, basefile, ol->o_file); + inw->c_str(), basefile, ol->o_file); tidy++; } else { op = (struct opt *) calloc(1, sizeof *op); if (op == NULL) err(EXIT_FAILURE, "calloc"); - op->op_name = inw; + op->op_name = ns(inw); op->op_value = invalue; SLIST_INSERT_HEAD(&op_head, op, op_next); } /* EOL? */ cp = get_word(inf); - if (cp == (char *)EOF) + if (cp.eof()) break; } (void)fclose(inf); @@ -364,25 +363,26 @@ read_option_file(const char *fname, int flags) { FILE *fp; - char *wd, *optname, *val; + configword wd; + char *optname, *val; char genopt[MAXPATHLEN]; fp = fopen(fname, "r"); if (fp == NULL) return (0); - while ((wd = get_word(fp)) != (char *)EOF) { - if (wd == NULL) + while (!(wd = get_word(fp)).eof()) { + if (wd.eol()) continue; if (wd[0] == '#') { - while (((wd = get_word(fp)) != (char *)EOF) && wd) + while (!(wd = get_word(fp)).eof() && !wd.eol()) continue; continue; } optname = ns(wd); - val = get_word(fp); - if (val == (char *)EOF) + wd = get_word(fp); + if (wd.eof()) return (1); - if (val == NULL) { + if (wd.eol()) { if (flags) { fprintf(stderr, "%s: compat file requires two" " words per line at %s\n", fname, optname); @@ -391,10 +391,11 @@ char *s = ns(optname); (void)snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s)); - val = genopt; + val = ns(genopt); free(s); + } else { + val = ns(wd); } - val = ns(val); if (flags == 0) insert_option(fname, optname, val); else