regularized spelling of license to match name of LICENSE file
[platform/upstream/nasm.git] / nasm.c
diff --git a/nasm.c b/nasm.c
index b7c1c66..b1c2239 100644 (file)
--- a/nasm.c
+++ b/nasm.c
@@ -2,7 +2,7 @@
  *
  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
+ * redistributable under the license given in the file "LICENSE"
  * distributed in the NASM archive.
  */
 
 #include <string.h>
 #include <ctype.h>
 #include <inttypes.h>
+#include <limits.h>
 
 #include "nasm.h"
 #include "nasmlib.h"
+#include "float.h"
 #include "stdscan.h"
 #include "insns.h"
 #include "preproc.h"
@@ -36,7 +38,6 @@ 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 int getkw(char **directive, char **value);
 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, ...);
@@ -47,7 +48,7 @@ static void usage(void);
 static efunc report_error;
 
 static int using_debug_info, opt_verbose_info;
-int tasm_compatible_mode = FALSE;
+bool tasm_compatible_mode = false;
 int pass0;
 int maxbits = 0;
 int globalrel = 0;
@@ -67,9 +68,9 @@ int optimizing = -1;            /* number of optimization passes to take */
 static int sb, cmd_sb = 16;     /* by default */
 static uint32_t cmd_cpu = IF_PLEVEL;       /* highest level by default */
 static uint32_t cpu = IF_PLEVEL;   /* passed to insn_size & assemble.c */
-int global_offset_changed;      /* referenced in labels.c */
+bool global_offset_changed;      /* referenced in labels.c */
 
-static loc_t location;
+static struct location location;
 int in_abs_seg;                 /* Flag we are in ABSOLUTE seg */
 int32_t abs_seg;                   /* ABSOLUTE segment basis */
 int32_t abs_offset;                /* ABSOLUTE offset */
@@ -77,7 +78,7 @@ int32_t abs_offset;                /* ABSOLUTE offset */
 static struct RAA *offsets;
 
 static struct SAA *forwrefs;    /* keep track of forward references */
