Add [default] directive
authorH. Peter Anvin <hpa@zytor.com>
Wed, 29 Aug 2007 16:38:05 +0000 (16:38 +0000)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 29 Aug 2007 16:38:05 +0000 (16:38 +0000)
Add the [default {abs|rel}] directive, and clean up directive parsing.

nasm.c
nasm.h
parser.c

diff --git a/nasm.c b/nasm.c
index 0dfad2aba07e89b4ee9f9d704259bd11ef87e650..479a3f3332a1c6437b59f392a2c7009cbd5734d7 100644 (file)
--- a/nasm.c
+++ b/nasm.c
@@ -778,6 +778,16 @@ static void parse_cmdline(int argc, char **argv)
                      "no input file specified");
 }
 
+/* List of directives */
+enum {
+    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
+};
+static const char *directives[] = {
+    "", "absolute", "bits", "common", "cpu", "debug", "default",
+    "extern", "global", "list", "section", "segment", "warning"
+};
+
 static void assemble_file(char *fname)
 {
     char *directive, *value, *p, *q, *special, *line, debugid[80];
@@ -835,8 +845,11 @@ static void assemble_file(char *fname)
             directive = line;
            i = getkw(&directive, &value);
             if (i) {
+               int err = 0;
+
                 switch (i) {
-                case 1:        /* [SEGMENT n] */
+                case D_SEGMENT:                /* [SEGMENT n] */
+               case D_SECTION:
                     seg = ofmt->section(value, pass2, &sb);
                     if (seg == NO_SEG) {
                         report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
@@ -847,7 +860,7 @@ static void assemble_file(char *fname)
                         location.segment = seg;
                     }
                     break;
-                case 2:        /* [EXTERN label:special] */
+                case D_EXTERN:         /* [EXTERN label:special] */
                     if (*value == '$')
                         value++;        /* skip initial $ if present */
                     if (pass0 == 2) {
@@ -889,10 +902,10 @@ static void assemble_file(char *fname)
                         }
                     }           /* else  pass0 == 1 */
                     break;
-                case 3:        /* [BITS bits] */
+                case D_BITS:           /* [BITS bits] */
                     globalbits = sb = get_bits(value);
                     break;
-                case 4:        /* [GLOBAL symbol:special] */
+                case D_GLOBAL:         /* [GLOBAL symbol:special] */
                     if (*value == '$')
                         value++;        /* skip initial $ if present */
                     if (pass0 == 2) {   /* pass 2 */
@@ -926,7 +939,7 @@ static void assemble_file(char *fname)
                         declare_as_global(value, special, report_error);
                     }           /* pass == 1 */
                     break;
-                case 5:        /* [COMMON symbol size:special] */
+                case D_COMMON:         /* [COMMON symbol size:special] */
                     if (*value == '$')
                         value++;        /* skip initial $ if present */
                     if (pass0 == 1) {
@@ -982,7 +995,7 @@ static void assemble_file(char *fname)
                         }
                     }
                     break;
-                case 6:        /* [ABSOLUTE address] */
+                case D_ABSOLUTE:               /* [ABSOLUTE address] */
                     stdscan_reset();
                     stdscan_bufptr = value;
                     tokval.t_type = TOKEN_INVALID;
@@ -1006,7 +1019,7 @@ static void assemble_file(char *fname)
                     in_abs_seg = TRUE;
                     location.segment = NO_SEG;
                     break;
-                case 7:        /* DEBUG       */
+                case D_DEBUG:          /* [DEBUG] */
                     p = value;
                     q = debugid;
                     validid = TRUE;
@@ -1028,7 +1041,7 @@ static void assemble_file(char *fname)
                     if (pass == pass_max)
                         ofmt->current_dfmt->debug_directive(debugid, p);
                     break;
-                case 8:        /* [WARNING {+|-}warn-name] */
+                case D_WARNING:                /* [WARNING {+|-}warn-name] */
                     if (pass1 == 1) {
                         while (*value && isspace(*value))
                             value++;
@@ -1049,10 +1062,10 @@ static void assemble_file(char *fname)
                                          "invalid warning id in WARNING directive");
                     }
                     break;
