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