-static struct forwrefinfo *forwref;
+static const struct forwrefinfo *forwref;
 
 static Preproc *preproc;
 enum op_type {
@@ -90,33 +91,37 @@ static enum op_type operating_mode;
 
 /*
  * Which of the suppressible warnings are suppressed. Entry zero
- * doesn't do anything. Initial defaults are given here.
+ * isn't an actual warning, but it used for -w+error/-Werror.
  */
-static char suppressed[1 + ERR_WARN_MAX] = {
-    0, TRUE, TRUE, TRUE, FALSE, TRUE
+static bool suppressed[ERR_WARN_MAX+1] = {
+    true, false, true, false, false, true, false, true, true, false
 };
 
 /*
  * The option names for the suppressible warnings. As before, entry
  * zero does nothing.
  */
-static const char *suppressed_names[1 + ERR_WARN_MAX] = {
-    NULL, "macro-params", "macro-selfref", "orphan-labels",
-        "number-overflow",
-    "gnu-elf-extensions"
+static const char *suppressed_names[ERR_WARN_MAX+1] = {
+    "error", "macro-params", "macro-selfref", "orphan-labels",
+    "number-overflow", "gnu-elf-extensions", "float-overflow",
+    "float-denorm", "float-underflow", "float-toolong"
 };
 
 /*
  * The explanations for the suppressible warnings. As before, entry
  * zero does nothing.
  */
-static const char *suppressed_what[1 + ERR_WARN_MAX] = {
-    NULL,
-    "macro calls with wrong no. of params",
-    "cyclic macro self-references",
+static const char *suppressed_what[ERR_WARN_MAX+1] = {
+    "treat warnings as errors",
+    "macro calls with wrong parameter count",
+    "cyclic macro references",
     "labels alone on lines without trailing `:'",
-    "numeric constants greater than 0xFFFFFFFF",
-    "using 8- or 16-bit relocation in ELF, a GNU extension"
+    "numeric constants does not fit in 64 bits",
+    "using 8- or 16-bit relocation in ELF32, a GNU extension",
+    "floating point overflow",
+    "floating point denormal",
+    "floating point underflow",
+    "too many digits in floating-point number"
 };
 
 /*
@@ -150,7 +155,7 @@ static void nasm_fputs(const char *line, FILE * outfile)
 {
     if (outfile) {
         fputs(line, outfile);
-        fputc('\n', outfile);
+        putc('\n', outfile);
     } else
         puts(line);
 }
@@ -158,7 +163,7 @@ static void nasm_fputs(const char *line, FILE * outfile)
 int main(int argc, char **argv)
 {
     pass0 = 1;
-    want_usage = terminate_after_phase = FALSE;
+    want_usage = terminate_after_phase = false;
     report_error = report_error_gnu;
 
     error_file = stderr;
@@ -234,7 +239,7 @@ int main(int argc, char **argv)
             } else
                 ofile = NULL;
 
-            location.known = FALSE;
+            location.known = false;
 
 /*      pass = 1; */
             preproc->reset(inname, 2, report_error, evaluate, &nasmlist);
@@ -331,9 +336,9 @@ int main(int argc, char **argv)
  * Get a parameter for a command line option.
  * First arg must be in the form of e.g. -f...
  */
-static char *get_param(char *p, char *q, int *advance)
+static char *get_param(char *p, char *q, bool *advance)
 {
-    *advance = 0;
+    *advance = false;
     if (p[2]) {                 /* the parameter's in the option */
         p += 2;
         while (isspace(*p))
@@ -341,7 +346,7 @@ static char *get_param(char *p, char *q, int *advance)
         return p;
     }
     if (q && q[0]) {
-        *advance = 1;
+        *advance = true;
         return q;
     }
     report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
@@ -349,6 +354,20 @@ static char *get_param(char *p, char *q, int *advance)
     return NULL;
 }
 
+/*
+ * Copy a filename
+ */
+static void copy_filename(char *dst, const char *src)
+{
+    size_t len = strlen(src);
+
+    if (len >= (size_t)FILENAME_MAX) {
+       report_error(ERR_FATAL | ERR_NOFILE, "file name too long");
+       return;
+    }
+    strncpy(dst, src, FILENAME_MAX);
+}
+
 struct textargs {
     const char *label;
     int value;
@@ -362,112 +381,145 @@ struct textargs textopts[] = {
     {NULL, 0}
 };
 
-int stopoptions = 0;
-static int process_arg(char *p, char *q)
+static bool stopoptions = false;
+static bool process_arg(char *p, char *q)
 {
     char *param;
-    int i, advance = 0;
+    int i;
+    bool advance = false;
+    bool suppress;
 
     if (!p || !p[0])
-        return 0;
+        return false;
 
     if (p[0] == '-' && !stopoptions) {
+       if (strchr("oOfpPdDiIlFXuUZwW", p[1])) {
+           /* These parameters take values */
+           if (!(param = get_param(p, q, &advance)))
+               return advance;
+       }
+
         switch (p[1]) {
         case 's':
             error_file = stdout;
             break;
-        case 'o':              /* these parameters take values */
-        case 'O':
-        case 'f':
-        case 'p':
-        case 'P':
-        case 'd':
-        case 'D':
-        case 'i':
-        case 'I':
-        case 'l':
-        case 'F':
-        case 'X':
-        case 'u':
-        case 'U':
-       case 'Z':
-            if (!(param = get_param(p, q, &advance)))
-                break;
-            if (p[1] == 'o') {  /* output file */
-                strcpy(outname, param);
-            } else if (p[1] == 'f') {   /* output format */
-                ofmt = ofmt_find(param);
-                if (!ofmt) {
-                    report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
-                                 "unrecognised output format `%s' - "
-                                 "use -hf for a list", param);
-                } else
-                    ofmt->current_dfmt = ofmt->debug_formats[0];
-            } else if (p[1] == 'O') {   /* Optimization level */
-                int opt;
-                opt = -99;
-                while (*param) {
-                    if (isdigit(*param)) {
-                        opt = atoi(param);
-                        while (isdigit(*++param)) ;
-                        if (opt <= 0)
-                            optimizing = -1;    /* 0.98 behaviour */
-                        else if (opt == 1)
-                            optimizing = 0;     /* Two passes, 0.98.09 behavior */
-                        else if (opt <= 5)
+
+       case 'o':               /* output file */
+           copy_filename(outname, param);
+           break;
+
+       case 'f':               /* output format */
+           ofmt = ofmt_find(param);
+           if (!ofmt) {
+               report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
+                            "unrecognised output format `%s' - "
+                            "use -hf for a list", param);
+           } else {
+               ofmt->current_dfmt = ofmt->debug_formats[0];
+           }
+           break;
+
+       case 'O':               /* Optimization level */
+       {
+           int opt;
+           
+           if (!*param) {
+               /* Naked -O == -Ox */
+               optimizing = INT_MAX >> 1; /* Almost unlimited */
+           } else {
+               while (*param) {
+                   switch (*param) {
+                   case '0': case '1': case '2': case '3': case '4':
+                   case '5': case '6': case '7': case '8': case '9':
+                       opt = strtoul(param, &param, 10);
+                       
+                       /* -O0 -> optimizing == -1, 0.98 behaviour */
+                       /* -O1 -> optimizing == 0, 0.98.09 behaviour */
+                       if (opt < 2)
+                           optimizing = opt - 1;
+                       else if (opt <= 5)
                            /* The optimizer seems to have problems with
                               < 5 passes?  Hidden bug? */
                            optimizing = 5;     /* 5 passes */
                        else
-                            optimizing = opt;   /* More than 5 passes */
-                    } else {
-                        if (*param == 'v' || *param == '+') {
-                            ++param;
-                            opt_verbose_info = TRUE;
-                            opt = 0;
-                        } else {        /* garbage */
-                            opt = -99;
-                            break;
-                        }
-                    }
-                }               /* while (*param) */
-                if (opt == -99)
-                    report_error(ERR_FATAL,
-                                 "command line optimization level must be 'v', 0..3 or <nn>");
-            } else if (p[1] == 'P' || p[1] == 'p') {    /* pre-include */
-                pp_pre_include(param);
-            } else if (p[1] == 'D' || p[1] == 'd') {    /* pre-define */
-                pp_pre_define(param);
-            } else if (p[1] == 'U' || p[1] == 'u') {    /* un-define */
-                pp_pre_undefine(param);
-            } else if (p[1] == 'I' || p[1] == 'i') {    /* include search path */
-                pp_include_path(param);
-            } else if (p[1] == 'l') {   /* listing file */
-                strcpy(listname, param);
-            } else if (p[1] == 'Z') {   /* error messages file */
-                strcpy(errname, param);
-            } else if (p[1] == 'F') {   /* specify debug format */
-                ofmt->current_dfmt = dfmt_find(ofmt, param);
-                if (!ofmt->current_dfmt) {
-                    report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
-                                 "unrecognized debug format `%s' for"
-                                 " output format `%s'",
-                                 param, ofmt->shortname);
-                }
-            } else if (p[1] == 'X') {   /* specify error reporting format */
-                if (nasm_stricmp("vc", param) == 0)
-                    report_error = report_error_vc;
-                else if (nasm_stricmp("gnu", param) == 0)
-                    report_error = report_error_gnu;
-                else
-                    report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
-                                 "unrecognized error reporting format `%s'",
-                                 param);
-            }
+                           optimizing = opt;   /* More than 5 passes */
+                       break;
+                       
+                   case 'v':
+                   case '+':
+                       param++;
+                       opt_verbose_info = true;
+                       break;
+                       
+                   case 'x':
+                       param++;
+                       optimizing = INT_MAX >> 1; /* Almost unlimited */
+                       break;
+                       
+                   default:
+                       report_error(ERR_FATAL,
+                                    "unknown optimization option -O%c\n",
+                                    *param);
+                       break;
+                   }
+               }
+           }
+           break;
+       }
+
+       case 'p':                       /* pre-include */
+       case 'P':
+           pp_pre_include(param);
+           break;
+
+       case 'd':                       /* pre-define */
+       case 'D':
+           pp_pre_define(param);
+           break;
+
+       case 'u':                       /* un-define */
+       case 'U':
+           pp_pre_undefine(param);
+           break;
+
+       case 'i':                       /* include search path */
+       case 'I':
+           pp_include_path(param);
+           break;
+
+       case 'l':                       /* listing file */
+           copy_filename(listname, param);
+           break;
+
+       case 'Z':                       /* error messages file */
+           strcpy(errname, param);
+           break;
+
+       case 'F':                       /* specify debug format */
+           ofmt->current_dfmt = dfmt_find(ofmt, param);
+           if (!ofmt->current_dfmt) {
+               report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
+                            "unrecognized debug format `%s' for"
+                            " output format `%s'",
+                            param, ofmt->shortname);
+           }
+           break;
+
+       case 'X':               /* specify error reporting format */
+           if (nasm_stricmp("vc", param) == 0)
+               report_error = report_error_vc;
+           else if (nasm_stricmp("gnu", param) == 0)
+               report_error = report_error_gnu;
+           else
+               report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
+                            "unrecognized error reporting format `%s'",
+                            param);
             break;
+
         case 'g':
-            using_debug_info = TRUE;
+            using_debug_info = true;
             break;
+
         case 'h':
             printf
                 ("usage: nasm [-@ response file] [-o outfile] [-f format] "
@@ -491,9 +543,10 @@ static int process_arg(char *p, char *q)
                  "    -D<macro>[=<value>] pre-defines a macro\n"
                  "    -U<macro>   undefines a macro\n"
                  "    -X<format>  specifies error reporting format (gnu or vc)\n"
-                 "    -w+foo      enables warnings about foo; -w-foo disables them\n"
-                 "where foo can be:\n");
-            for (i = 1; i <= ERR_WARN_MAX; i++)
+                 "    -w+foo      enables warning foo (equiv. -Wfoo)\n"
+                "    -w-foo      disable warning foo (equiv. -Wno-foo)\n"
+                 "Warnings:\n");
+            for (i = 0; i <= ERR_WARN_MAX; i++)
                 printf("    %-23s %s (default %s)\n",
                        suppressed_names[i], suppressed_what[i],
                        suppressed[i] ? "off" : "on");
@@ -510,15 +563,18 @@ static int process_arg(char *p, char *q)
             }
             exit(0);            /* never need usage message here */
             break;
