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");
37 char *tok, *p, sepc = ',';
38 int i = 0, cnt_quote = 0;
45 tok = p = strdup_chk(str, "opdtok.p");
47 /* オペランド数が多すぎる場合はエラー */
48 if(opd->opdc >= OPDSIZE) {
49 setcerr(117, ""); /* operand is too many */
58 /* 「''」以外の場合はquote値を反転する */
59 if(p[i+1] != '\'' && (i == 0 || p[i-1] != '\'')) {
62 /* 「'」をカウントする。「''」の場合は1をカウント */
68 /* 「'」で開いたまま文字列が終了した場合 */
70 setcerr(123, str); /* unclosed quote */
75 i += strcspn(p + i, ", ");
77 setcerr(121, ""); /* cannot get operand token */
80 if(i - cnt_quote > OPDSIZE) {
81 setcerr(118, ""); /* operand length too long */
85 opd->opdv[(opd->opdc)++] = strndup_chk(p, i, "opd->opdv[]");
94 /* assemble.hで定義された関数群 */
95 void addcerrlist_tok()
97 addcerrlist(ARRAYSIZE(cerr_linetok), cerr_linetok);
98 addcerrlist(ARRAYSIZE(cerr_opdtok), cerr_opdtok);
101 char *strip_casl2_comment(char *s)
104 bool quoting = false;
106 for(i = 0; s[i]; i++) {
107 /* 「'」で囲まれた文字列の場合。「''」は無視 */
108 if(s[i] == '\'' && s[i+1] != '\'' && (i == 0 || s[i-1] != '\'')) {
110 /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */
111 } else if(quoting == false && s[i] == ';') {
119 CMDLINE *linetok(const char *line)
121 char *tok = NULL, *p = NULL, *lbl = NULL;
123 CMDLINE *cmdl = NULL;
125 if(!line[0] || line[0] == '\n') {
128 tok = p = strdup_chk(line, "tok");
130 strip_casl2_comment(p);
137 cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
140 /* 行の先頭が空白またはタブの場合、ラベルは空 */
141 if((i = strcspn(p, " \t")) == 0) {
142 lbl = strdup_chk("", "linetok.lbl");
144 lbl = strndup_chk(p, i, "linetok.lbl");
145 /* ラベルの文字列が長すぎる場合はエラー */
147 setcerr(104, lbl); /* label length is too long */
151 /* 文字列先頭をラベルの次の文字に移動 */
158 /* 文字列先頭を、ラベルと命令の間の空白の後ろに移動 */
159 p += strspn(p, " \t");
162 if(cmdl->label) { /* ラベルが定義されていて命令がない場合はエラー */
163 setcerr(105, ""); /* no command in the line */
170 i = strcspn(p, " \t");
171 cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
174 /* 文字列先頭を、命令の次の文字に移動 */
176 /* 文字列先頭を、命令とオペランドの間の空白の後ろに移動 */
177 p += strspn(p, " \t");
179 cmdl->opd = opdtok(p);