strip_casl2_commentの、''があるときの動作を修正
[YACASL2.git] / src / token.c
index b6d971c..22f33ba 100644 (file)
@@ -1,8 +1,4 @@
-#include <stdio.h>
-#include <string.h>
-#include "cerr.h"
-#include "cmem.h"
-#include "assemble.h"
+#include "token.h"
 
 /**
  * @brief 「,」区切りの文字列から、オペランドのトークンを取得
 
 /**
  * @brief 「,」区切りの文字列から、オペランドのトークンを取得
@@ -34,13 +30,12 @@ static CERR cerr_opdtok[] = {
 OPD *opdtok(const char *str)
 {
     OPD *opd = malloc_chk(sizeof(OPD), "opd");
 OPD *opdtok(const char *str)
 {
     OPD *opd = malloc_chk(sizeof(OPD), "opd");
-    char *tok, *p;
-    char sepc = ',';
+    char *tok, *p, sepc = ',';
     int i = 0, cnt_quote = 0;
     bool quoting = false;
 
     opd->opdc = 0;
     int i = 0, cnt_quote = 0;
     bool quoting = false;
 
     opd->opdc = 0;
-    if(str == NULL || !str[0]) {
+    if(!str || !str[0]) {
         return opd;
     }
     tok = p = strdup_chk(str, "opdtok.p");
         return opd;
     }
     tok = p = strdup_chk(str, "opdtok.p");
@@ -57,7 +52,7 @@ OPD *opdtok(const char *str)
         /* 「'」の場合 */
         if(p[i] == '\'') {
             /* 「''」以外の場合はquote値を反転する */
         /* 「'」の場合 */
         if(p[i] == '\'') {
             /* 「''」以外の場合はquote値を反転する */
-            if(p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) {
+            if(p[i+1] != '\'' && (quoting == false || p[i-1] != '\'')) {
                 quoting = !quoting;
             }
             /* 「'」をカウントする。「''」の場合は1をカウント */
                 quoting = !quoting;
             }
             /* 「'」をカウントする。「''」の場合は1をカウント */
@@ -74,17 +69,16 @@ OPD *opdtok(const char *str)
             i++;
         } else {
             i += strcspn(p + i, ", ");
             i++;
         } else {
             i += strcspn(p + i, ", ");
-            sepc = p[i];
-            p[i] = '\0';
-            if(!p[0]) {
+            if(i == 0) {
                 setcerr(121, "");    /* cannot get operand token */
                 break;
             }
                 setcerr(121, "");    /* cannot get operand token */
                 break;
             }
-            if(strlen(p) - cnt_quote > OPDSIZE) {
+            if(i - cnt_quote > OPDSIZE) {
                 setcerr(118, "");    /* operand length too long */
                 break;
             }
                 setcerr(118, "");    /* operand length too long */
                 break;
             }
-            opd->opdv[(++opd->opdc)-1] = strdup_chk(p, "opd.opdv[]");
+            sepc = p[i];
+            opd->opdv[(opd->opdc)++] = strndup_chk(p, i, "opd->opdv[]");
             p += i + 1;
             i = cnt_quote = 0;
         }
             p += i + 1;
             i = cnt_quote = 0;
         }
@@ -100,62 +94,64 @@ void addcerrlist_tok()
     addcerrlist(ARRAYSIZE(cerr_opdtok), cerr_opdtok);
 }
 
     addcerrlist(ARRAYSIZE(cerr_opdtok), cerr_opdtok);
 }
 
