ソースコードの推敲
authorj8takagi <j8takagi@nifty.com>
Sat, 9 Feb 2019 14:40:56 +0000 (23:40 +0900)
committerj8takagi <j8takagi@nifty.com>
Sat, 9 Feb 2019 14:40:56 +0000 (23:40 +0900)
src/token.c

index 457ca8f..a328532 100644 (file)
@@ -34,15 +34,16 @@ static CERR cerr_opdtok[] = {
 OPD *opdtok(const char *str)
 {
     OPD *opd = malloc_chk(sizeof(OPD), "opd");
-    char *p, *q, *r, *sepp;     /* pは文字列全体の先頭位置、qはトークンの先頭位置、rは文字の位置 */
-    int sepc = ',', rcnt = 0;
+    char *tok, *p;
+    char sepc = ',';
+    int i = 0, cnt_quote = 0;
     bool quoting = false;
 
     opd->opdc = 0;
-    if(str == NULL) {
+    if(str == NULL || !str[0]) {
         return opd;
     }
-    p = q = r = strdup_chk(str, "opdtok.p");
+    tok = p = strdup_chk(str, "opdtok.p");
     do {
         /* オペランド数が多すぎる場合はエラー */
         if(opd->opdc >= OPDSIZE) {
@@ -50,45 +51,45 @@ OPD *opdtok(const char *str)
             break;
         }
         /* 先頭が等号(=)の場合 */
-        if(r[0] == '=') {
-            r++;
+        if(p[i] == '=') {
+            i++;
         }
         /* 「'」の場合 */
-        if(r[0] == '\'') {
-            /* 「''」以外の場合はquote値を反転 */
-            if(r[1] != '\'' && !(q < r && r[-1] == '\'')) {
+        if(p[i] == '\'') {
+            /* 「''」以外の場合はquote値を反転する */
+            if(p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) {
                 quoting = !quoting;
             }
-            /* 文字列の長さを数える。「'」の場合は数えない */
-            if(r[1] != '\'') {
-                rcnt++;
+            /* 「'」をカウントする。「''」の場合は1をカウント */
+            if(p[i+1] != '\'') {
+                cnt_quote++;
             }
         }
         if(quoting == true) {
-            /* 閉じ「'」がないまま文字列が終了した場合 */
-            if(!r[0]) {
+            /* 「'」で開いたまま文字列が終了した場合 */
+            if(!p[i]) {
                 setcerr(123, str);    /* unclosed quote */
                 break;
             }
-            r++;
+            i++;
         } else {
-            sepp = r + strcspn(r, ", ");
-            sepc = sepp[0];
-            strcpy(sepp, "");
-            if(!q[0]) {
+            i += strcspn(p + i, ", ");
+            sepc = p[i];
+            p[i] = '\0';
+            if(!p[0]) {
                 setcerr(121, "");    /* cannot get operand token */
                 break;
             }
-            if(strlen(q) - rcnt > OPDSIZE) {
+            if(strlen(p) - cnt_quote > OPDSIZE) {
                 setcerr(118, "");    /* operand length too long */
                 break;
             }
-            opd->opdv[(++opd->opdc)-1] = strdup_chk(q, "opd.opdv[]");
-            q = r = sepp + 1;
-            rcnt = 0;
+            opd->opdv[(++opd->opdc)-1] = strdup_chk(p, "opd.opdv[]");
+            p += i + 1;
+            i = cnt_quote = 0;
         }
     } while(sepc == ',');
-    FREE(p);
+    FREE(tok);
     return opd;
 }
 
@@ -101,73 +102,74 @@ void addcerrlist_tok()
 
 CMDLINE *linetok(const char *line)
 {
-    char *tokens, *p, *sepp;
+    char *tok, *p;
+    int i;
     bool quoting = false;
     CMDLINE *cmdl = NULL;
 
     if(!line[0]) {
         return NULL;
     }
-    tokens = strdup_chk(line, "tokens");
+    tok = p = strdup_chk(line, "tok");
     /* コメントを削除 */
-    for(p = tokens; p[0]; p++) {
+    for(i = 0; p[i]; i++) {
         /* 「'」で囲まれた文字列の処理。「''」は無視 */
-        if(p[0] == '\'' && p[1] != '\'' && !(p > tokens && p[-1] == '\'')) {
+        if(p[i] == '\'' && p[i+1] != '\'' && !(i > 0 && p[i-1] == '\'')) {
             quoting = !quoting;
-        } else if(quoting == false && p[0] == ';') {
-            strcpy(p, "");
+        } else if(quoting == false && p[i] == ';') {
+            p[i] = '\0';
             break;
         }
     }
-    if(tokens[0] && tokens[0] != '\n') {
-        p = tokens;
-        cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
-        cmdl->label = malloc_chk(LABELSIZE + 1, "cmdl.label");
-        /* ラベルの取得。行の先頭が空白またはタブの場合、ラベルは空 */
-        if((sepp = p + strcspn(p, " \t\n")) == p){
-            strcpy(cmdl->label, "");
-        } else {        /* ラベルを取得 */
-            strcpy(sepp, "");
-            /* 文字列が長すぎる場合はエラー */
-            if(strlen(p) > LABELSIZE) {
-                setcerr(104, p);    /* label length is too long */
-            } else {
-                strcpy(cmdl->label, p);
-            }
-            p = sepp + 1;
-        }
-        /* ラベルと命令の間の空白をスキップ */
-        while(p[0] == ' ' || p[0] == '\t') {
-            p++;
-        }
-        /* 命令とオペランドの取得 */
-        if(!p[0] || p[0] == '\n') {        /* 命令がない場合は、終了 */
-            if(cmdl->label) {      /* ラベルが定義されていて命令がない場合はエラー */
-                setcerr(105, "");    /* no command in the line */
-            }
-            FREE(cmdl->label);
-            FREE(cmdl);
+    if(!p[0] || p[0] == '\n') {
+        goto linetokfin;
+    }
+    cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
+    /* ラベルの取得。行の先頭が空白またはタブの場合、ラベルは空 */
+    if((i = strcspn(p, " \t\n")) == 0){
+        cmdl->label = strdup_chk("", "cmdl->label");
+    } else {        /* ラベルを取得 */
+        /* 文字列が長すぎる場合はエラー */
+        if(i > LABELSIZE) {
+            p[i] = '\0';
+            setcerr(104, p);    /* label length is too long */
         } else {
-            /* 命令の取得 */
-            sepp = p + strcspn(p, " \t\n");
-            strcpy(sepp, "");
-            cmdl->cmd = strdup_chk(p, "cmdl.cmd");
-            p = sepp + 1;
-            /* 命令とオペランドの間の空白をスキップ */
-            while(p[0] == ' ' || p[0] == '\t') {
-                p++;
-            }
-            /* 改行かタブまでの文字列を取得 */
-            /* 「'」で囲まれた文字列に含まれる場合があるため、空白は無視 */
-            if((sepp = p + strcspn(p, "\t\n")) > p) {
-                strcpy(sepp, "");
-                cmdl->opd = opdtok(p);
-            } else {
-                cmdl->opd = malloc_chk(sizeof(OPD), "cmdl.opd");
-                cmdl->opd->opdc = 0;
-            }
+            cmdl->label = strndup_chk(p, i, "cmdl->label");
+        }
+        p += i + 1;
+    }
+    /* ラベルと命令の間の空白をスキップ */
+    while(p[0] == ' ' || p[0] == '\t') {
+        p++;
+    }
+    /* 命令とオペランドの取得 */
+    if(!p[0] || p[0] == '\n') {        /* 命令がない場合は、終了 */
+        if(cmdl->label) {      /* ラベルが定義されていて命令がない場合はエラー */
+            setcerr(105, "");    /* no command in the line */
         }
+        FREE(cmdl->label);
+        FREE(cmdl);
+        goto linetokfin;
+    }
+    /* 命令の取得 */
+    i = strcspn(p, " \t\n");
+    p[i] = '\0';
+    cmdl->cmd = strdup_chk(p, "cmdl.cmd");
+    p += i + 1;
+    /* 命令とオペランドの間の空白をスキップ */
+    while(p[0] == ' ' || p[0] == '\t') {
+        p++;
+    }
+    /* 改行かタブまでの文字列を取得 */
+    /* 「'」で囲まれた文字列に含まれる場合があるため、空白は無視 */
+    if((i = strcspn(p, "\t\n")) > 0) {
+        p[i] = '\0';
+        cmdl->opd = opdtok(p);
+    } else {
+        cmdl->opd = malloc_chk(sizeof(OPD), "cmdl.opd");
+        cmdl->opd->opdc = 0;
     }
-    FREE(tokens);
+linetokfin:
+    FREE(tok);
     return cmdl;
 }