トークンの処理を推敲
authorj8takagi <j8takagi@nifty.com>
Fri, 15 Feb 2019 15:16:07 +0000 (00:16 +0900)
committerj8takagi <j8takagi@nifty.com>
Fri, 15 Feb 2019 15:16:07 +0000 (00:16 +0900)
include/cmem.h
src/cmem.c
src/monitor.c
src/token.c
test/unit/strip_end/0.txt [new file with mode: 0644]
test/unit/strip_end/Makefile [new file with mode: 0644]
test/unit/strip_end/cmd.c [new file with mode: 0644]

index fca5acb..134baa8 100644 (file)
@@ -44,7 +44,7 @@ void *malloc_chk(size_t size, const char *tag);
  * @param size 領域1個あたりのメモリーサイズ
  * @param tag エラーメッセージなどで表示されるタグ
  */
-void *calloc_chk(size_t nmemb, size_t size, char *tag);
+void *calloc_chk(size_t nmemb, size_t size, const char *tag);
 
 /**
  * @brief malloc_chkを実行してメモリを確保し、コピーした文字列を返す
@@ -54,7 +54,7 @@ void *calloc_chk(size_t nmemb, size_t size, char *tag);
  * @param s 文字列
  * @param tag エラーメッセージなどで表示されるタグ
  */
-char *strdup_chk(const char *s, char *tag);
+char *strdup_chk(const char *s, const char *tag);
 
 /**
  * @brief malloc_chkを実行してメモリを確保し、コピーした文字列の指定した長さの部分を返す
@@ -65,5 +65,14 @@ char *strdup_chk(const char *s, char *tag);
  * @param len 文字列の長さ
  * @param tag エラーメッセージなどで表示されるタグ
  */
-char *strndup_chk(const char *s, size_t len, char *tag);
+char *strndup_chk(const char *s, size_t len, const char *tag);
+
+/**
+ * @brief 文字列の末尾から、改行と空白とタブを削除する
+ *
+ * @return 末尾から改行と空白とタブを削除した文字列
+ *
+ * @param s 文字列
+ */
+char *strip_end(char *s);
 #endif