+
         case 'y':
             printf("\nvalid debug formats for '%s' output format are"
                    " ('*' denotes default):\n", ofmt->shortname);
             dfmt_list(ofmt, stdout);
             exit(0);
             break;
+
         case 't':
-            tasm_compatible_mode = TRUE;
+            tasm_compatible_mode = true;
             break;
+
         case 'v':
             {
                 const char *nasm_version_string =
@@ -531,28 +587,51 @@ static int process_arg(char *p, char *q)
                 exit(0);        /* never need usage message here */
             }
             break;
+
         case 'e':              /* preprocess only */
        case 'E':
             operating_mode = op_preprocess;
             break;
+
         case 'a':              /* assemble only - don't preprocess */
             preproc = &no_pp;
             break;
+
+       case 'W':
+           if (param[0] == 'n' && param[1] == 'o' && param[2] == '-') {
+               suppress = true;
+               param += 3;
+           } else {
+               suppress = false;
+           }
+           goto set_warning;
+
         case 'w':
-            if (p[2] != '+' && p[2] != '-') {
+            if (param[0] != '+' && param[0] != '-') {
                 report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                              "invalid option to `-w'");
-            } else {
-                for (i = 1; i <= ERR_WARN_MAX; i++)
-                    if (!nasm_stricmp(p + 3, suppressed_names[i]))
-                        break;
-                if (i <= ERR_WARN_MAX)
-                    suppressed[i] = (p[2] == '-');
-                else
-                    report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
-                                 "invalid option to `-w'");
+               break;
             }
