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