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