+           suppress = (param[0] == '-');
+           param++;
+           goto set_warning;
+       set_warning:
+           for (i = 0; i <= ERR_WARN_MAX; i++)
+               if (!nasm_stricmp(param, suppressed_names[i]))
+                   break;
+           if (i <= ERR_WARN_MAX)
+               suppressed[i] = suppress;
+           else if (!nasm_stricmp(param, "all"))
+               for (i = 1; i <= ERR_WARN_MAX; i++)
+                   suppressed[i] = suppress;
+           else if (!nasm_stricmp(param, "none"))
+               for (i = 1; i <= ERR_WARN_MAX; i++)
+                   suppressed[i] = !suppress;
+           else
+               report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
+                            "invalid warning `%s'", param);
             break;
+
         case 'M':
             operating_mode = p[2] == 'G' ? op_depend_missing_ok : op_depend;
             break;
@@ -618,8 +697,9 @@ static int process_arg(char *p, char *q)
         if (*inname) {
             report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                          "more than one input file specified");
-        } else
-            strcpy(inname, p);
+        } else {
+            copy_filename(inname, p);
+       }
     }
 
     return advance;
@@ -638,7 +718,6 @@ static void process_respfile(FILE * rfile)
     prevarg[0] = '\0';
 
     while (1) {                 /* Loop to handle all lines in file */
-
         p = buffer;
         while (1) {             /* Loop to handle long lines */
             q = fgets(p, bufsize - (p - buffer), rfile);
@@ -680,11 +759,11 @@ static void process_respfile(FILE * rfile)
         if (process_arg(prevarg, p))
             *p = '\0';
 
-        if (strlen(p) > prevargsize - 10) {
+        if ((int) strlen(p) > prevargsize - 10) {
             prevargsize += ARG_BUF_DELTA;
             prevarg = nasm_realloc(prevarg, prevargsize);
         }
-        strcpy(prevarg, p);
+        strncpy(prevarg, p, prevargsize);
     }
 }
 
@@ -738,7 +817,7 @@ static void parse_cmdline(int argc, char **argv)
      * Now process the actual command line.
      */
     while (--argc) {
-        int i;
+       bool advance;
         argv++;
         if (argv[0][0] == '@') {
             /* We have a response file, so process this as a set of
@@ -764,7 +843,7 @@ static void parse_cmdline(int argc, char **argv)
             argv++;
         }
         if (!stopoptions && argv[0][0] == '-' && argv[0][1] == '@') {
-           p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &i);
+           p = get_param(argv[0], argc > 1 ? argv[1] : NULL, &advance);
             if (p) {
                rfile = fopen(p, "r");
                 if (rfile) {
@@ -775,23 +854,22 @@ static void parse_cmdline(int argc, char **argv)
                                  "unable to open response file `%s'", p);
             }
         } else
-            i = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
-        argv += i, argc -= i;
+            advance = process_arg(argv[0], argc > 1 ? argv[1] : NULL);
+        argv += advance, argc -= advance;
     }
 
+    /* Look for basic command line typos.  This definitely doesn't
+       catch all errors, but it might help cases of fumbled fingers. */
     if (!*inname)
         report_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
                      "no input file specified");
-
-    /* Look for basic command line typos.  This definitely doesn't
-       catch all errors, but it might help cases of fumbled fingers. */
-    if (!strcmp(inname, errname) || !strcmp(inname, outname) ||
+    else if (!strcmp(inname, errname) || !strcmp(inname, outname) ||
        !strcmp(inname, listname))
        report_error(ERR_FATAL | ERR_NOFILE | ERR_USAGE,
                     "file `%s' is both input and output file",
                     inname);
 
-    if (*errname) {  
+    if (*errname) {
        error_file = fopen(errname, "w");
        if (!error_file) {
            error_file = stderr;        /* Revert to default! */
@@ -803,21 +881,24 @@ static void parse_cmdline(int argc, char **argv)
 }
 
 /* List of directives */
-enum {
+enum directives {
     D_NONE, D_ABSOLUTE, D_BITS, D_COMMON, D_CPU, D_DEBUG, D_DEFAULT,
-    D_EXTERN, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
+    D_EXTERN, D_FLOAT, D_GLOBAL, D_LIST, D_SECTION, D_SEGMENT, D_WARNING
 };
 static const char *directives[] = {
     "", "absolute", "bits", "common", "cpu", "debug", "default",
-    "extern", "global", "list", "section", "segment", "warning"
+    "extern", "float", "global", "list", "section", "segment", "warning"
 };
+static enum directives getkw(char **directive, char **value);
 
 static void assemble_file(char *fname)
 {
     char *directive, *value, *p, *q, *special, *line, debugid[80];
     insn output_ins;
-    int i, rn_error, validid;
-    int32_t seg, offs;
+    int i, validid;
+    bool rn_error;
+    int32_t seg;
+    int64_t offs;
     struct tokenval tokval;
     expr *e;
     int pass, pass_max;
@@ -845,8 +926,8 @@ static void assemble_file(char *fname)
             if (*listname)
                 nasmlist.init(listname, report_error);
         }
-        in_abs_seg = FALSE;
-        global_offset_changed = FALSE;  /* set by redefine_label */
+        in_abs_seg = false;
+        global_offset_changed = false;  /* set by redefine_label */
         location.segment = ofmt->section(NULL, pass2, &sb);
         globalbits = sb;
         if (pass > 1) {
@@ -858,20 +939,21 @@ static void assemble_file(char *fname)
         preproc->reset(fname, pass1, report_error, evaluate, &nasmlist);
         globallineno = 0;
         if (pass == 1)
-            location.known = TRUE;
+            location.known = true;
         location.offset = offs = GET_CURR_OFFS;
 
         while ((line = preproc->getline())) {
+           enum directives d;
             globallineno++;
 
             /* here we parse our directives; this is not handled by the 'real'
              * parser. */
             directive = line;
-           i = getkw(&directive, &value);
-            if (i) {
+           d = getkw(&directive, &value);
+            if (d) {
                int err = 0;
 
-                switch (i) {
+                switch (d) {
                 case D_SEGMENT:                /* [SEGMENT n] */
                case D_SECTION:
                     seg = ofmt->section(value, pass2, &sb);
@@ -880,7 +962,7 @@ static void assemble_file(char *fname)
                                      "segment name `%s' not recognized",
                                      value);
                     } else {
-                        in_abs_seg = FALSE;
+                        in_abs_seg = false;
                         location.segment = seg;
                     }
                     break;
@@ -897,12 +979,12 @@ static void assemble_file(char *fname)
                         }
                     } else if (pass == 1) {     /* pass == 1 */
                         q = value;
-                        validid = TRUE;
+                        validid = true;
                         if (!isidstart(*q))
-                            validid = FALSE;
+                            validid = false;
                         while (*q && *q != ':') {
                             if (!isidchar(*q))
-                                validid = FALSE;
+                                validid = false;
                             q++;
                         }
                         if (!validid) {
@@ -921,7 +1003,7 @@ static void assemble_file(char *fname)
                             declare_as_global(value, special,
                                               report_error);
                             define_label(value, seg_alloc(), 0L, NULL,
-                                         FALSE, TRUE, ofmt, report_error);
+                                         false, true, ofmt, report_error);
                             pass0 = temp;
                         }
                     }           /* else  pass0 == 1 */
@@ -942,12 +1024,12 @@ static void assemble_file(char *fname)
                         }
                     } else if (pass2 == 1) {    /* pass == 1 */
                         q = value;
-                        validid = TRUE;
+                        validid = true;
                         if (!isidstart(*q))
-                            validid = FALSE;
+                            validid = false;
                         while (*q && *q != ':') {
                             if (!isidchar(*q))
-                                validid = FALSE;
+                                validid = false;
                             q++;
                         }
                         if (!validid) {
@@ -968,12 +1050,12 @@ static void assemble_file(char *fname)
                         value++;        /* skip initial $ if present */
                     if (pass0 == 1) {
                         p = value;
-                        validid = TRUE;
+                        validid = true;
                         if (!isidstart(*p))
-                            validid = FALSE;
+                            validid = false;
                         while (*p && !isspace(*p)) {
                             if (!isidchar(*p))
-                                validid = FALSE;
+                                validid = false;
                             p++;
                         }
                         if (!validid) {
@@ -1040,18 +1122,18 @@ static void assemble_file(char *fname)
                     else
                         report_error(ERR_PANIC, "invalid ABSOLUTE address "
                                      "in pass two");
-                    in_abs_seg = TRUE;
+                    in_abs_seg = true;
                     location.segment = NO_SEG;
                     break;
                 case D_DEBUG:          /* [DEBUG] */
                     p = value;
                     q = debugid;
-                    validid = TRUE;
+                    validid = true;
                     if (!isidstart(*p))
-                        validid = FALSE;
+                        validid = false;
                     while (*p && !isspace(*p)) {
                         if (!isidchar(*p))
-                            validid = FALSE;
+                            validid = false;
                         *q++ = *p++;
                     }
                     *q++ = 0;
@@ -1071,10 +1153,10 @@ static void assemble_file(char *fname)
                             value++;
 
                         if (*value == '+' || *value == '-') {
-                            validid = (*value == '-') ? TRUE : FALSE;
+                            validid = (*value == '-') ? true : false;
                             value++;
                         } else
-                            validid = FALSE;
+                            validid = false;
 
                         for (i = 1; i <= ERR_WARN_MAX; i++)
                             if (!nasm_stricmp(value, suppressed_names[i]))
@@ -1123,6 +1205,13 @@ static void assemble_file(char *fname)
                        err = 1;
                    }
                    break;
+               case D_FLOAT:
+                   if (float_option(value)) {
+                       report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
+                                    "unknown 'float' directive: %s",
+                                    value);
+                   }
+                   break;
                 default:
                     if (!ofmt->directive(directive, value, pass2))
                         report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
@@ -1141,7 +1230,7 @@ static void assemble_file(char *fname)
 
                 if (!(optimizing > 0) && pass == 2) {
                     if (forwref != NULL && globallineno == forwref->lineno) {
-                        output_ins.forw_ref = TRUE;
+                        output_ins.forw_ref = true;
                         do {
                             output_ins.oprs[forwref->operand].opflags |=
                                 OPFLAG_FORWARD;
@@ -1149,7 +1238,7 @@ static void assemble_file(char *fname)
                         } while (forwref != NULL
                                  && forwref->lineno == globallineno);
                     } else
-                        output_ins.forw_ref = FALSE;
+                        output_ins.forw_ref = false;
                 }
 
                 if (!(optimizing > 0) && output_ins.forw_ref) {
@@ -1220,7 +1309,7 @@ static void assemble_file(char *fname)
                                 def_label(output_ins.label,
                                           output_ins.oprs[0].segment,
                                           output_ins.oprs[0].offset, NULL,
-                                          FALSE, isext, ofmt,
+                                          false, isext, ofmt,
                                           report_error);
                             } else if (output_ins.operands == 2
                                        && (output_ins.oprs[0].
@@ -1239,7 +1328,7 @@ static void assemble_file(char *fname)
                                           output_ins.oprs[0].
                                           offset | SEG_ABS,
                                           output_ins.oprs[1].offset, NULL,
-                                          FALSE, FALSE, ofmt,
+                                          false, false, ofmt,
                                           report_error);
                             } else
                                 report_error(ERR_NONFATAL,
@@ -1258,7 +1347,7 @@ static void assemble_file(char *fname)
                                 define_label(output_ins.label,
                                              output_ins.oprs[0].segment,
                                              output_ins.oprs[0].offset,
-                                             NULL, FALSE, FALSE, ofmt,
+                                             NULL, false, false, ofmt,
                                              report_error);
                             } else if (output_ins.operands == 2
                                        && (output_ins.oprs[0].
@@ -1274,7 +1363,7 @@ static void assemble_file(char *fname)
                                              output_ins.oprs[0].
                                              offset | SEG_ABS,
                                              output_ins.oprs[1].offset,
-                                             NULL, FALSE, FALSE, ofmt,
+                                             NULL, false, false, ofmt,
                                              report_error);
                             } else
                                 report_error(ERR_NONFATAL,
@@ -1285,7 +1374,7 @@ static void assemble_file(char *fname)
 
                     if (pass1 == 1) {
 
-                        int32_t l = insn_size(location.segment, offs, sb, cpu,
+                        int64_t l = insn_size(location.segment, offs, sb, cpu,
                                            &output_ins, report_error);
 
                         /* if (using_debug_info)  && output_ins.opcode != -1) */
@@ -1405,7 +1494,7 @@ static void assemble_file(char *fname)
 #endif
 }                               /* exit from assemble_file (...) */
 
-static int getkw(char **directive, char **value)
+static enum directives getkw(char **directive, char **value)
 {
     char *p, *q, *buf;
 
@@ -1459,13 +1548,13 @@ static int getkw(char **directive, char **value)
  * This function prints an error message to error_file in the
  * style used by GNU. An example would be:
  * file.asm:50: error: blah blah blah
- * where file.asm is the name of the file, 50 is the line number on 
+ * where file.asm is the name of the file, 50 is the line number on
  * which the error occurs (or is detected) and "error:" is one of
  * the possible optional diagnostics -- it can be "error" or "warning"
- * or something else.  Finally the line terminates with the actual 
+ * or something else.  Finally the line terminates with the actual
  * error message.
- * 
- * @param severity the severity of the warning or error 
+ *
+ * @param severity the severity of the warning or error
  * @param fmt the printf style format string
  */
 static void report_error_gnu(int severity, const char *fmt, ...)
@@ -1492,16 +1581,16 @@ static void report_error_gnu(int severity, const char *fmt, ...)
 /**
  * MS style error reporting
  * This function prints an error message to error_file in the
- * style used by Visual C and some other Microsoft tools. An example 
+ * style used by Visual C and some other Microsoft tools. An example
  * would be:
  * file.asm(50) : error: blah blah blah
- * where file.asm is the name of the file, 50 is the line number on 
+ * where file.asm is the name of the file, 50 is the line number on
  * which the error occurs (or is detected) and "error:" is one of
  * the possible optional diagnostics -- it can be "error" or "warning"
- * or something else.  Finally the line terminates with the actual 
+ * or something else.  Finally the line terminates with the actual
  * error message.
- * 
- * @param severity the severity of the warning or error 
+ *
+ * @param severity the severity of the warning or error
  * @param fmt the printf style format string
  */
 static void report_error_vc(int severity, const char *fmt, ...)
@@ -1527,7 +1616,7 @@ static void report_error_vc(int severity, const char *fmt, ...)
 
 /**
  * check for supressed warning
- * checks for suppressed warning or pass one only warning and we're 
+ * checks for suppressed warning or pass one only warning and we're
  * not in pass 1
  *
  * @param severity the severity of the warning or error
@@ -1550,11 +1639,11 @@ static int is_suppressed_warning(int severity)
 /**
  * common error reporting
  * This is the common back end of the error reporting schemes currently
- * implemented.  It prints the nature of the warning and then the 
+ * implemented.  It prints the nature of the warning and then the
  * specific error message to error_file and may or may not return.  It
  * doesn't return if the error severity is a "panic" or "debug" type.
- * 
- * @param severity the severity of the warning or error 
+ *
+ * @param severity the severity of the warning or error
  * @param fmt the printf style format string
  */
 static void report_error_common(int severity, const char *fmt,
@@ -1579,19 +1668,21 @@ static void report_error_common(int severity, const char *fmt,
     }
 
     vfprintf(error_file, fmt, args);
-    fputc('\n', error_file);
+    putc('\n', error_file);
 
     if (severity & ERR_USAGE)
-        want_usage = TRUE;
+        want_usage = true;
 
     switch (severity & ERR_MASK) {
-    case ERR_WARNING:
     case ERR_DEBUG:
         /* no further action, by definition */
         break;
+    case ERR_WARNING:
+       if (!suppressed[0])     /* Treat warnings as errors */
+           terminate_after_phase = true;
+       break;
     case ERR_NONFATAL:
-        /* hack enables listing(!) on errors */
-        terminate_after_phase = TRUE;
+        terminate_after_phase = true;
         break;
     case ERR_FATAL:
         if (ofile) {
@@ -1710,7 +1801,6 @@ static void no_pp_cleanup(int pass)
 
 static uint32_t get_cpu(char *value)
 {
-
     if (!strcmp(value, "8086"))
         return IF_8086;
     if (!strcmp(value, "186"))