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