YACASL2
token.c
Go to the documentation of this file.
1 #include "token.h"
2 
10 OPD *opdtok(const char *str);
11 
16  { 104, "label length is too long" },
17  { 105, "no command in the line" },
18 };
19 
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" },
28 };
29 
30 OPD *opdtok(const char *str)
31 {
32  OPD *opd = malloc_chk(sizeof(OPD), "opd");
33  char *tok, *p, sepc = ',';
34  int i = 0, cnt_quote = 0;
35  bool quoting = false;
36 
37  opd->opdc = 0;
38  if(!str || !str[0]) {
39  return opd;
40  }
41  tok = p = strdup_chk(str, "opdtok.p");
42  do {
43  /* オペランド数が多すぎる場合はエラー */
44  if(opd->opdc >= OPDSIZE) {
45  setcerr(117, ""); /* operand is too many */
46  break;
47  }
48  /* 先頭が等号(=)の場合 */
49  if(p[i] == '=') {
50  i++;
51  }
52  /* 「'」の場合 */
53  if(p[i] == '\'') {
54  /* 「''」以外の場合はquote値を反転する */
55  if(p[i+1] != '\'' && (quoting == false || p[i-1] != '\'')) {
56  quoting = !quoting;
57  }
58  /* 「'」をカウントする。「''」の場合は1をカウント */
59  if(p[i+1] != '\'') {
60  cnt_quote++;
61  }
62  }
63  if(quoting == true) {
64  /* 「'」で開いたまま文字列が終了した場合 */
65  if(!p[i]) {
66  setcerr(123, str); /* unclosed quote */
67  break;
68  }
69  i++;
70  } else {
71  i += strcspn(p + i, ", ");
72  if(i == 0) {
73  setcerr(121, ""); /* cannot get operand token */
74  break;
75  }
76  if(i - cnt_quote > OPDSIZE) {
77  setcerr(118, ""); /* operand length too long */
78  break;
79  }
80  sepc = p[i];
81  opd->opdv[(opd->opdc)++] = strndup_chk(p, i, "opd->opdv[]");
82  p += i + 1;
83  i = cnt_quote = 0;
84  }
85  } while(sepc == ',');
86  FREE(tok);
87  return opd;
88 }
89 
90 /* assemble.hで定義された関数群 */
92 {
95 }
96 
97 CMDLINE *linetok(const char *line)
98 {
99  char *tok = NULL, *p = NULL;
100  int i;
101  CMDLINE *cmdl = NULL;
102 
103  assert(line);
104  if(!line[0] || line[0] == '\n') {
105  return NULL;
106  }
107  tok = p = strdup_chk(line, "tok");
108  /* コメントを削除 */
110  /* 文字列末尾の改行と空白を削除 */
111  strip_end(p);
112  /* 空行の場合、終了 */
113  if(!p[0]) {
114  goto linetokfin;
115  }
116  cmdl = malloc_chk(sizeof(CMDLINE), "cmdl");
117 
118  /* ラベルの取得 */
119  /* 行の先頭が空白またはタブの場合、ラベルは空 */
120  if((i = strcspn(p, " \t")) == 0) {
121  cmdl->label = strdup_chk("", "cmdl->label");
122  } else {
123  cmdl->label = strndup_chk(p, i, "cmdl->label");
124  /* ラベルの文字列が長すぎる場合はエラー */
125  if(i > LABELSIZE) {
126  setcerr(104, cmdl->label); /* label length is too long */
127  FREE(cmdl->label);
128  goto linetokfin;
129  }
130  }
131 
132  /* 命令の取得 */
133  /* 文字列先頭をラベルの次の文字に移動 */
134  p += i;
135  /* 文字列先頭を、ラベルと命令の間の空白の後ろに移動 */
136  p += strspn(p, " \t");
137  /* 命令がない場合は、終了 */
138  if(!p[0]) {
139  if(cmdl->label) { /* ラベルが定義されていて命令がない場合はエラー */
140  setcerr(105, ""); /* no command in the line */
141  }
142  FREE(cmdl->label);
143  FREE(cmdl);
144  goto linetokfin;
145  }
146  /* 命令取得の実行 */
147  i = strcspn(p, " \t");
148  cmdl->cmd = strndup_chk(p, i, "cmdl.cmd");
149 
150  /* オペランドの取得 */
151  /* 文字列先頭を、命令の次の文字に移動 */
152  p += i;
153  /* 文字列先頭を、命令とオペランドの間の空白の後ろに移動 */
154  p += strspn(p, " \t");
155  /* オペランド取得の実行 */
156  cmdl->opd = opdtok(p);
157 linetokfin:
158  FREE(tok);
159  return cmdl;
160 }
void addcerrlist(int cerrc, CERR cerrv[])
エラーリストを作成・追加する
Definition: cerr.c:13
void setcerr(int num, const char *str)
現在のエラーを設定する
Definition: cerr.c:45
char * strndup_chk(const char *s, size_t len, const char *tag)
malloc_chkを実行してメモリを確保し、コピーした文字列の指定した長さの部分を返す
Definition: cmem.c:33
#define FREE(ptr)
メモリを解放するマクロ
Definition: cmem.h:21
void strip_end(char *s)
文字列の末尾から、改行と空白とタブを削除する
Definition: cmem.c:48
char * strdup_chk(const char *s, const char *tag)
malloc_chkを実行してメモリを確保し、コピーした文字列を返す
Definition: cmem.c:25
void strip_casl2_comment(char *s)
文字列から「'」以降の文字列をCASL IIのコメントとして削除する。「''」の場合は除く
Definition: cmem.c:55
#define ARRAYSIZE(array)
配列のサイズを返すマクロ
Definition: cmem.h:14
void * malloc_chk(size_t size, const char *tag)
mallocを実行し、0で初期化する
Definition: cmem.c:3
エラーを表すデータ型
Definition: cerr.h:15
命令行を表すデータ型
Definition: token.h:41
OPD * opd
Definition: token.h:44
char * cmd
Definition: token.h:43
char * label
Definition: token.h:42
オペランドを表すデータ型
Definition: token.h:33
int opdc
Definition: token.h:34
char * opdv[OPDSIZE]
Definition: token.h:35
void addcerrlist_tok()
トークン取得のエラーを追加する
Definition: token.c:91
static CERR cerr_opdtok[]
オペランドトークン取得のエラー定義
Definition: token.c:23
OPD * opdtok(const char *str)
「,」区切りの文字列から、オペランドのトークンを取得
Definition: token.c:30
CERR cerr_linetok[]
行トークン取得のエラー定義
Definition: token.c:15
CMDLINE * linetok(const char *line)
行から、ラベル・コマンド・オペランドを取得する
Definition: token.c:97
@ LABELSIZE
Definition: token.h:18
@ OPDSIZE
Definition: token.h:19