ソースの推敲
[YACASL2.git] / src / label.c
1 #include "assemble.h"
2
3 /**
4  * ラベルのハッシュ値をセットしたキーを返す
5  *
6  * @return ハッシュ値をセットしたキー
7  *
8  * @param value 値
9  */
10 HKEY *label_hashkey(const char *value);
11
12 /**
13  * プログラム名とラベルに対応するハッシュ値を返す
14  *
15  * @return ハッシュ値
16  *
17  * @param prog プログラム名
18  * @param label ラベル
19  */
20 unsigned labelhash(const char *prog, const char *label);
21
22 /**
23  * ラベルを比較した結果を返す。qsort内で使われる関数
24  *
25  * @return ラベルが同一の場合は0、異なる場合は0以外
26  *
27  * @param *a ラベルa
28  * @param *b ラベルb
29  */
30 int compare_adr(const void *a, const void *b);
31
32 /**
33  * @brief ラベル数
34  */
35 static int labelcnt = 0;
36
37 /**
38  * @brief ラベル表
39  */
40 static LABELTAB *labels[LABELTABSIZE];
41
42 /**
43  * @brief ラベルのエラー
44  */
45 static CERR cerr_label[] = {
46     { 101, "label already defined" },
47     { 102, "label table is full" },
48     { 103, "label not found" },
49 };
50
51 HKEY *label_hashkey(const char *value) {
52     HKEY *key;
53
54     key = malloc_chk(sizeof(HKEY), "label_hashkey");
55     key->type = CHARS;
56     key->val.s = strdup_chk(value, "label_hashkey.value");
57     return key;
58 }
59
60 unsigned labelhash(const char *prog, const char *label)
61 {
62     HKEY *keys[2];
63     int i = 0, j;
64     unsigned h;
65
66     if(*prog != '\0') {
67         keys[i++] = label_hashkey(prog);
68     }
69     keys[i] = label_hashkey(label);
70     h = hash(i+1, keys, LABELTABSIZE);
71     for(j = 0; j < i + 1; j++) {
72         FREE(keys[j]->val.s);
73         FREE(keys[j]);
74     }
75     return h;
76 }
77
78 int compare_adr(const void *a, const void *b)
79 {
80     return (**(LABELARRAY **)a).adr - (**(LABELARRAY **)b).adr;
81 }
82
83 /* assemble.hで定義された関数群 */
84 void addcerrlist_label()
85 {
86     addcerrlist(ARRAYSIZE(cerr_label), cerr_label);
87 }
88
89 WORD getlabel(const char *prog, const char *label)
90 {
91     assert(prog != NULL && label != NULL);
92     LABELTAB *p;
93     LABELARRAY *l;
94
95     for(p = labels[labelhash(prog, label)]; p != NULL; p = p->next) {
96         l = p->label;
97         if((*prog == '\0' || (strcmp(prog, l->prog) == 0)) &&
98            strcmp(label, l->label) == 0)
99         {
100             return l->adr;
101         }
102     }
103     return 0xFFFF;
104 }
105
106 bool addlabel(const char *prog, const char *label, WORD adr)
107 {
108     assert(label != NULL);
109     LABELTAB *p;
110     LABELARRAY *l;
111     unsigned h;
112
113     /* 登録されたラベルを検索。すでに登録されている場合はエラー発生 */
114     if(getlabel(prog, label) != 0xFFFF) {
115         setcerr(101, label);    /* label already defined */
116         return false;
117     }
118     /* メモリを確保 */
119     p = malloc_chk(sizeof(LABELTAB), "labels.next");
120     l = p->label = malloc_chk(sizeof(LABELARRAY), "labels.label");
121     /* プログラム名を設定 */
122     l->prog = strdup_chk(prog, "label.prog");
123     /* ラベルを設定 */
124     l->label = strdup_chk(label, "label.label");
125     /* アドレスを設定 */
126     l->adr = adr;
127     /* ラベル数を設定 */
128     labelcnt++;
129     /* ハッシュ表へ追加 */
130     p->next = labels[h = labelhash(prog, label)];
131     labels[h] = p;
132     return true;
133 }
134
135 void printlabel()
136 {
137     int i, s = 0;
138     LABELTAB *p;
139     LABELARRAY **l;
140
141     l = calloc_chk(labelcnt, sizeof(LABELARRAY **), "labels");
142     for(i = 0; i < LABELTABSIZE; i++) {
143         for(p = labels[i]; p != NULL; p = p->next) {
144             assert(p->label != NULL);
145             l[s++] = p->label;
146         }
147     }
148     qsort(l, s, sizeof(*l), compare_adr);
149     for(i = 0; i < s; i++) {
150         if(*(l[i]->prog) != '\0') {
151             fprintf(stdout, "%s.", l[i]->prog);
152         }
153         fprintf(stdout, "%s ---> #%04X\n", l[i]->label, l[i]->adr);
154     }
155     FREE(l);
156 }
157
158 void freelabel()
159 {
160     int i;
161     LABELTAB *p, *q;
162
163     for(i = 0; i < LABELTABSIZE; i++) {
164         for(p = labels[i]; p != NULL; p = q) {
165             q = p->next;
166             FREE(p->label->prog);
167             FREE(p->label->label);
168             FREE(p->label);
169             FREE(p);
170         }
171         labels[i] = NULL;
172     }
173 }