c705ad11600aa3ffb81bb73825f757a14ad92dc8
[YACASL2.git] / src / label.c
1 #include "casl2.h"
2 #include "assemble.h"
3
4 int labelcnt = 0;                /* ラベル数 */
5 LABELTAB *labels[LABELTABSIZE];  /* ラベル表 */
6
7 /* プログラム名とラベルに対応するハッシュ値を返す */
8 unsigned labelhash(const char *prog, const char *label)
9 {
10     HKEY *keys[2];
11     int i = 0;
12     if(prog != NULL) {
13         keys[i] = malloc(sizeof(HKEY));
14         keys[i]->type = CHARS;
15         keys[i++]->val.s = strdup(prog);
16     }
17     keys[i] = malloc(sizeof(HKEY));
18     keys[i]->type = CHARS;
19     keys[i]->val.s = strdup(label);
20     /* ハッシュ値を返す */
21     return hash(i+1, keys, LABELTABSIZE);
22 }
23
24 /* ラベル表からアドレスを検索する */
25 WORD getlabel(const char *prog, const char *label)
26 {
27     assert(label != NULL);
28     LABELTAB *np;
29     for(np = labels[labelhash(prog, label)]; np != NULL; np = np->next) {
30         if((prog == NULL || (np->prog != NULL && strcmp(prog, np->prog) == 0)) &&
31            strcmp(label, np->label) == 0)
32         {
33             return np->adr;
34         }
35     }
36     return 0xFFFF;
37 }
38
39 /* プログラム名、ラベル、アドレスをラベル表に追加する */
40 bool addlabel(const char *prog, const char *label, WORD adr)
41 {
42     assert(label != NULL);
43     LABELTAB *np;
44     unsigned hashval;
45
46     /* 登録されたラベルを検索。すでに登録されている場合はエラー発生 */
47     if(getlabel(prog, label) != 0xFFFF) {
48         setcerr(101, label);    /* label already defined */
49         return false;
50     }
51     /* メモリを確保 */
52     if((np = malloc(sizeof(LABELTAB))) == NULL) {
53         goto cerr102;
54     }
55     /* プログラム名を設定 */
56     if(prog == NULL) {
57         np->prog = NULL;
58     } else {
59         if((np->prog = strdup(prog)) == NULL) {
60             goto cerr102;
61         }
62     }
63     /* ラベルを設定 */
64     if((np->label = strdup(label)) == NULL) {
65         goto cerr102;
66     }
67     /* アドレスを設定 */
68     np->adr = adr;
69     /* ラベル数を設定 */
70     labelcnt++;
71     /* ハッシュ表へ追加 */
72     hashval = labelhash(prog, label);
73     np->next = labels[hashval];
74     labels[hashval] = np;
75     return true;
76 cerr102:
77     setcerr(102, NULL);    /* label table is full */
78     return false;
79 }
80
81 int compare_adr(const void *a, const void *b)
82 {
83     return (**(LABELARRAY **)a).adr - (**(LABELARRAY **)b).adr;
84 }
85
86 /* ラベル表を表示する */
87 void printlabel()
88 {
89     int i, asize = 0;
90     LABELTAB *np;
91     LABELARRAY *ar[labelcnt];
92
93     for(i = 0; i < LABELTABSIZE; i++) {
94         for(np = labels[i]; np != NULL; np = np->next) {
95             assert(np->label != NULL);
96             ar[asize] = malloc(sizeof(LABELARRAY));
97             ar[asize]->prog = (np->prog == NULL ? NULL : strdup(np->prog));
98             ar[asize]->label = strdup(np->label);
99             ar[asize++]->adr = np->adr;
100         }
101     }
102     qsort(ar, asize, sizeof(*ar), compare_adr);
103     for(i = 0; i < asize; i++) {
104         if(ar[i]->prog != NULL) {
105             fprintf(stdout, "%s.", ar[i]->prog);
106         }
107         fprintf(stdout, "%s ---> #%04X\n", ar[i]->label, ar[i]->adr);
108     }
109 }
110
111 /* ラベル表を解放する */
112 void freelabel()
113 {
114     int i;
115     LABELTAB *np, *nq;
116     for(i = 0; i < LABELTABSIZE; i++) {
117         for(np = labels[i]; np != NULL; np = nq) {
118             nq = np->next;
119             if(np->prog != NULL) {
120                 free(np->prog);
121             }
122             free(np->label);
123             free(np);
124         }
125     }
126 }