summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbird2tori <bird-github@anduin.net>2023-05-13 06:22:36 +0200
committerGitHub <noreply@github.com>2023-05-12 21:22:36 -0700
commit241bf4c42c2403f0ccae3d52cc610d5cec5d8c2e (patch)
tree50f52b82343d8908e2dab3c3720176a11a2e0d72
parent563a03be817a8ce08380605c9fe495ceae362d69 (diff)
downloadyasm-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.c201
-rw-r--r--modules/preprocs/nasm/nasm-preproc.c20
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;