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)
107 bool quoting = false;
108 CMDLINE *cmdl = NULL;
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 } else if(quoting == false && p[i] == ';') {
124 if(!p[0] || p[0] == '\n') {
127 cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
128 /* ラベルの取得。行の先頭が空白またはタブの場合、ラベルは空 */
129 if((i = strcspn(p, " \t\n")) == 0){
130 cmdl->label = strdup_chk("", "cmdl->label");
131 } else { /* ラベルを取得 */
135 setcerr(104, p); /* label length is too long */
137 cmdl->label = strndup_chk(p, i, "cmdl->label");
141 /* ラベルと命令の間の空白をスキップ */
142 while(p[0] == ' ' || p[0] == '\t') {
146 if(!p[0] || p[0] == '\n') { /* 命令がない場合は、終了 */
147 if(cmdl->label) { /* ラベルが定義されていて命令がない場合はエラー */
148 setcerr(105, ""); /* no command in the line */
155 i = strcspn(p, " \t\n");
157 cmdl->cmd = strdup_chk(p, "cmdl.cmd");
159 /* 命令とオペランドの間の空白をスキップ */
160 while(p[0] == ' ' || p[0] == '\t') {
164 /* 「'」で囲まれた文字列に含まれる場合があるため、空白は無視 */
165 if((i = strcspn(p, "\t\n")) > 0) {
167 cmdl->opd = opdtok(p);
169 cmdl->opd = malloc_chk(sizeof(OPD), "cmdl.opd");