Makefileの修正
[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 != '\0') {
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(prog != NULL && label != NULL);
63     LABELTAB *p;
64
65     for(p = labels[labelhash(prog, label)]; p != NULL; p = p->next) {
66         if((*prog == '\0' || (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     p->prog = strdup_chk(prog, "labels.prog");
93     /* ラベルを設定 */
94     p->label = strdup_chk(label, "labels.label");
95     /* アドレスを設定 */
96     p->adr = adr;
97     /* ラベル数を設定 */
98     labelcnt++;
99     /* ハッシュ表へ追加 */
100     hashval = labelhash(prog, label);
101     p->next = labels[hashval];
102     labels[hashval] = p;
103     return true;
104 }
105
106 /**
107  * ラベルを比較した結果を返す
108  */
109 int compare_adr(const void *a, const void *b)
110 {
111     return (**(LABELARRAY **)a).adr - (**(LABELARRAY **)b).adr;
112 }
113
114 /**
115  * ラベル表を表示する
116  */
117 void printlabel()
118 {
119     int i, s = 0;
120     LABELTAB *p;
121     LABELARRAY **l;
122
123     l = calloc_chk(labelcnt, sizeof(LABELARRAY **), "labels");
124     for(i = 0; i < LABELTABSIZE; i++) {
125         for(p = labels[i]; p != NULL; p = p->next) {
126             assert(p->label != NULL);
127             l[s] = malloc_chk(sizeof(LABELARRAY), "lables");
128             l[s]->prog = strdup_chk(p->prog, "labels.prog");
129             l[s]->label = strdup_chk(p->label, "labels.label");
130             l[s++]->adr = p->adr;
131         }
132     }
133     qsort(l, s, sizeof(*l), compare_adr);
134     for(i = 0; i < s; i++) {
135         if(*(l[i]->prog) != '\0') {
136             fprintf(stdout, "%s.", l[i]->prog);
137         }
138         fprintf(stdout, "%s ---> #%04X\n", l[i]->label, l[i]->adr);
139     }
140     FREE(l);
141 }
142
143 /**
144  * ラベル表を解放する
145  */
146 void freelabel()
147 {
148     int i;
149     LABELTAB *p, *q;
150
151     for(i = 0; i < LABELTABSIZE; i++) {
152         for(p = labels[i]; p != NULL; p = q) {
153             q = p->next;
154             FREE(p->prog);
155             FREE(p->label);
156             FREE(p);
157         }
158     }
159 }