X-Git-Url: http://j8takagi.net/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ftoken.c;h=b6d971c854fecc378dee9a4c0c4bd20600576200;hb=a0ccd206e7e3a3c0a5d73abf5ad6a16ed13e6955;hp=a3285328dfd2c05a08069131cd46de655d335198;hpb=9e915630081faeda3fa9d0fcb90de379661333be;p=YACASL2.git diff --git a/src/token.c b/src/token.c index a328532..b6d971c 100644 --- a/src/token.c +++ b/src/token.c @@ -102,48 +102,62 @@ void addcerrlist_tok() CMDLINE *linetok(const char *line) { - char *tok, *p; + char *tok = NULL, *p = NULL, *lbl = NULL; int i; bool quoting = false; CMDLINE *cmdl = NULL; - if(!line[0]) { + if(!line[0] || line[0] == '\n') { return NULL; } tok = p = strdup_chk(line, "tok"); /* コメントを削除 */ for(i = 0; p[i]; i++) { - /* 「'」で囲まれた文字列の処理。「''」は無視 */ - if(p[i] == '\'' && p[i+1] != '\'' && !(i > 0 && p[i-1] == '\'')) { + /* 「'」で囲まれた文字列の場合。「''」は無視 */ + if(p[i] == '\'' && p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) { quoting = !quoting; + /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */ } else if(quoting == false && p[i] == ';') { p[i] = '\0'; break; } } + /* 文字列末尾の改行と空白を削除 */ + i = strlen(p) - 1; + while(i > 0 && (p[i] == '\n' || p[i] == ' ' || p[i] == '\t')) { + p[i--] = '\0'; + } + /* 空行の場合、終了 */ 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 = strcspn(p, " \t\n")) == 0) { + lbl = strdup_chk("", "linetok.lbl"); + } else { + lbl = strndup_chk(p, i, "linetok.lbl"); /* 文字列が長すぎる場合はエラー */ if(i > LABELSIZE) { - p[i] = '\0'; - setcerr(104, p); /* label length is too long */ - } else { - cmdl->label = strndup_chk(p, i, "cmdl->label"); + setcerr(104, lbl); /* label length is too long */ + FREE(lbl); + goto linetokfin; } - p += i + 1; + /* 文字列先頭をラベルの次の文字に移動 */ + p += i; } - /* ラベルと命令の間の空白をスキップ */ - while(p[0] == ' ' || p[0] == '\t') { - p++; + cmdl->label = lbl; + + /* 命令の取得 */ + /* 文字列先頭の、ラベルと命令の間の空白を削除 */ + for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) { + ; } - /* 命令とオペランドの取得 */ - if(!p[0] || p[0] == '\n') { /* 命令がない場合は、終了 */ + p += i; + /* 命令がない場合は、終了 */ + if(!p[0]) { if(cmdl->label) { /* ラベルが定義されていて命令がない場合はエラー */ setcerr(105, ""); /* no command in the line */ } @@ -151,24 +165,20 @@ CMDLINE *linetok(const char *line) FREE(cmdl); goto linetokfin; } - /* 命令の取得 */ - i = strcspn(p, " \t\n"); - p[i] = '\0'; - cmdl->cmd = strdup_chk(p, "cmdl.cmd"); + /* 命令取得の実行 */ + i = strcspn(p, " \t"); + cmdl->cmd = strndup_chk(p, i, "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; + /* 文字列先頭の、命令とオペランドの間の空白を削除 */ + for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) { + ; } + p += i; + /* オペランド取得の実行 */ + cmdl->opd = opdtok(p); linetokfin: FREE(tok); return cmdl;