Fix #136: Unbreak ..@ non-local-label mechanism.
authorPeter Johnson <peter@tortall.net>
Thu, 27 Mar 2008 05:35:36 +0000 (05:35 -0000)
committerPeter Johnson <peter@tortall.net>
Thu, 27 Mar 2008 05:35:36 +0000 (05:35 -0000)
Add testcase for this.
Also fix $-prefixed labels to match non-$-prefixed label behavior
(this has been broken for a very long time).

svn path=/trunk/yasm/; revision=2045

modules/parsers/nasm/nasm-parse.c
modules/parsers/nasm/nasm-parser.h
modules/parsers/nasm/nasm-token.re
modules/parsers/nasm/tests/Makefile.inc
modules/parsers/nasm/tests/locallabel.asm [new file with mode: 0644]
modules/parsers/nasm/tests/locallabel.hex [new file with mode: 0644]

index 02a64121c2d18b2fd7d4761b10136389839f730c..cba949f85da946e1b851d7785ac95cb7ba51e1f4 100644 (file)
@@ -98,6 +98,7 @@ destroy_curtok_(yasm_parser_nasm *parser_nasm)
         case ID:
         case LOCAL_ID:
         case SPECIAL_ID:
+        case NONLOCAL_ID:
             yasm_xfree(curval.str_val);
             break;
         case STRING:
@@ -169,6 +170,7 @@ describe_token(int token)
         case ID:                str = "identifier"; break;
         case LOCAL_ID:          str = ".identifier"; break;
         case SPECIAL_ID:        str = "..identifier"; break;
+        case NONLOCAL_ID:       str = "..@identifier"; break;
         case LINE:              str = "%line"; break;
         default:
             strch[1] = token;
@@ -349,6 +351,7 @@ parse_line(yasm_parser_nasm *parser_nasm)
             return parse_times(parser_nasm);
         case ID:
         case SPECIAL_ID:
+        case NONLOCAL_ID:
         case LOCAL_ID:
         {
             char *name = ID_val;
@@ -1143,6 +1146,7 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
             /*@fallthrough@*/
         case ID:
         case LOCAL_ID:
+        case NONLOCAL_ID:
             sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
             e = p_expr_new_ident(yasm_expr_sym(sym));
             yasm_xfree(ID_val);
index 359761c31d5af2d9e1c3fa9e656dbb82dec454e3..c6148a7b65a86323cf939e11fa9a334d63f06417 100644 (file)
@@ -62,6 +62,7 @@ enum tokentype {
     ID,
     LOCAL_ID,
     SPECIAL_ID,
+    NONLOCAL_ID,
     LINE,
     NONE                /* special token for lookahead */
 };
index d81e0ce66e0b0a891b17022f5c22aa59cc071d1d..4409566c1a539721b5540553e5a84fd7399a2691 100644 (file)
@@ -70,6 +70,34 @@ static int linechg_numcount;
   quot = ["'];
 */
 
+static int
+handle_dot_label(YYSTYPE *lvalp, char *tok, size_t toklen, size_t zeropos,
+                 yasm_parser_nasm *parser_nasm)
+{
+    /* check for special non-local labels like ..start */
+    if (tok[zeropos+1] == '.') {
+        lvalp->str_val = yasm__xstrndup(tok+zeropos, toklen-zeropos);
+        /* check for special non-local ..@label */
+        if (lvalp->str_val[zeropos+2] == '@')
+            return NONLOCAL_ID;
+        return SPECIAL_ID;
+    }
+
+    if (!parser_nasm->locallabel_base) {
+        lvalp->str_val = yasm__xstrndup(tok+zeropos, toklen-zeropos);
+        yasm_warn_set(YASM_WARN_GENERAL,
+                      N_("no non-local label before `%s'"),
+                      lvalp->str_val);
+    } else {
+        size_t len = toklen - zeropos + parser_nasm->locallabel_base_len;
+        lvalp->str_val = yasm_xmalloc(len + 1);
+        strcpy(lvalp->str_val, parser_nasm->locallabel_base);
+        strncat(lvalp->str_val, tok+zeropos, toklen-zeropos);
+        lvalp->str_val[len] = '\0';
+    }
+
+    return LOCAL_ID;
+}
 
 int
 nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm)
@@ -77,7 +105,7 @@ nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm)
     yasm_scanner *s = &parser_nasm->s;
     YYCTYPE *cursor = s->cur;
     YYCTYPE endch;
