summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-05-29 19:09:11 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-05-29 19:09:11 -0700
commit07b7b9e15efef5f19389a09fb65601b2a0c6ba13 (patch)
treee8e0dad76d7bea37e435c4f490937096baa03153
parentb037a67e68a0dcab179fc5dea7b2ef900cfec9d2 (diff)
downloadnasm-07b7b9e15efef5f19389a09fb65601b2a0c6ba13.tar.gz
Implement -MD, -MF, -MT, -MQ
Implement the dependency options: -MF: set the file to which dependencies are written. -MD: generate dependencies in parallel with compilation. -MT: set the name of the dependency target. -MQ: same as -MT, but *attempt* to quote it for Makefile safety.
-rw-r--r--nasm.c181
-rw-r--r--nasm.h4
-rw-r--r--preproc.c18
3 files changed, 177 insertions, 26 deletions
diff --git a/nasm.c b/nasm.c
index 484993a7..766248e1 100644
--- a/nasm.c
+++ b/nasm.c
@@ -38,7 +38,7 @@ struct forwrefinfo { /* info held on forward refs. */
static int get_bits(char *value);
static uint32_t get_cpu(char *cpu_str);
static void parse_cmdline(int, char **);
-static void assemble_file(char *);
+static void assemble_file(char *, FILE *);
static void register_output_formats(void);
static void report_error_gnu(int severity, const char *fmt, ...);
static void report_error_vc(int severity, const char *fmt, ...);
@@ -88,9 +88,12 @@ enum op_type {
op_normal, /* Preprocess and assemble */
op_preprocess, /* Preprocess only */
op_depend, /* Generate dependencies */
- op_depend_missing_ok, /* Generate dependencies, missing OK */
};
static enum op_type operating_mode;
+/* Dependency flags */
+static bool depend_missing_ok = false;
+static const char *depend_target = NULL;
+static const char *depend_file = NULL;
/*
* Which of the suppressible warnings are suppressed. Entry zero
@@ -133,7 +136,7 @@ static const char *suppressed_what[ERR_WARN_MAX+1] = {
* not preprocess their source file.
*/
-static void no_pp_reset(char *, int, efunc, evalfunc, ListGen *);
+static void no_pp_reset(char *, int, efunc, evalfunc, ListGen *, FILE *);
static char *no_pp_getline(void);
static void no_pp_cleanup(int);
static Preproc no_pp = {
@@ -241,6 +244,8 @@ static void define_macros_late(void)
int main(int argc, char **argv)
{
+ FILE *depends;
+
time(&official_compile_time);
pass0 = 1;
@@ -284,22 +289,39 @@ int main(int argc, char **argv)
/* define some macros dependent of command-line */
define_macros_late();
+ depends = NULL;
+ if (depend_file) {
+ depends = fopen(depend_file, "w");
+ if (!depends) {
+ report_error(ERR_FATAL | ERR_NOFILE,
+ "unable to open dependencies file `%s'",
+ depend_file);
+ }
+ }
+
+ if (!depend_target)
+ depend_target = outname;
+
switch (operating_mode) {
- case op_depend_missing_ok:
- pp_include_path(NULL); /* "assume generated" */
- /* fall through */
case op_depend:
{
char *line;
- preproc->reset(inname, 0, report_error, evaluate, &nasmlist);
+
+ if (!depends)
+ depends = stdout;
+
+ if (depend_missing_ok)
+ pp_include_path(NULL); /* "assume generated" */
+
+ preproc->reset(inname, 0, report_error, evaluate, &nasmlist,
+ depends);
if (outname[0] == '\0')
ofmt->filename(inname, outname, report_error);
ofile = NULL;
- fprintf(stdout, "%s: %s", outname, inname);
+ fprintf(depends, "%s: %s", depend_target, inname);
while ((line = preproc->getline()))
nasm_free(line);
preproc->cleanup(0);
- putc('\n', stdout);
}
break;
@@ -321,8 +343,12 @@ int main(int argc, char **argv)
location.known = false;
-/* pass = 1; */
- preproc->reset(inname, 2, report_error, evaluate, &nasmlist);
+ /* pass = 1; */
+ preproc->reset(inname, 2, report_error, evaluate, &nasmlist,
+ depends);
+ if (depends)
+ fprintf(depends, "%s: %s", depend_target, inname);
+
while ((line = preproc->getline())) {
/*
* We generate %line directives if needed for later programs
@@ -378,7 +404,7 @@ int main(int argc, char **argv)
ofmt->init(ofile, report_error, define_label, evaluate);
- assemble_file(inname);
+ assemble_file(inname, depends);
if (!terminate_after_phase) {
ofmt->cleanup(using_debug_info);
@@ -398,6 +424,12 @@ int main(int argc, char **argv)
break;
}
+ if (depends) {
+ putc('\n', depends);
+ if (depends != stdout)
+ fclose(depends);
+ }
+
if (want_usage)
usage();
@@ -448,6 +480,88 @@ static void copy_filename(char *dst, const char *src)
strncpy(dst, src, FILENAME_MAX);
}
+/*
+ * Convert a string to Make-safe form
+ */
+static char *quote_for_make(const char *str)
+{
+ const char *p;
+ char *os, *q;
+
+ size_t n = 1; /* Terminating zero */
+ size_t nbs = 0;
+
+ if (!str)
+ return NULL;
+
+ for (p = str; *p; p++) {
+ switch (*p) {
+ case ' ':
+ case '\t':
+ /* Convert N backslashes + ws -> 2N+1 backslashes + ws */
+ n += nbs + 2;
+ nbs = 0;
+ break;
+ case '$':
+ case '#':
+ nbs = 0;
+ n += 2;
+ break;
+ case '\\':
+ nbs++;
+ n++;
+ break;
+ default:
+ nbs = 0;
+ n++;
+ break;
+ }
+ }
+
+ /* Convert N backslashes at the end of filename to 2N backslashes */
+ if (nbs)
+ n += nbs;
+
+ os = q = nasm_malloc(n);
+
+ nbs = 0;
+ for (p = str; *p; p++) {
+ switch (*p) {
+ case ' ':
+ case '\t':
+ while (nbs--)
+ *q++ = '\\';
+ *q++ = '\\';
+ *q++ = *p;
+ break;
+ case '$':
+ *q++ = *p;
+ *q++ = *p;
+ nbs = 0;
+ break;
+ case '#':
+ *q++ = '\\';
+ *q++ = *p;
+ nbs = 0;
+ break;
+ case '\\':
+ *q++ = *p;
+ nbs++;
+ break;
+ default:
+ *q++ = *p;
+ nbs = 0;
+ break;
+ }
+ }
+ while (nbs--)
+ *q++ = '\\';
+
+ *q = '\0';
+
+ return os;
+}
+
struct textargs {
const char *label;
int value;
@@ -709,7 +823,37 @@ static bool process_arg(char *p, char *q)
break;
case 'M':
- operating_mode = p[2] == 'G' ? op_depend_missing_ok : op_depend;
+ switch (p[2]) {
+ case 0:
+ case 'M':
+ operating_mode = op_depend;
+ break;
+ case 'G':
+ operating_mode = op_depend;
+ depend_missing_ok = true;
+ break;
+ case 'D':
+ depend_file = q;
+ advance = true;
+ break;
+ case 'T':
+ depend_target = q;
+ advance = true;
+ break;
+ case 'Q':
+ depend_target = quote_for_make(q);
+ advance = true;
+ break;
+ default:
+ report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
+ "unknown dependency option `-M%c'", p[2]);
+ break;
+ }
+ if (advance && (!q || !q[0])) {
+ report_error(ERR_NONFATAL|ERR_NOFILE|ERR_USAGE,
+ "option `-M%c' requires a parameter", p[2]);
+ break;
+ }
break;
case '-':
@@ -969,7 +1113,7 @@ static const char *directives[] = {
};
static enum directives getkw(char **directive, char **value);
-static void assemble_file(char *fname)
+static void assemble_file(char *fname, FILE *depends)
{
char *directive, *value, *p, *q, *special, *line, debugid[80];
insn output_ins;
@@ -1013,7 +1157,11 @@ static void assemble_file(char *fname)
raa_free(offsets);
offsets = raa_init();
}
- preproc->reset(fname, pass1, report_error, evaluate, &nasmlist);
+ preproc->reset(fname, pass1, report_error, evaluate, &nasmlist,
+ pass1 == 2 ? depends : NULL);
+ if (pass1 == 2 && depends)
+ fprintf(depends, "%s: %s", depend_target, inname);
+
globallineno = 0;
if (passn == 1)
location.known = true;
@@ -1802,7 +1950,7 @@ static ListGen *no_pp_list;
static int32_t no_pp_lineinc;
static void no_pp_reset(char *file, int pass, efunc error, evalfunc eval,
- ListGen * listgen)
+ ListGen * listgen, FILE *depends)
{
src_set_fname(nasm_strdup(file));
src_set_linnum(0);
@@ -1815,6 +1963,7 @@ static void no_pp_reset(char *file, int pass, efunc error, evalfunc eval,
no_pp_list = listgen;
(void)pass; /* placate compilers */
(void)eval; /* placate compilers */
+ (void)depends; /* placate compilers */
}
static char *no_pp_getline(void)
diff --git a/nasm.h b/nasm.h
index b1f05116..4c7b3386 100644
--- a/nasm.h
+++ b/nasm.h
@@ -291,7 +291,7 @@ typedef expr *(*evalfunc) (scanner sc, void *scprivate,
#define EXPR_SEGBASE (EXPR_REG_END+4)
/*
- * Preprocessors ought to look like this:
+ * preprocessors ought to look like this:
*/
typedef struct preproc_ops {
/*
@@ -299,7 +299,7 @@ typedef struct preproc_ops {
* of the pass, an error reporting function, an evaluator
* function, and a listing generator to talk to.
*/
- void (*reset) (char *, int, efunc, evalfunc, ListGen *);
+ void (*reset) (char *, int, efunc, evalfunc, ListGen *, FILE *);
/*
* Called to fetch a line of preprocessed source. The line
diff --git a/preproc.c b/preproc.c
index 482d6af2..7a305b39 100644
--- a/preproc.c
+++ b/preproc.c
@@ -327,6 +327,7 @@ static efunc _error; /* Pointer to client-provided error reporting fu
static evalfunc evaluate;
static int pass; /* HACK: pass 0 = generate dependencies only */
+static FILE *deplist; /* Write dependencies to this FILE */
static uint64_t unique; /* unique identifier numbers */
@@ -1275,13 +1276,13 @@ static FILE *inc_fopen(char *file)
strcpy(combine, prefix);
strcat(combine, file);
fp = fopen(combine, "r");
- if (pass == 0 && fp) {
+ if (fp && deplist) {
namelen += strlen(combine) + 1;
if (namelen > 62) {
- printf(" \\\n ");
+ fprintf(deplist, " \\\n ");
namelen = 2;
}
- printf(" %s", combine);
+ fprintf(deplist, " %s", combine);
}
nasm_free(combine);
if (fp)
@@ -1293,13 +1294,13 @@ static FILE *inc_fopen(char *file)
if (!prefix) {
/* -MG given and file not found */
- if (pass == 0) {
+ if (deplist) {
namelen += strlen(file) + 1;
if (namelen > 62) {
- printf(" \\\n ");
- namelen = 2;
+ fprintf(deplist, " \\\n ");
+ namelen = 2;
}
- printf(" %s", file);
+ fprintf(deplist, " %s", file);
}
return NULL;
}
@@ -3733,7 +3734,7 @@ static void error(int severity, const char *fmt, ...)
static void
pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
- ListGen * listgen)
+ ListGen * listgen, FILE * adeplist)
{
_error = errfunc;
cstk = NULL;
@@ -3762,6 +3763,7 @@ pp_reset(char *file, int apass, efunc errfunc, evalfunc eval,
list = listgen;
evaluate = eval;
pass = apass;
+ deplist = adeplist;
}
static char *pp_getline(void)