-CMDLINE *linetok(const char *line)
+char *strip_casl2_comment(char *s)
 {
 {
-    char *tok = NULL, *p = NULL, *lbl = NULL;
     int i;
     bool quoting = false;
     int i;
     bool quoting = false;
-    CMDLINE *cmdl = NULL;
 
 
-    if(!line[0] || line[0] == '\n') {
-        return NULL;
-    }
-    tok = p = strdup_chk(line, "tok");
-    /* コメントを削除 */
-    for(i = 0; p[i]; i++) {
+    for(i = 0; s[i]; i++) {
         /* 「'」で囲まれた文字列の場合。「''」は無視 */
         /* 「'」で囲まれた文字列の場合。「''」は無視 */
-        if(p[i] == '\'' && p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) {
+        if(s[i] == '\'' && s[i+1] != '\'' && (quoting == false || s[i-1] != '\'')) {
             quoting = !quoting;
         /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */
             quoting = !quoting;
         /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */
-        } else if(quoting == false && p[i] == ';') {
-            p[i] = '\0';
+        } else if(quoting == false && s[i] == ';') {
+            s[i] = '\0';
             break;
         }
     }
             break;
         }
     }
-    /* 文字列末尾の改行と空白を削除 */
-    i = strlen(p) - 1;
-    while(i > 0 && (p[i] == '\n' || p[i] == ' ' || p[i] == '\t')) {
-        p[i--] = '\0';
+    return s;
+}
+
+CMDLINE *linetok(const char *line)
+{
+    char *tok = NULL, *p = NULL;
+    int i;
+    CMDLINE *cmdl = NULL;
+
+    assert(line);
+    if(!line[0] || line[0] == '\n') {
+        return NULL;
     }
     }
+    tok = p = strdup_chk(line, "tok");
+    /* コメントを削除 */
+    strip_casl2_comment(p);
+    /* 文字列末尾の改行と空白を削除 */
+    strip_end(p);
     /* 空行の場合、終了 */
     /* 空行の場合、終了 */
-    if(!p[0] || p[0] == '\n') {
+    if(!p[0]) {
         goto linetokfin;
     }
     cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
 
     /* ラベルの取得 */
     /* 行の先頭が空白またはタブの場合、ラベルは空 */
         goto linetokfin;
     }
     cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
 
     /* ラベルの取得 */
     /* 行の先頭が空白またはタブの場合、ラベルは空 */
-    if((i = strcspn(p, " \t\n")) == 0) {
-        lbl = strdup_chk("", "linetok.lbl");
+    if((i = strcspn(p, " \t")) == 0) {
+        cmdl->label = strdup_chk("", "cmdl->label");
     } else {
     } else {
-        lbl = strndup_chk(p, i, "linetok.lbl");
-        /* 文字列が長すぎる場合はエラー */
+        cmdl->label = strndup_chk(p, i, "cmdl->label");
+        /* ラベルの文字列が長すぎる場合はエラー */
         if(i > LABELSIZE) {
         if(i > LABELSIZE) {
-            setcerr(104, lbl);    /* label length is too long */
-            FREE(lbl);
+            setcerr(104, cmdl->label);    /* label length is too long */
+            FREE(cmdl->label);
             goto linetokfin;
         }
             goto linetokfin;
         }
-        /* 文字列先頭をラベルの次の文字に移動 */
-        p += i;
     }
     }
-    cmdl->label = lbl;
 
     /* 命令の取得 */
 
     /* 命令の取得 */
-    /* 文字列先頭の、ラベルと命令の間の空白を削除 */
-    for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) {
-        ;
-    }
+    /* 文字列先頭をラベルの次の文字に移動 */
     p += i;
     p += i;
+    /* 文字列先頭を、ラベルと命令の間の空白の後ろに移動 */
+    p += strspn(p, " \t");
     /* 命令がない場合は、終了 */
     if(!p[0]) {
         if(cmdl->label) {      /* ラベルが定義されていて命令がない場合はエラー */
     /* 命令がない場合は、終了 */
     if(!p[0]) {
         if(cmdl->label) {      /* ラベルが定義されていて命令がない場合はエラー */
@@ -170,13 +166,10 @@ CMDLINE *linetok(const char *line)
     cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
 
     /* オペランドの取得 */
     cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
 
     /* オペランドの取得 */
-    /* 文字列の先頭を命令の次の文字に移動 */
-    p += i + 1;
-    /* 文字列先頭の、命令とオペランドの間の空白を削除 */
-    for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) {
-        ;
-    }
+    /* 文字列先頭を、命令の次の文字に移動 */
     p += i;
     p += i;
+    /* 文字列先頭を、命令とオペランドの間の空白の後ろに移動 */
+    p += strspn(p, " \t");
     /* オペランド取得の実行 */
     cmdl->opd = opdtok(p);
 linetokfin:
     /* オペランド取得の実行 */
     cmdl->opd = opdtok(p);
 linetokfin: