From 99ec64a7a06e452a79ac7bd855b1ab72676d2ee0 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 14 Jul 2022 01:15:29 +0200 Subject: [PATCH] Add support for specifying the output directory (avoiding nasty cd tricks when using it in build scripts). --- util/LLgen/build.lua | 35 +++++++++++++++++++++++++++++++---- util/LLgen/doc/LLgen.1 | 3 +++ util/LLgen/src/extern.h | 39 +++++++++++++++++++++------------------ util/LLgen/src/global.c | 13 +++++++------ util/LLgen/src/io.h | 23 ++++++++++++----------- util/LLgen/src/machdep.c | 23 +++++++++++++---------- util/LLgen/src/main.c | 26 +++++++++++++++++--------- util/LLgen/src/utils.c | 27 +++++++++++++++++++++++++++ 8 files changed, 131 insertions(+), 58 deletions(-) create mode 100644 util/LLgen/src/utils.c diff --git a/util/LLgen/build.lua b/util/LLgen/build.lua index ea7cdf122..8e5bd4ca7 100644 --- a/util/LLgen/build.lua +++ b/util/LLgen/build.lua @@ -1,6 +1,13 @@ clibrary { name = "headers", - hdrs = { "./src/*.h" } -- rm alloc.h + hdrs = { + "./src/cclass.h", + "./src/extern.h", + "./src/io.h", + "./src/Lpars.h", + "./src/sets.h", + "./src/types.h", + } } cprogram { @@ -10,11 +17,28 @@ cprogram { -- tokens.c. If LLgen.g or tokens.g gets updated, they need -- rebuilding. Use the bootstrap target to do this. - srcs = { "./src/*.c" }, + srcs = { + "./src/LLgen.c", + "./src/Lpars.c", + "./src/alloc.c", + "./src/cclass.c", + "./src/check.c", + "./src/compute.c", + "./src/gencode.c", + "./src/global.c", + "./src/machdep.c", + "./src/main.c", + "./src/name.c", + "./src/reach.c", + "./src/savegram.c", + "./src/sets.c", + "./src/tokens.c", + "./src/utils.c", + }, deps = { "+headers" }, vars = { ["+cflags"] = { - "-DLIBDIR=\\\""..posix.getcwd().."/"..cwd().."/lib\\\"", + "-DLIBDIR=\\\""..cwd().."/lib\\\"", "-DNON_CORRECTING" }, } @@ -55,8 +79,11 @@ definerule("llgen", "util/LLgen+llgen", e.srcs, }, + vars = { + srcs = e.srcs + }, commands = { - "cd %{dir} && rm -f %{outs} && %{abspath(ins)}" + "rm -f %{outs} && %{ins[1]} -o%{dirname(outs[1])} %{srcs}" } } end diff --git a/util/LLgen/doc/LLgen.1 b/util/LLgen/doc/LLgen.1 index 0436ffa30..a50b900b3 100644 --- a/util/LLgen/doc/LLgen.1 +++ b/util/LLgen/doc/LLgen.1 @@ -76,6 +76,9 @@ If the flag is given more than once, will be more "verbose". If it is given three times, a complete description of the grammar will be supplied. +.IP \fB\-o\fP +Specifies the location of the output files. If not set, they +are placed in the current directory. .IP \fB\-x\fP the sets that are computed are extended with the nonterminal symbols and these extended sets are also included in the diff --git a/util/LLgen/src/extern.h b/util/LLgen/src/extern.h index d3b3b89d6..82d861dba 100644 --- a/util/LLgen/src/extern.h +++ b/util/LLgen/src/extern.h @@ -97,37 +97,40 @@ extern int strip_grammar; extern int in_production; /* LLgen.g */ -void LLparse(void); +extern void LLparse(void); /* check.c */ -void conflchecks(void); +extern void conflchecks(void); /* compute.c */ -void do_compute(void); -int empty(p_gram); -int t_safety(int, int, int, int); -int t_after(int, int, int); +extern void do_compute(void); +extern int empty(p_gram); +extern int t_safety(int, int, int, int); +extern int t_after(int, int, int); /* gencode.c */ -void gencode(int); +extern void gencode(int); /* machdep.c */ -void TMPNAM(string); -string libpath(string); +extern string maketempfile(void); +extern string libpath(string); /* main.c */ -void error(int lineno,string s,string t); -void warning(int lineno,string s,string t); -void fatal(int lineno,string s,string t); -void copyfile(string); -void install(string, string); +extern void error(int lineno,string s,string t); +extern void warning(int lineno,string s,string t); +extern void fatal(int lineno,string s,string t); +extern void copyfile(string); +extern void install(string, string); /* name.c */ -void name_init(void); -string store(string); -p_gram search(int, string, int); +extern void name_init(void); +extern string store(string); +extern p_gram search(int, string, int); /* reach.c */ -void co_reach(void); +extern void co_reach(void); + +/* utils.c */ +extern string aprintf(const char* fmt, ...); #endif /* EXTERN_H_ */ diff --git a/util/LLgen/src/global.c b/util/LLgen/src/global.c index e2fcc8599..8333f3684 100644 --- a/util/LLgen/src/global.c +++ b/util/LLgen/src/global.c @@ -45,15 +45,16 @@ FILE *fout; FILE *fpars; FILE *finput; FILE *fact; -char f_pars[L_tmpnam+sizeof(char)]; /* Add one more character for NULL, just in case of buggy implementations. */ -char f_temp[L_tmpnam+sizeof(char)]; +string f_dir; +string f_pars; +string f_temp; #ifdef NON_CORRECTING -char f_nc[20]; +string f_nc; #endif -char f_out[20]; +string f_out; string f_input; -char f_include[20]; -char f_rec[20]; +string f_include; +string f_rec; string e_noopen = "Cannot open %s"; int verbose; int wflag; diff --git a/util/LLgen/src/io.h b/util/LLgen/src/io.h index fdfe0d630..8b4d68e1a 100644 --- a/util/LLgen/src/io.h +++ b/util/LLgen/src/io.h @@ -20,22 +20,23 @@ /* FILES */ -# define OUTFILE "%s.output" /* -v option */ -# define HFILE "%spars.h" /* file for "#define's " */ -# define RFILE "%spars.c" /* Error recovery */ +# define OUTFILE "%s/%s.output" /* -v option */ +# define HFILE "%s/%spars.h" /* file for "#define's " */ +# define RFILE "%s/%spars.c" /* Error recovery */ #ifdef NON_CORRECTING -# define NCFILE "%sncor.c" /* Non-corrcting error recovery */ +# define NCFILE "%s/%sncor.c" /* Non-corrcting error recovery */ #endif extern FILE *finput; extern FILE *fpars; extern FILE *fact; extern FILE *fout; -extern char f_pars[]; -extern char f_temp[]; -extern char f_out[]; -extern string f_input; -extern char f_include[]; -extern char f_rec[]; +extern string f_dir; +extern string f_pars; +extern string f_temp; +extern string f_out; +extern string f_input; +extern string f_include; +extern string f_rec; #ifdef NON_CORRECTING -extern char f_nc[]; +extern string f_nc; #endif diff --git a/util/LLgen/src/machdep.c b/util/LLgen/src/machdep.c index cf43119d4..34df65332 100644 --- a/util/LLgen/src/machdep.c +++ b/util/LLgen/src/machdep.c @@ -18,6 +18,7 @@ #include #include #include +#include # include "extern.h" # include "types.h" @@ -39,18 +40,20 @@ string libpath(string s) char* libdir = getenv("LLGEN_LIB_DIR"); if (!libdir) libdir = LIBDIR; - length = strlen(libdir) + strlen(s) + 2; - p = (string) alloc(length); - strcpy(p,libdir); - strcat(p,"/"); - strcat(p,s); - return p; + return aprintf("%s/%s", libdir, s); } -void TMPNAM(string result) +string maketempfile() { - if (tmpnam(result)==NULL) - { + string tmp = getenv("TMP"); + if (!tmp) + tmp = "/tmp"; + + string filename = aprintf("%s/llgen-XXXXXX", tmp); + int fd = mkstemp(filename); + if (fd == -1) fatal(1, "Cannot create temporary file.", NULL); - } + + close(fd); + return filename; } diff --git a/util/LLgen/src/main.c b/util/LLgen/src/main.c index 217214f68..8f2a814c3 100644 --- a/util/LLgen/src/main.c +++ b/util/LLgen/src/main.c @@ -37,8 +37,9 @@ int main(int argc, register string argv[]) { register string arg; - TMPNAM(f_temp); - TMPNAM(f_pars); + f_dir = "."; + f_temp = maketempfile(); + f_pars = maketempfile(); /* Initialize */ @@ -116,6 +117,12 @@ int main(int argc, register string argv[]) case 'G': strip_grammar = 1; continue; + + case 'o': + case 'O': + f_dir = ++arg; + break; + default: fprintf(stderr, "illegal option : %c\n", *arg); exit(1); @@ -170,16 +177,16 @@ int main(int argc, register string argv[]) } name_init(); readgrammar(argc, argv); - sprintf(f_out, OUTFILE, prefix ? prefix : "LL"); + f_out = aprintf(OUTFILE, f_dir, prefix ? prefix : "LL"); /* for the following two filenames only one L is used; historical reasons ... */ - sprintf(f_include, HFILE, prefix ? prefix : "L"); - sprintf(f_rec, RFILE, prefix ? prefix : "L"); + f_include = aprintf(HFILE, f_dir, prefix ? prefix : "L"); + f_rec = aprintf(RFILE, f_dir, prefix ? prefix : "L"); #ifdef NON_CORRECTING if (non_corr) - sprintf(f_nc, NCFILE, prefix ? prefix : "L"); + f_nc = aprintf(NCFILE, f_dir, prefix ? prefix : "L"); #endif setinit(ntneeded); maxnt = &nonterms[nnonterms]; @@ -377,6 +384,7 @@ void install(string target, string source) register int c1, c2; register FILE *f1, *f2; int cnt; + string realtarget = (target[0] != '/') ? aprintf("%s/%s", f_dir, target) : target; /* * First open temporary, generated for source @@ -388,10 +396,10 @@ void install(string target, string source) /* * Now open target for reading */ - if ((f2 = fopen(target, "r")) == NULL) + if ((f2 = fopen(realtarget, "r")) == NULL) { fclose(f1); - copyto(target, f_pars); + copyto(realtarget, f_pars); return; } /* @@ -420,6 +428,6 @@ void install(string target, string source) { fatal(0, "%s : not a file generated by LLgen", target); } - copyto(target, f_pars); + copyto(realtarget, f_pars); } } diff --git a/util/LLgen/src/utils.c b/util/LLgen/src/utils.c new file mode 100644 index 000000000..7da06e9fa --- /dev/null +++ b/util/LLgen/src/utils.c @@ -0,0 +1,27 @@ +#include +#include +#include + +const char* aprintf(const char* fmt, ...) +{ + int n; + char* p; + va_list ap; + + va_start(ap, fmt); + n = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + p = malloc(n); + if (!p) + return NULL; + + va_start(ap, fmt); + vsnprintf(p, n, fmt, ap); + va_end(ap); + + return p; +} + +/* vim: set sw=4 ts=4 expandtab : */ +