-    size_t count, len;
+    size_t count;
     YYCTYPE savech;
 
     /* Handle one token of lookahead */
@@ -286,38 +314,17 @@ scan:
         [-+|^*&/%~$():=,\[]     { RETURN(s->tok[0]); }
         "]"                     { RETURN(s->tok[0]); }
 
-        /* special non-local ..@label */
-        "..@" [a-zA-Z0-9_$#@~.?]+ {
-            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
-            RETURN(ID);
-        }
-
-        /* special non-local labels like ..start */
-        ".." [a-zA-Z0-9_$#~.?]+ {
-            lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
-            RETURN(SPECIAL_ID);
-        }
-
         /* local label (.label) */
-        "." [a-zA-Z0-9_$#@~?][a-zA-Z0-9_$#@~.?]* {
-            if (!parser_nasm->locallabel_base) {
-                lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
-                yasm_warn_set(YASM_WARN_GENERAL,
-                              N_("no non-local label before `%s'"),
-                              lvalp->str_val);
-            } else {
-                len = TOKLEN + parser_nasm->locallabel_base_len;
-                lvalp->str_val = yasm_xmalloc(len + 1);
-                strcpy(lvalp->str_val, parser_nasm->locallabel_base);
-                strncat(lvalp->str_val, TOK, TOKLEN);
-                lvalp->str_val[len] = '\0';
-            }
-
-            RETURN(LOCAL_ID);
+        "." [a-zA-Z0-9_$#@~.?]+ {
+            RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 0, parser_nasm));
         }
 
         /* forced identifier */
         "$" [a-zA-Z0-9_$#@~.?]+ {
+            if (TOK[1] == '.') {
+                /* handle like .label */
+                RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 1, parser_nasm));
+            }
             lvalp->str_val = yasm__xstrndup(TOK+1, TOKLEN-1);
             RETURN(ID);
         }
index 0e7cf1ed611b416af9adc7c00bd40f75e7e4fc44..ad84593cba7904356f42d24445e023f3c2e6977f 100644 (file)
@@ -19,6 +19,8 @@ EXTRA_DIST += modules/parsers/nasm/tests/hexconst.asm
 EXTRA_DIST += modules/parsers/nasm/tests/hexconst.hex
 EXTRA_DIST += modules/parsers/nasm/tests/long.asm
 EXTRA_DIST += modules/parsers/nasm/tests/long.hex
+EXTRA_DIST += modules/parsers/nasm/tests/locallabel.asm
+EXTRA_DIST += modules/parsers/nasm/tests/locallabel.hex
 EXTRA_DIST += modules/parsers/nasm/tests/nasm-prefix.asm
 EXTRA_DIST += modules/parsers/nasm/tests/nasm-prefix.hex
 EXTRA_DIST += modules/parsers/nasm/tests/newsect.asm
diff --git a/modules/parsers/nasm/tests/locallabel.asm b/modules/parsers/nasm/tests/locallabel.asm
new file mode 100644 (file)
index 0000000..013de53
--- /dev/null
@@ -0,0 +1,21 @@
+label:
+db 0
+.local:
+db 0
+..@local1:
+.local2:
+dw label.local
+dw label.local2
+
+$label2:
+db 0
+$.local:
+db 0
+$..@local2:
+$.local2:
+dw label2.local
+dw label2.local2
+dw $label2.local
+dw $label2.local2
+
+
diff --git a/modules/parsers/nasm/tests/locallabel.hex b/modules/parsers/nasm/tests/locallabel.hex
new file mode 100644 (file)
index 0000000..4aaba4e
--- /dev/null
@@ -0,0 +1,16 @@
+00 
+00 
+01 
+00 
+02 
+00 
+00 
+00 
+07 
+00 
+08 
+00 
+07 
+00 
+08 
+00