データ構造の名前を変更
[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 unsigned labelhash(const char *prog, const char *label)
18 {
19     HKEY *keys[2];
20     int i = 0;
21
22     if(prog != NULL) {
23         keys[i] = malloc_chk(sizeof(HKEY), "labelhash.key[]");
24         keys[i]->type = CHARS;
25         keys[i]->val.s = strdup_chk(prog, "labelhash.key[].val");
26     }
27     keys[i] = malloc_chk(sizeof(HKEY), "labelhash.key[]");
28     keys[i]->type = CHARS;
29     keys[i]->val.s = strdup_chk(label, "labelhash.key[].val");
30     /* ハッシュ値を返す */
31     return hash(i+1, keys, LABELTABSIZE);
32 }
33
34 /**
35  * プログラム名とラベルに対応するアドレスをラベル表から検索する
36  */
37 WORD getlabel(const char *prog, const char *label)
38 {
39     assert(label != NULL);
40     LABELTAB *np;
41
42     for(np = labels[labelhash(prog, label)]; np != NULL; np = np->next) {
43         if((prog == NULL || (np->prog != NULL && strcmp(prog, np->prog) == 0)) &&
44            strcmp(label, np->label) == 0)
45         {
46             return np->adr;
47         }
48     }
49     return 0xFFFF;
50 }
51
52 /**
53  * プログラム名、ラベル、アドレスをラベル表に追加する
54  */
55 bool addlabel(const char *prog, const char *label, WORD adr)
56 {
57     assert(label != NULL);
58     LABELTAB *np;
59     unsigned hashval;
60
61     /* 登録されたラベルを検索。すでに登録されている場合はエラー発生 */
62     if(getlabel(prog, label) != 0xFFFF) {
63         setcerr(101, label);    /* label already defined */
64         return false;
65     }
66     /* メモリを確保 */
67     np = malloc_chk(sizeof(LABELTAB), "labels.next");
68     /* プログラム名を設定 */
69     if(prog == NULL) {
70         np->prog = NULL;
71     } else {
72         np->prog = strdup_chk(prog, "labels.prog");
73     }
74     /* ラベルを設定 */
75     np->label = strdup_chk(label, "labels.label");
76     /* アドレスを設定 */
77     np->adr = adr;
78     /* ラベル数を設定 */
79     labelcnt++;
80     /* ハッシュ表へ追加 */
81     hashval = labelhash(prog, label);
82     np->next = labels[hashval];
83     labels[hashval] = np;
84     return true;
85 }
86
87 /**
88  * ラベルを比較した結果を返す
89  */
90 int compare_adr(const void *a, const void *b)
91 {
92     return (**(LABELARRAY **)a).adr - (**(LABELARRAY **)b).adr;
93 }
94
95 /**
96  * ラベル表を表示する
97  */
98 void printlabel()
99 {
100     int i, asize = 0;
101     LABELTAB *np;
102     LABELARRAY *ar[labelcnt];
103
104     for(i = 0; i < LABELTABSIZE; i++) {
105         for(np = labels[i]; np != NULL; np = np->next) {
106             assert(np->label != NULL);
107             ar[asize] = malloc_chk(sizeof(LABELARRAY), "ar[]");
108             if(np->prog == NULL) {
109                 ar[asize]->prog = NULL;
110             } else {
111                 ar[asize]->prog = strdup_chk(np->prog, "ar[].prog");
112             }
113             ar[asize]->label = strdup_chk(np->label, "ar[].label");
114             ar[asize++]->adr = np->adr;
115         }
116     }
117     qsort(ar, asize, sizeof(*ar), compare_adr);
118     for(i = 0; i < asize; i++) {
119         if(ar[i]->prog != NULL) {
120             fprintf(stdout, "%s.", ar[i]->prog);
121         }
122         fprintf(stdout, "%s ---> #%04X\n", ar[i]->label, ar[i]->adr);
123     }
124 }
125
126 /**
127  * ラベル表を解放する
128  */
129 void freelabel()
130 {
131     int i;
132     LABELTAB *np, *nq;
133
134     for(i = 0; i < LABELTABSIZE; i++) {
135         for(np = labels[i]; np != NULL; np = nq) {
136             nq = np->next;
137             if(np->prog != NULL) {
138                 free_chk(np->prog, "np.prog");
139             }
140             free_chk(np->label, "np.label");
141             free_chk(np, "np");
142         }
143     }
144 }