8 * @brief 「,」区切りの文字列から、オペランドのトークンを取得
12 * @param *str 「,」区切りの文字列
14 OPD *opdtok(const char *str);
17 * @brief 行トークン取得のエラー定義
19 CERR cerr_linetok[] = {
20 { 104, "label length is too long" },
21 { 105, "no command in the line" },
25 * @brief オペランドトークン取得のエラー定義
27 static CERR cerr_opdtok[] = {
28 { 117, "operand too many in DC" },
29 { 118, "operand length too long" },
30 { 121, "cannot get operand token" },
31 { 123, "unclosed quote" },
34 OPD *opdtok(const char *str)
36 OPD *opd = malloc_chk(sizeof(OPD), "opd");
39 int i = 0, cnt_quote = 0;
43 if(str == NULL || !str[0]) {
46 tok = p = strdup_chk(str, "opdtok.p");
48 /* オペランド数が多すぎる場合はエラー */
49 if(opd->opdc >= OPDSIZE) {
50 setcerr(117, ""); /* operand is too many */
59 /* 「''」以外の場合はquote値を反転する */
60 if(p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) {
63 /* 「'」をカウントする。「''」の場合は1をカウント */
69 /* 「'」で開いたまま文字列が終了した場合 */
71 setcerr(123, str); /* unclosed quote */
76 i += strcspn(p + i, ", ");
80 setcerr(121, ""); /* cannot get operand token */
83 if(strlen(p) - cnt_quote > OPDSIZE) {
84 setcerr(118, ""); /* operand length too long */
87 opd->opdv[(++opd->opdc)-1] = strdup_chk(p, "opd.opdv[]");
96 /* assemble.hで定義された関数群 */
97 void addcerrlist_tok()
99 addcerrlist(ARRAYSIZE(cerr_linetok), cerr_linetok);
100 addcerrlist(ARRAYSIZE(cerr_opdtok), cerr_opdtok);
103 CMDLINE *linetok(const char *line)
105 char *tok = NULL, *p = NULL, *lbl = NULL;
107 bool quoting = false;
108 CMDLINE *cmdl = NULL;
110 if(!line[0] || line[0] == '\n') {
113 tok = p = strdup_chk(line, "tok");
115 for(i = 0; p[i]; i++) {
116 /* 「'」で囲まれた文字列の場合。「''」は無視 */
117 if(p[i] == '\'' && p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) {
119 /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */
120 } else if(quoting == false && p[i] == ';') {
127 while(i > 0 && (p[i] == '\n' || p[i] == ' ' || p[i] == '\t')) {
131 if(!p[0] || p[0] == '\n') {
134 cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
137 /* 行の先頭が空白またはタブの場合、ラベルは空 */
138 if((i = strcspn(p, " \t\n")) == 0) {
139 lbl = strdup_chk("", "linetok.lbl");
141 lbl = strndup_chk(p, i, "linetok.lbl");
144 setcerr(104, lbl); /* label length is too long */
148 /* 文字列先頭をラベルの次の文字に移動 */
154 /* 文字列先頭の、ラベルと命令の間の空白を削除 */
155 for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) {
161 if(cmdl->label) { /* ラベルが定義されていて命令がない場合はエラー */
162 setcerr(105, ""); /* no command in the line */
169 i = strcspn(p, " \t");
170 cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
173 /* 文字列の先頭を命令の次の文字に移動 */
175 /* 文字列先頭の、命令とオペランドの間の空白を削除 */
176 for(i = 0; p[i] == ' ' || p[i] == '\t'; i++) {
181 cmdl->opd = opdtok(p);