ソースの修正
[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[labelcnt];
126
127     for(i = 0; i < LABELTABSIZE; i++) {
128         for(p = labels[i]; p != NULL; p = p->next) {
129             assert(p->label != NULL);
130             l[s] = malloc_chk(sizeof(LABELARRAY), "l[]");
131             if(p->prog == NULL) {
132                 l[s]->prog = NULL;
133             } else {
134                 l[s]->prog = strdup_chk(p->prog, "l[].prog");
135             }
136             l[s]->label = strdup_chk(p->label, "l[].label");
137             l[s++]->adr = p->adr;
138         }
139     }
140     qsort(l, s, sizeof(*l), compare_adr);
141     for(i = 0; i < s; i++) {
142         if(l[i]->prog != NULL) {
143             fprintf(stdout, "%s.", l[i]->prog);
144         }
145         fprintf(stdout, "%s ---> #%04X\n", l[i]->label, l[i]->adr);
146     }
147 }
148
149 /**
150  * ラベル表を解放する
151  */
152 void freelabel()
153 {
154     int i;
155     LABELTAB *p, *q;
156
157     for(i = 0; i < LABELTABSIZE; i++) {
158         for(p = labels[i]; p != NULL; p = q) {
159             q = p->next;
160             FREE(p->prog);
161             FREE(p->label);
162             FREE(p);
163         }
164     }
165 }