index 17535d8..e921bb0 100644 (file)
@@ -2,7 +2,7 @@
 
 void *malloc_chk(size_t size, const char *tag)
 {
-    void *p;
+    void *p = NULL;
 
     if((p = malloc(size)) == NULL) {
         fprintf(stderr, "%s: cannot allocate memory\n", tag);
@@ -11,9 +11,9 @@ void *malloc_chk(size_t size, const char *tag)
     return memset(p, 0, size);
 }
 
-void *calloc_chk(size_t nmemb, size_t size, char *tag)
+void *calloc_chk(size_t nmemb, size_t size, const char *tag)
 {
-    void *p;
+    void *p = NULL;
 
     if((p = calloc(nmemb, size)) == NULL) {
         fprintf(stderr, "%s: cannot allocate memory\n", tag);
@@ -22,20 +22,20 @@ void *calloc_chk(size_t nmemb, size_t size, char *tag)
     return p;
 }
 
-char *strdup_chk(const char *s, char *tag)
+char *strdup_chk(const char *s, const char *tag)
 {
     assert(s != NULL);
-    char *t;
+    char *t = NULL;
 
     t = malloc_chk(strlen(s) + 1, tag);
     strcpy(t, s);
     return t;
 }
 
-char *strndup_chk(const char *s, size_t len, char *tag)
+char *strndup_chk(const char *s, size_t len, const char *tag)
 {
     assert(s != NULL);
-    char *t;
+    char *t = NULL;
 
     if(len < strlen(s)) {
         t = malloc_chk(len + 1, tag);
@@ -46,3 +46,13 @@ char *strndup_chk(const char *s, size_t len, char *tag)
     }
     return t;
 }
+
+char *strip_end(char *s)
+{
+    int i;
+    i = strlen(s) - 1;
+    while(i > 0 && (s[i] == '\n' || s[i] == ' ' || s[i] == '\t')) {
+        s[i--] = '\0';
+    }
+    return s;
+}
index 89ad918..69da165 100644 (file)
@@ -123,25 +123,22 @@ void freebps()
 MONARGS *monargstok(const char *str)
 {
     MONARGS *args = malloc_chk(sizeof(MONARGS), "args");
-    char *p, *q, *r, *sepp;     /* pは文字列全体の先頭位置、qはトークンの先頭位置、rは文字の位置 */
-    int sepc = ' ';
+    char *tok, *p, sepc = ' ';
+    int i = 0;
 
     args->argc = 0;
-    if(str == NULL) {
+    if(!str || !str[0]) {
         return args;
     }
-    p = q = r = strdup_chk(str, "argstok.p");
+    tok = p = strdup_chk(str, "argstok.p");
     do {
-        while(*q == ' ' || *q == '\t'){
-            q = ++r;
-        }
-        sepp = r + strcspn(r, " ");
-        sepc = *sepp;
-        strcpy(sepp, "");
-        args->argv[++(args->argc)-1] = strdup_chk(q, "args.argv[]");
-        q = r = sepp + 1;
+        i = strcspn(p, " ");
+        sepc = p[i];
+        args->argv[(args->argc)++] = strndup_chk(p, i, "args->argv[]");
+        p += i + 1;
+        i = 0;
     } while(sepc == ' ');
-    FREE(p);
+    FREE(tok);
     return args;
 }
 
@@ -275,7 +272,7 @@ MONCMDTYPE monitorcmd(char *cmd, MONARGS *args)
     } else if(stracmp(cmd, 2, (char* []){"d", "dump"})) {
         mon_dump(args->argc, args->argv);
     } else if(stracmp(cmd, 2, (char* []){"l", "load"})) {
-        loadassemble(args->argv[0], nh2word(args->argv[1]));
+        execptr->end = loadassemble(args->argv[0], nh2word(args->argv[1]));
     } else if(stracmp(cmd, 2, (char* []){"n", "next"})) {
         execmode.step = true;
         cmdtype = MONNEXT;
index b6d971c..fa531b5 100644 (file)
@@ -34,13 +34,12 @@ static CERR cerr_opdtok[] = {
 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;
-    if(str == NULL || !str[0]) {
+    if(!str || !str[0]) {
         return opd;
     }
     tok = p = strdup_chk(str, "opdtok.p");
@@ -74,17 +73,16 @@ OPD *opdtok(const char *str)
             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;
             }
-            if(strlen(p) - cnt_quote > OPDSIZE) {
+            if(i - cnt_quote > OPDSIZE) {
                 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;
         }
@@ -100,11 +98,28 @@ void addcerrlist_tok()
     addcerrlist(ARRAYSIZE(cerr_opdtok), cerr_opdtok);
 }
 
+char *strip_casl2_comment(char *s)
+{
+    int i;
+    bool quoting = false;
+
+    for(i = 0; s[i]; i++) {
+        /* 「'」で囲まれた文字列の場合。「''」は無視 */
+        if(s[i] == '\'' && s[i+1] != '\'' && (i == 0 || s[i-1] != '\'')) {
+            quoting = !quoting;
+        /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */
+        } else if(quoting == false && s[i] == ';') {
+            s[i] = '\0';
+            break;
+        }
+    }
+    return s;
+}
+
 CMDLINE *linetok(const char *line)
 {
     char *tok = NULL, *p = NULL, *lbl = NULL;
     int i;
-    bool quoting = false;
     CMDLINE *cmdl = NULL;
 
     if(!line[0] || line[0] == '\n') {
@@ -112,34 +127,22 @@ CMDLINE *linetok(const char *line)
     }
     tok = p = strdup_chk(line, "tok");
     /* コメントを削除 */
-    for(i = 0; p[i]; i++) {
-        /* 「'」で囲まれた文字列の場合。「''」は無視 */
-        if(p[i] == '\'' && p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) {
-            quoting = !quoting;
-        /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */
-        } else if(quoting == false && p[i] == ';') {
-            p[i] = '\0';
-            break;
-        }
-    }
+    strip_casl2_comment(p);
     /* 文字列末尾の改行と空白を削除 */
-    i = strlen(p) - 1;
-    while(i > 0 && (p[i] == '\n' || p[i] == ' ' || p[i] == '\t')) {
-        p[i--] = '\0';
-    }
+    strip_end(p);
     /* 空行の場合、終了 */
-    if(!p[0] || p[0] == '\n') {
+    if(!p[0]) {
         goto linetokfin;
     }
     cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
 
     /* ラベルの取得 */
     /* 行の先頭が空白またはタブの場合、ラベルは空 */
-    if((i = strcspn(p, " \t\n")) == 0) {
+    if((i = strcspn(p, " \t")) == 0) {
         lbl = strdup_chk("", "linetok.lbl");
     } else {
         lbl = strndup_chk(p, i, "linetok.lbl");
-        /* 文字列が長すぎる場合はエラー */
+        /* ラベルの文字列が長すぎる場合はエラー */
         if(i > LABELSIZE) {
             setcerr(104, lbl);    /* label length is too long */
             FREE(lbl);
@@ -148,14 +151,12 @@ CMDLINE *linetok(const char *line)
         /* 文字列先頭をラベルの次の文字に移動 */
         p += i;
     }
+    /* ラベル取得の実行 */
     cmdl->label = lbl;
 
     /* 命令の取得 */
-    /* 文字列先頭の、ラベルと命令の間の空白を削除 */
-    for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) {
-        ;
-    }
-    p += i;
+    /* 文字列先頭を、ラベルと命令の間の空白の後ろに移動 */
+    p += strspn(p, " \t");
     /* 命令がない場合は、終了 */
     if(!p[0]) {
         if(cmdl->label) {      /* ラベルが定義されていて命令がない場合はエラー */
@@ -170,13 +171,10 @@ CMDLINE *linetok(const char *line)
     cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
 
     /* オペランドの取得 */
-    /* 文字列の先頭を命令の次の文字に移動 */
-    p += i + 1;
-    /* 文字列先頭の、命令とオペランドの間の空白を削除 */
-    for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) {
-        ;
-    }
+    /* 文字列先頭を、命令の次の文字に移動 */
     p += i;
+    /* 文字列先頭を、命令とオペランドの間の空白の後ろに移動 */
+    p += strspn(p, " \t");
     /* オペランド取得の実行 */
     cmdl->opd = opdtok(p);
 linetokfin:
diff --git a/test/unit/strip_end/0.txt b/test/unit/strip_end/0.txt
new file mode 100644 (file)
index 0000000..df55f75
--- /dev/null
@@ -0,0 +1,5 @@
+abc:
+abc:
+abc:
+abc:
+abc:
diff --git a/test/unit/strip_end/Makefile b/test/unit/strip_end/Makefile
new file mode 100644 (file)
index 0000000..c9ff667
--- /dev/null
@@ -0,0 +1,20 @@
+include ../Define.mk
+include ../Test.mk
+
+CC := gcc
+CFLAGS := -Wall
+
+.INTERMEDIATE: $(CMD_FILE)
+
+CMDSRC_FILE := cmd.c
+TARGETDIR := ../../../src
+INCLUDEDIR := ../../../include
+TESTTARGET_FILES := $(TARGETDIR)/cmem.c         # Set test target files
+
+$(CMD_FILE): $(CMDSRC_FILE) $(TESTTARGET_FILES)
+       $(CC) $(CFLAGS) -I $(INCLUDEDIR) -o $@ $^
+
+clean_cmd:
+       @rm -rf cmd.dSYM cmd
+
+clean: clean_cmd
diff --git a/test/unit/strip_end/cmd.c b/test/unit/strip_end/cmd.c
new file mode 100644 (file)
index 0000000..d7122e4
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include "cmem.h"
+
+int main(){
+    char s[][10] = {"abc\n", "abc    ", "abc\t", "abc\t\n", "abc"};
+
+    for(int i = 0; i < sizeof(s) / sizeof(s[0]); i++) {
+        printf("%s:\n", strip_end(s[i]));
+    }
+    return 0;
+}