Passo intermediario, ainda falta um longo caminho
[pspdecompiler.git] / nids.c
blobdd67bc6ef734833a61c4eed6e033e43deffe2c9b
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <expat.h>
7 #include "nids.h"
8 #include "hash.h"
9 #include "alloc.h"
10 #include "utils.h"
12 struct nidstable {
13 hashpool pool;
14 hashtable libs;
15 fixedpool infopool;
16 char *buffer;
19 enum XMLSCOPE {
20 XMLS_LIBRARY,
21 XMLS_FUNCTION,
22 XMLS_VARIABLE
25 enum XMLELEMENT {
26 XMLE_DEFAULT,
27 XMLE_NID,
28 XMLE_NAME,
29 XMLE_NUMARGS
32 struct xml_data {
33 enum XMLSCOPE scope;
34 enum XMLELEMENT last;
36 size_t buffer_pos;
37 struct nidstable *result;
38 hashtable curlib;
39 const char *libname;
41 struct nidinfo currnid;
42 int error;
45 void nids_free (struct nidstable *nids)
47 nids->libs = NULL;
48 if (nids->buffer)
49 free (nids->buffer);
50 nids->buffer = NULL;
51 if (nids->pool)
52 hashpool_destroy (nids->pool);
53 nids->pool = NULL;
54 if (nids->infopool)
55 fixedpool_destroy (nids->infopool, NULL, NULL);
56 nids->infopool = NULL;
57 free (nids);
61 static
62 void start_hndl (void *data, const char *el, const char **attr)
64 struct xml_data *d = (struct xml_data *) data;
66 d->last = XMLE_DEFAULT;
68 if (strcmp (el, "LIBRARY") == 0) {
69 d->scope = XMLS_LIBRARY;
70 } else if (strcmp (el, "NAME") == 0) {
71 d->last = XMLE_NAME;
72 } else if (strcmp (el, "FUNCTION") == 0) {
73 d->currnid.isvariable = 0;
74 d->scope = XMLS_FUNCTION;
75 } else if (strcmp (el, "VARIABLE") == 0) {
76 d->currnid.isvariable = 1;
77 d->scope = XMLS_VARIABLE;
78 } else if (strcmp (el, "NID") == 0) {
79 d->last = XMLE_NID;
80 } else if (strcmp (el, "NUMARGS") == 0) {
81 d->last = XMLE_NUMARGS;
85 static
86 void end_hndl (void *data, const char *el)
88 struct xml_data *d = (struct xml_data *) data;
90 d->last = XMLE_DEFAULT;
92 if (strcmp (el, "LIBRARY") == 0) {
93 d->curlib = NULL;
94 d->libname = NULL;
95 } else if (strcmp (el, "FUNCTION") == 0 || strcmp (el, "VARIABLE") == 0) {
96 d->scope = XMLS_LIBRARY;
97 if (d->currnid.name && d->currnid.nid && d->curlib) {
98 struct nidinfo *info = hashtable_searchhash (d->curlib, NULL, NULL, d->currnid.nid);
99 if (info) {
100 if (strcmp (info->name, d->currnid.name)) {
101 error (__FILE__ ": NID `0x%08X' repeated in library `%s'", d->currnid.nid, d->libname);
102 d->error = 1;
104 } else {
105 info = fixedpool_alloc (d->result->infopool);
106 memcpy (info, &d->currnid, sizeof (struct nidinfo));
107 hashtable_inserthash (d->curlib, NULL, info, d->currnid.nid);
109 } else {
110 error (__FILE__ ": missing function or variable definition");
111 d->error = 1;
113 d->currnid.name = NULL;
114 d->currnid.nid = 0;
115 d->currnid.numargs = -1;
119 static
120 const char *dup_string (struct xml_data *d, const char *txt, size_t len)
122 char *result;
124 result = &d->result->buffer[d->buffer_pos];
125 memcpy (result, txt, len);
126 result[len] = '\0';
127 d->buffer_pos += len + 1;
129 return (const char *) result;
132 static
133 void char_hndl (void *data, const char *txt, int txtlen)
135 struct xml_data *d = (struct xml_data *) data;
137 switch (d->scope) {
138 case XMLS_FUNCTION:
139 case XMLS_VARIABLE:
140 if (d->last == XMLE_NAME) {
141 if (d->currnid.name) {
142 error (__FILE__ ": repeated name in function/variable");
143 d->error = 1;
144 } else {
145 d->currnid.name = dup_string (d, txt, txtlen);
147 } else if (d->last == XMLE_NID || d->last == XMLE_NUMARGS) {
148 char buffer[256];
150 if (txtlen > sizeof (buffer) - 1)
151 txtlen = sizeof (buffer) - 1;
152 memcpy (buffer, txt, txtlen);
153 buffer[txtlen] = '\0';
155 if (d->last == XMLE_NID) {
156 if (d->currnid.nid) {
157 error (__FILE__ ": nid repeated in function/variable");
158 d->error = 1;
159 } else {
160 d->currnid.nid = 0;
161 sscanf (buffer, "0x%X", &d->currnid.nid);
163 } else {
164 d->currnid.numargs = -1;
165 sscanf (buffer, "%d", &d->currnid.numargs);
168 break;
169 case XMLS_LIBRARY:
170 if (d->last == XMLE_NAME) {
171 d->libname = dup_string (d, txt, txtlen);
172 if (d->curlib) {
173 error (__FILE__ ": current lib is not null");
174 d->error = 1;
175 } else {
176 d->curlib = hashtable_search (d->result->libs, (void *) d->libname, NULL);
177 if (!d->curlib) {
178 d->curlib = hashtable_alloc (d->result->pool, 128, NULL, &hashtable_pointer_compare);
179 hashtable_insert (d->result->libs, (void *) d->libname, d->curlib);
183 break;
187 struct nidstable *nids_load (const char *xmlpath)
189 XML_Parser p;
190 struct xml_data data;
191 size_t size;
192 void *buf;
194 buf = read_file (xmlpath, &size);
195 if (!buf) {
196 return NULL;
199 p = XML_ParserCreate (NULL);
200 if (!p) {
201 error (__FILE__ ": can't create XML parser");
202 free (buf);
203 return 0;
206 data.error = 0;
207 data.curlib = NULL;
208 data.libname = NULL;
209 data.currnid.name = NULL;
210 data.currnid.nid = 0;
211 data.currnid.numargs = 0;
212 data.scope = XMLS_LIBRARY;
213 data.last = XMLE_DEFAULT;
215 data.result =
216 (struct nidstable *) xmalloc (sizeof (struct nidstable));
217 data.result->pool =
218 hashpool_create (256, 8192);
219 data.result->libs =
220 hashtable_alloc (data.result->pool, 32, &hashtable_hash_string,
221 &hashtable_string_compare);
222 data.result->infopool = fixedpool_create (sizeof (struct nidinfo), 8192, 0);
224 data.buffer_pos = 0;
225 data.result->buffer = buf;
226 buf = xmalloc (size);
228 memcpy (buf, data.result->buffer, size);
230 XML_SetUserData (p, (void *) &data);
231 XML_SetElementHandler (p, &start_hndl, &end_hndl);
232 XML_SetCharacterDataHandler (p, &char_hndl);
234 if (!XML_Parse (p, buf, size, 1)) {
235 error (__FILE__ ": parse error at line %d:\n %s\n", XML_GetCurrentLineNumber (p),
236 XML_ErrorString (XML_GetErrorCode (p)));
237 data.error = 1;
240 XML_ParserFree (p);
241 free (buf);
243 if (data.error) {
244 nids_free (data.result);
245 return NULL;
248 return data.result;
251 static
252 void print_level2 (void *key, void *value, unsigned int hash, void *arg)
254 struct nidinfo *info = value;
255 report (" NID: 0x%08X ", info->nid);
256 if (info->isvariable) report ("(Variable)");
257 else report ("Num args: %d", info->numargs);
258 report (" Name: %s\n", info->name);
261 static
262 void print_level1 (void *key, void *value, unsigned int hash, void *arg)
264 hashtable lib = (hashtable) value;
265 report (" %s:\n", (char *) key);
266 hashtable_traverse (lib, &print_level2, NULL);
267 report ("\n");
270 void nids_print (struct nidstable *nids)
272 report ("Libraries:\n");
273 hashtable_traverse (nids->libs, &print_level1, NULL);
277 struct nidinfo *nids_find (struct nidstable *nids, const char *library, unsigned int nid)
279 hashtable lib;
281 lib = hashtable_search (nids->libs, (void *) library, NULL);
282 if (lib) return hashtable_searchhash (lib, NULL, NULL, nid);
283 return NULL;
287 #ifdef TEST_NIDS
288 int main (int argc, char **argv)
290 struct nidstable *nids = NULL;
292 nids = nids_load (argv[1]);
293 if (nids) {
294 nids_print (nids);
295 nids_free (nids);
297 return 0;
300 #endif /* TEST_NIDS */