-                case 9:        /* cpu */
+                case D_CPU:            /* [CPU] */
                     cpu = get_cpu(value);
                     break;
-                case 10:       /* fbk 9/2/00 *//* [LIST {+|-}] */
+                case D_LIST:           /* [LIST {+|-}] */
                     while (*value && isspace(*value))
                         value++;
 
@@ -1062,17 +1075,41 @@ static void assemble_file(char *fname)
                         if (*value == '-') {
                             user_nolist = 1;
                         } else {
-                            report_error(ERR_NONFATAL,
-                                         "invalid parameter to \"list\" directive");
+                           err = 1;
                         }
                     }
                     break;
+               case D_DEFAULT:         /* [DEFAULT] */
+                   stdscan_reset();
+                    stdscan_bufptr = value;
+                    tokval.t_type = TOKEN_INVALID;
+                   if (stdscan(NULL, &tokval) == TOKEN_SPECIAL) {
+                       switch ((int)tokval.t_integer) {
+                       case S_REL:
+                           globalrel = 1;
+                           break;
+                       case S_ABS:
+                           globalrel = 0;
+                           break;
+                       default:
+                           err = 1;
+                           break;
+                       }
+                   } else {
+                       err = 1;
+                   }
+                   break;
                 default:
                     if (!ofmt->directive(directive, value, pass2))
                         report_error(pass1 == 1 ? ERR_NONFATAL : ERR_PANIC,
                                      "unrecognised directive [%s]",
                                      directive);
                 }
+               if (err) {
+                   report_error(ERR_NONFATAL,
+                                "invalid parameter to [%s] directive",
+                                directive);
+               }
             } else {            /* it isn't a directive */
 
                 parse_line(pass1, line, &output_ins,
@@ -1386,31 +1423,8 @@ static int getkw(char **directive, char **value)
             buf++;
         *buf++ = '\0';
     }
-#if 0
-    for (q = p; *q; q++)
-        *q = tolower(*q);
-#endif
-    if (!nasm_stricmp(p, "segment") || !nasm_stricmp(p, "section"))
-        return 1;
-    if (!nasm_stricmp(p, "extern"))
-        return 2;
-    if (!nasm_stricmp(p, "bits"))
-        return 3;
-    if (!nasm_stricmp(p, "global"))
-        return 4;
-    if (!nasm_stricmp(p, "common"))
-        return 5;
-    if (!nasm_stricmp(p, "absolute"))
-        return 6;
-    if (!nasm_stricmp(p, "debug"))
-        return 7;
-    if (!nasm_stricmp(p, "warning"))
-        return 8;
-    if (!nasm_stricmp(p, "cpu"))
-        return 9;
-    if (!nasm_stricmp(p, "list"))       /* fbk 9/2/00 */
-        return 10;
-    return -1;
+
+    return bsii(*directive, directives, elements(directives));
 }
 
 /**
diff --git a/nasm.h b/nasm.h
index 9bae66a67dac3671d87c1e35bf39df57efa1ae9b..dfd993377d6ded96fb296d33dc4ad4dc441090a6 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -924,6 +924,18 @@ struct dfmt {
 #define TYM_ELEMENTS(x) (((x) & 0xFFFFFF00) >> 8)
 
 #define TYS_ELEMENTS(x)  ((x) << 8)
+
+/*
+ * -----
+ * Special tokens
+ * -----
+ */
+
+enum {
+    S_ABS, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, S_QWORD, S_REL,
+    S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD
+};
+
 /*
  * -----
  * Other
index f786c2cf97df19478eb5b6c5994527541a3f87b5..5940de3701ae15a7a8fb1ec818112b47f709e7ee 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -27,11 +27,6 @@ extern int32_t abs_offset;         /* ABSOLUTE segment offset */
 
 #include "regflags.c"           /* List of register flags */
 
-enum {                          /* special tokens */
-    S_ABS, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, S_QWORD, S_REL,
-    S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD
-};
-
 static int is_comma_next(void);
 
 static int i;