4 * @brief 「,」区切りの文字列から、オペランドのトークンを取得
8 * @param *str 「,」区切りの文字列
10 OPD *opdtok(const char *str);
13 * @brief 行トークン取得のエラー定義
15 CERR cerr_linetok[] = {
16 { 104, "label length is too long" },
17 { 105, "no command in the line" },
21 * @brief オペランドトークン取得のエラー定義
23 static CERR cerr_opdtok[] = {
24 { 117, "operand too many in DC" },
25 { 118, "operand length too long" },
26 { 121, "cannot get operand token" },
27 { 123, "unclosed quote" },
30 OPD *opdtok(const char *str)
32 OPD *opd = malloc_chk(sizeof(OPD), "opd");
33 char *tok, *p, sepc = ',';
34 int i = 0, cnt_quote = 0;
41 tok = p = strdup_chk(str, "opdtok.p");
43 /* オペランド数が多すぎる場合はエラー */
44 if(opd->opdc >= OPDSIZE) {
45 setcerr(117, ""); /* operand is too many */
54 /* 「''」以外の場合はquote値を反転する */
55 if(p[i+1] != '\'' && (quoting == false || p[i-1] != '\'')) {
58 /* 「'」をカウントする。「''」の場合は1をカウント */
64 /* 「'」で開いたまま文字列が終了した場合 */
66 setcerr(123, str); /* unclosed quote */
71 i += strcspn(p + i, ", ");
73 setcerr(121, ""); /* cannot get operand token */
76 if(i - cnt_quote > OPDSIZE) {
77 setcerr(118, ""); /* operand length too long */
81 opd->opdv[(opd->opdc)++] = strndup_chk(p, i, "opd->opdv[]");
90 /* assemble.hで定義された関数群 */
91 void addcerrlist_tok()
93 addcerrlist(ARRAYSIZE(cerr_linetok), cerr_linetok);
94 addcerrlist(ARRAYSIZE(cerr_opdtok), cerr_opdtok);
97 char *strip_casl2_comment(char *s)
100 bool quoting = false;
102 for(i = 0; s[i]; i++) {
103 /* 「'」で囲まれた文字列の場合。「''」は無視 */
104 if(s[i] == '\'' && s[i+1] != '\'' && (quoting == false || s[i-1] != '\'')) {
106 /* 「'」で囲まれた文字列でない場合、文字列末尾の「;」以降を削除 */
107 } else if(quoting == false && s[i] == ';') {
115 CMDLINE *linetok(const char *line)
117 char *tok = NULL, *p = NULL;
119 CMDLINE *cmdl = NULL;
122 if(!line[0] || line[0] == '\n') {
125 tok = p = strdup_chk(line, "tok");
127 strip_casl2_comment(p);
134 cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
137 /* 行の先頭が空白またはタブの場合、ラベルは空 */
138 if((i = strcspn(p, " \t")) == 0) {
139 cmdl->label = strdup_chk("", "cmdl->label");
141 cmdl->label = strndup_chk(p, i, "cmdl->label");
142 /* ラベルの文字列が長すぎる場合はエラー */
144 setcerr(104, cmdl->label); /* label length is too long */
151 /* 文字列先頭をラベルの次の文字に移動 */
153 /* 文字列先頭を、ラベルと命令の間の空白の後ろに移動 */
154 p += strspn(p, " \t");
157 if(cmdl->label) { /* ラベルが定義されていて命令がない場合はエラー */
158 setcerr(105, ""); /* no command in the line */
165 i = strcspn(p, " \t");
166 cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
169 /* 文字列先頭を、命令の次の文字に移動 */
171 /* 文字列先頭を、命令とオペランドの間の空白の後ろに移動 */
172 p += strspn(p, " \t");
174 cmdl->opd = opdtok(p);