git: 83d7ed8af3d9 - main - config: drop dependency on libsbuf
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 09 Feb 2023 05:27:42 UTC
The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=83d7ed8af3d9eab0567749d9d6e99a7e24d17817 commit 83d7ed8af3d9eab0567749d9d6e99a7e24d17817 Author: Kyle Evans <kevans@FreeBSD.org> AuthorDate: 2023-02-09 04:56:10 +0000 Commit: Kyle Evans <kevans@FreeBSD.org> CommitDate: 2023-02-09 04:56:10 +0000 config: drop dependency on libsbuf Use an std::stringstream instead. get_word() and get_quoted_word() both return a buffer that's presumed to not need release, so solve this by returning a new special configword type that holds a string or eof/eol state. This cleans up caller checking for EOF/EOL to make it more explicit what they're doing, at least in the EOL cases which previously checked for NULL. Sponsored by: Klara, Inc. Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D38276 --- usr.sbin/config/Makefile | 6 +- usr.sbin/config/config.h | 57 +++++++++++- usr.sbin/config/{main.c => main.cc} | 119 ++++++++++++-------------- usr.sbin/config/mkmakefile.cc | 38 ++++---- usr.sbin/config/{mkoptions.c => mkoptions.cc} | 39 +++++---- 5 files changed, 152 insertions(+), 107 deletions(-) diff --git a/usr.sbin/config/Makefile b/usr.sbin/config/Makefile index 241a501f52af..dab9aa43f036 100644 --- a/usr.sbin/config/Makefile +++ b/usr.sbin/config/Makefile @@ -5,8 +5,8 @@ SRCDIR:=${.PARSEDIR:tA} 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 @@ CFLAGS+= -I. -I${SRCDIR} 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 index 7d97d66979e2..8555bf000d0f 100644 --- a/usr.sbin/config/config.h +++ b/usr.sbin/config/config.h @@ -35,13 +35,66 @@ /* * Config. */ -#include <sys/cdefs.h> /* __BEGIN_DECLS/__END_DECLS */ #include <sys/types.h> #include <sys/queue.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> +#ifdef __cplusplus +#include <string> + +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); + } + + 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 { @@ -186,8 +239,6 @@ extern char kernconfstr[]; 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 similarity index 90% rename from usr.sbin/config/main.c rename to usr.sbin/config/main.cc index 988c296d97ce..ef24d373c8b0 100644 --- a/usr.sbin/config/main.c +++ b/usr.sbin/config/main.cc @@ -45,19 +45,21 @@ static const char rcsid[] = #include <sys/types.h> #include <sys/stat.h> -#include <sys/sbuf.h> #include <sys/file.h> #include <sys/mman.h> #include <sys/param.h> #include <assert.h> #include <ctype.h> +#include <dirent.h> #include <err.h> +#include <iostream> +#include <sstream> #include <stdio.h> #include <string.h> #include <sysexits.h> #include <unistd.h> -#include <dirent.h> + #include "y.tab.h" #include "config.h" #include "configvers.h" @@ -111,7 +113,7 @@ struct hdr_list { 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 @@ usage(void) 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 @@ get_line_buf(void) * NULL on end of line * pointer to the word otherwise */ -char * +configword get_word(FILE *fp) { int ch; @@ -351,7 +350,7 @@ begin: 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 @@ begin: 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 @@ begin: * 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 @@ begin: 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 @@ begin: goto begin; } else - return (NULL); + return (configword().eol(true)); } if (ch == '"' || ch == '\'') { int quote = ch; @@ -419,7 +418,7 @@ begin: 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 @@ begin: 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 @@ path(const char *file) * 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 @@ configfile_dynamic(struct sbuf *sb) 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 @@ configfile_dynamic(struct sbuf *sb) * 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 @@ configfile_filebased(struct sbuf *sb) } 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 @@ static void 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 @@ configfile(void) 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 @@ configfile(void) 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 index 2aabb9e0f347..472f85fa4bc2 100644 --- a/usr.sbin/config/mkmakefile.cc +++ b/usr.sbin/config/mkmakefile.cc @@ -380,7 +380,8 @@ read_file(char *fname) 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 @@ next: * [ 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 @@ next: 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 @@ next: } 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 @@ next: } 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 @@ next: } 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 @@ next: } 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 @@ next: } 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 @@ next: 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 similarity index 94% rename from usr.sbin/config/mkoptions.c rename to usr.sbin/config/mkoptions.cc index b93e56e3a491..f45c1026417c 100644 --- a/usr.sbin/config/mkoptions.c +++ b/usr.sbin/config/mkoptions.cc @@ -141,7 +141,7 @@ options(void) 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 @@ do_option(char *name) 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 @@ do_option(char *name) 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 @@ static int 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 @@ read_option_file(const char *fname, int flags) 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