diff options
author | bird2tori <bird-github@anduin.net> | 2023-05-13 06:22:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-12 21:22:36 -0700 |
commit | 241bf4c42c2403f0ccae3d52cc610d5cec5d8c2e (patch) | |
tree | 50f52b82343d8908e2dab3c3720176a11a2e0d72 | |
parent | 563a03be817a8ce08380605c9fe495ceae362d69 (diff) | |
download | yasm-241bf4c42c2403f0ccae3d52cc610d5cec5d8c2e.tar.gz |
More makedep features (#80)
yasm.c: Added -MD, -MT and -MP options similar to gcc. Also added --makedep-dos2unix-slash for helping users of NUG make (and similar) on Windows. The -MD option does both assembling and Makefile dependency generation in one go, which convenient and a little quicker.
nasm-preproc.c: Have to always gather dependencies to support -MD. Minimal cost.
Co-authored-by: knut st. osmundsen <bird-skylake@anduin.net>
-rw-r--r-- | frontends/yasm/yasm.c | 201 | ||||
-rw-r--r-- | modules/preprocs/nasm/nasm-preproc.c | 20 |
2 files changed, 188 insertions, 33 deletions
diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index 7ac141e6..d11147ec 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -70,6 +70,10 @@ static int special_options = 0; static int preproc_only = 0; static unsigned int force_strict = 0; static int generate_make_dependencies = 0; +static int makedep_with_empty_recipts = 0; +static int makedep_dos2unix_slash = 0; +/*@null@*/ /*@only@*/ static const char *makedep_out_filename = NULL; +/*@null@*/ /*@only@*/ static const char *makedep_target = NULL; static int warning_error = 0; /* warnings being treated as errors */ static FILE *errfile; /*@null@*/ /*@only@*/ static char *error_filename = NULL; @@ -105,7 +109,11 @@ static int preproc_only_handler(char *cmd, /*@null@*/ char *param, int extra); static int opt_include_option(char *cmd, /*@null@*/ char *param, int extra); static int opt_preproc_option(char *cmd, /*@null@*/ char *param, int extra); static int opt_ewmsg_handler(char *cmd, /*@null@*/ char *param, int extra); +static int opt_makedep_and_assemble_handler(char *cmd, /*@null@*/ char *param, int extra); +static int opt_makedep_empty_handler(char *cmd, /*@null@*/ char *param, int extra); +static int opt_makedep_target_handler(char *cmd, /*@null@*/ char *param, int extra); static int opt_makedep_handler(char *cmd, /*@null@*/ char *param, int extra); +static int opt_makedep_dos2unix_slash_handler(char *cmd, /*@null@*/ char *param, int extra); static int opt_prefix_handler(char *cmd, /*@null@*/ char *param, int extra); static int opt_suffix_handler(char *cmd, /*@null@*/ char *param, int extra); #if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS) @@ -137,6 +145,10 @@ static void apply_preproc_standard_macros(const yasm_stdmac *stdmacs); static void apply_preproc_saved_options(void); static void print_list_keyword_desc(const char *name, const char *keyword); +#ifndef MAX +# define MAX(a, b) ( ((a) > (b)) ? (a) : (b) ) +#endif + /* values for special_options */ #define SPECIAL_SHOW_HELP 0x01 #define SPECIAL_SHOW_VERSION 0x02 @@ -178,8 +190,18 @@ static opt_option options[] = N_("inhibits warning messages"), NULL }, { 'W', NULL, 0, opt_warning_handler, 0, N_("enables/disables warning"), NULL }, - { 'M', NULL, 0, opt_makedep_handler, 0, + { 0, "MD", 1, opt_makedep_and_assemble_handler, 0, + N_("generate Makefile dependencies and assemble normally"), + N_("file")}, + { 0, "MP", 0, opt_makedep_empty_handler, 0, + N_("generate empty Makefile recipts for the include files"), NULL }, + { 0, "MT", 1, opt_makedep_target_handler, 0, + N_("the Makefile target to associate the dependencies with"), + N_("target")}, + { 'M', NULL, 0, opt_makedep_handler, 0, /* -M must come after -MD and -MP'! */ N_("generate Makefile dependencies on stdout"), NULL }, + { 0, "makedep-dos2unix-slash", 0, opt_makedep_dos2unix_slash_handler, 0, + N_("convert DOS to UNIX slashes in Makefile dependencies file"), NULL }, { 'Z', NULL, 1, opt_error_file, 0, N_("redirect error messages to file"), N_("file") }, { 's', NULL, 0, opt_error_stdout, 0, @@ -247,12 +269,129 @@ typedef struct constcharparam { static constcharparam_head preproc_options; +static char * +dos2unix_slash(char *path) +{ + char *slash = strchr(path, '\\'); + while (slash) { + *slash++ = '/'; + slash = strchr(slash, '\\'); + } + return path; +} + +static int +do_generate_make_dependencies(void) +{ + size_t empty_recipts_alloc = 0; + size_t empty_recipts_len = 0; + char *empty_recipts = NULL; + char *preproc_buf; + size_t linelen; + size_t got; + FILE *depout = stdout; + const char *target; + + /* Open the -MD <file>. */ + if ( makedep_out_filename != NULL + && strcmp(makedep_out_filename, "-") != 0) { + depout = open_file(makedep_out_filename, "wt"); + if (!depout) + return EXIT_FAILURE; + } + + /* -MT (and later -MQ?) can be used to specify the target name. + If not given, fall back on the object file. */ + target = makedep_target ? makedep_target : obj_filename; + + /* Make sure preproc_buf is large enough for either of the main + file names to avoid checking later (very ulikely that it isn't). */ + linelen = strlen(target); + got = strlen(in_filename); + preproc_buf = yasm_xmalloc(MAX(PREPROC_BUF_SIZE, MAX(got, linelen) + 1)); + + /* The target (the object file) to add the dependencies to. */ + if (!makedep_dos2unix_slash || makedep_target == NULL) + fputs(target, depout); + else + fputs(dos2unix_slash(memcpy(preproc_buf, target, linelen + 1)), + depout); + + /* The source file (no empty rule for it, thus the code duplication). */ + linelen += 2 + got; + if (linelen <= 72) + fputs(": ", depout); + else { + fputs(": \\\n ", depout); + linelen = 1 + got; + } + if (!makedep_dos2unix_slash) + fwrite(in_filename, got, 1, depout); + else + fwrite(dos2unix_slash(memcpy(preproc_buf, in_filename, got + 1)), + got, 1, depout); + + /* Now the include files. */ + while ((got = yasm_preproc_get_included_file(cur_preproc, preproc_buf, + PREPROC_BUF_SIZE)) != 0) { + linelen += 1 + got; + if (linelen <= 72) + fputc(' ', depout); + else { + fputs(" \\\n ", depout); + linelen = 1 + got; + } + if (makedep_dos2unix_slash) + dos2unix_slash(preproc_buf); + fwrite(preproc_buf, got, 1, depout); + + if (makedep_with_empty_recipts) { + /* We only get one shot at each include file, so we generate the + dummy recipts in a buffer while we're writing the dependencies + for the object file. (The empty recipts makes make shut up + about deleted includes.) */ + static const char empty_tail[] = ":\n\n"; + size_t cur_len = empty_recipts_len; + + empty_recipts_len = cur_len + got + sizeof(empty_tail) - 1; + if (empty_recipts_len >= empty_recipts_alloc) { + if (empty_recipts_alloc == 0) + empty_recipts_alloc = 4096; + while (empty_recipts_len >= empty_recipts_alloc) + empty_recipts_alloc *= 2; + empty_recipts = yasm_xrealloc(empty_recipts, + empty_recipts_alloc); + } + + memcpy(&empty_recipts[cur_len], preproc_buf, got); + cur_len += got; + memcpy(&empty_recipts[cur_len], empty_tail, sizeof(empty_tail)); + } + } + + fputc('\n', depout); + yasm_xfree(preproc_buf); + + if (empty_recipts) { + fputc('\n', depout); + fwrite(empty_recipts, empty_recipts_len, 1, depout); + yasm_xfree(empty_recipts); + } + + if ( depout != stdout + && fclose(depout) != 0) { + print_error(_("error writing `%s'"), makedep_out_filename); + return EXIT_FAILURE; + } + + return 0; +} + static int do_preproc_only(void) { yasm_linemap *linemap; char *preproc_buf; - size_t got; const char *base_filename; FILE *out = NULL; yasm_errwarns *errwarns = yasm_errwarns_create(); @@ -301,25 +440,7 @@ do_preproc_only(void) /* Pre-process until done */ if (generate_make_dependencies) { - size_t totlen; - - preproc_buf = yasm_xmalloc(PREPROC_BUF_SIZE); - - fprintf(stdout, "%s: %s", obj_filename, in_filename); - totlen = strlen(obj_filename)+2+strlen(in_filename); - - while ((got = yasm_preproc_get_included_file(cur_preproc, preproc_buf, - PREPROC_BUF_SIZE)) != 0) { - totlen += got; - if (totlen > 72) { - fputs(" \\\n ", stdout); - totlen = 2; - } - fputc(' ', stdout); - fwrite(preproc_buf, got, 1, stdout); - } - fputc('\n', stdout); - yasm_xfree(preproc_buf); + do_generate_make_dependencies(); } else { while ((preproc_buf = yasm_preproc_get_line(cur_preproc)) != NULL) { fputs(preproc_buf, out); @@ -573,6 +694,10 @@ do_assemble(void) fclose(list); } + /* Generate make dependency. */ + if (generate_make_dependencies) + do_generate_make_dependencies(); + yasm_errwarns_output_all(errwarns, linemap, warning_error, print_yasm_error, print_yasm_warning); @@ -1171,6 +1296,32 @@ opt_ewmsg_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra) } static int +opt_makedep_and_assemble_handler(/*@unused@*/ char *cmd, char *param, + /*@unused@*/ int extra) +{ + generate_make_dependencies = 1; + makedep_out_filename = param; + return 0; +} + +static int +opt_makedep_empty_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, + /*@unused@*/ int extra) +{ + makedep_with_empty_recipts = 1; + return 0; +} + +static int +opt_makedep_target_handler(/*@unused@*/ char *cmd, char *param, + /*@unused@*/ int extra) +{ + makedep_target = param; + return 0; +} + + +static int opt_makedep_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, /*@unused@*/ int extra) { @@ -1182,6 +1333,14 @@ opt_makedep_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, } static int +opt_makedep_dos2unix_slash_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, + /*@unused@*/ int extra) +{ + makedep_dos2unix_slash = 1; + return 0; +} + +static int opt_prefix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra) { if (global_prefix) diff --git a/modules/preprocs/nasm/nasm-preproc.c b/modules/preprocs/nasm/nasm-preproc.c index 96d66dbc..75e60157 100644 --- a/modules/preprocs/nasm/nasm-preproc.c +++ b/modules/preprocs/nasm/nasm-preproc.c @@ -151,7 +151,8 @@ nasm_preproc_create(const char *in_filename, yasm_symtab *symtab, nasm_symtab = symtab; cur_lm = lm; cur_errwarns = errwarns; - preproc_deps = NULL; + preproc_deps = yasm_xmalloc(sizeof(struct preproc_dep_head)); + STAILQ_INIT(preproc_deps); done_dep_preproc = 0; preproc_nasm->line = NULL; preproc_nasm->file_name = NULL; @@ -176,8 +177,12 @@ nasm_preproc_destroy(yasm_preproc *preproc) if (preproc_nasm->in) fclose(preproc_nasm->in); yasm_xfree(preproc); - if (preproc_deps) - yasm_xfree(preproc_deps); + while (!STAILQ_EMPTY(preproc_deps)) { + preproc_dep *dep = STAILQ_FIRST(preproc_deps); + STAILQ_REMOVE_HEAD(preproc_deps, link); + yasm_xfree(dep->name); + yasm_xfree(dep); + } yasm_xfree(nasm_src_set_fname(NULL)); } @@ -222,10 +227,6 @@ nasm_preproc_add_dep(char *name) { preproc_dep *dep; - /* If not processing dependencies, simply return */ - if (!preproc_deps) - return; - /* Save in preproc_deps */ dep = yasm_xmalloc(sizeof(preproc_dep)); dep->name = yasm__xstrdup(name); @@ -236,11 +237,6 @@ static size_t nasm_preproc_get_included_file(yasm_preproc *preproc, /*@out@*/ char *buf, size_t max_size) { - if (!preproc_deps) { - preproc_deps = yasm_xmalloc(sizeof(struct preproc_dep_head)); - STAILQ_INIT(preproc_deps); - } - for (;;) { char *line; |