Hlide problem solved (i believe)
[pspdecompiler.git] / nids.c
blobdc35df46f8a01ee652674bbbe624469a3eb00bac
1 /**
2 * Author: Humberto Naves (hsnaves@gmail.com)
3 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <expat.h>
10 #include "nids.h"
11 #include "hash.h"
12 #include "alloc.h"
13 #include "utils.h"
15 struct nidstable {
16 hashpool pool;
17 hashtable libs;
18 fixedpool infopool;
19 char *buffer;
22 enum XMLSCOPE {
23 XMLS_LIBRARY,
24 XMLS_FUNCTION,
25 XMLS_VARIABLE
28 enum XMLELEMENT {
29 XMLE_DEFAULT,
30 XMLE_NID,
31 XMLE_NAME,
32 XMLE_NUMARGS
35 struct xml_data {
36 enum XMLSCOPE scope;
37 enum XMLELEMENT last;
39 size_t buffer_pos;
40 struct nidstable *result;
41 hashtable curlib;
42 const char *libname;
44 struct nidinfo currnid;
45 int error;
48 void nids_free (struct nidstable *nids)
50 nids->libs = NULL;
51 if (nids->buffer)
52 free (nids->buffer);
53 nids->buffer = NULL;
54 if (nids->pool)
55 hashpool_destroy (nids->pool);
56 nids->pool = NULL;
57 if (nids->infopool)
58 fixedpool_destroy (nids->infopool, NULL, NULL);
59 nids->infopool = NULL;
60 free (nids);
64 static
65 void start_hndl (void *data, const char *el, const char **attr)
67 struct xml_data *d = (struct xml_data *) data;
69 d->last = XMLE_DEFAULT;
71 if (strcmp (el, "LIBRARY") == 0) {
72 d->scope = XMLS_LIBRARY;
73 } else if (strcmp (el, "NAME") == 0) {
74 d->last = XMLE_NAME;
75 } else if (strcmp (el, "FUNCTION") == 0) {
76 d->currnid.isvariable = 0;
77 d->scope = XMLS_FUNCTION;
78 } else if (strcmp (el, "VARIABLE") == 0) {
79 d->currnid.isvariable = 1;
80 d->scope = XMLS_VARIABLE;
81 } else if (strcmp (el, "NID") == 0) {
82 d->last = XMLE_NID;
83 } else if (strcmp (el, "NUMARGS") == 0) {
84 d->last = XMLE_NUMARGS;
88 static
89 void end_hndl (void *data, const char *el)
91 struct xml_data *d = (struct xml_data *) data;
93 d->last = XMLE_DEFAULT;
95 if (strcmp (el, "LIBRARY") == 0) {
96 d->curlib = NULL;
97 d->libname = NULL;
98 } else if (strcmp (el, "FUNCTION") == 0 || strcmp (el, "VARIABLE") == 0) {
99 d->scope = XMLS_LIBRARY;
100 if (d->currnid.name && d->currnid.nid && d->curlib) {
101 struct nidinfo *info = hashtable_searchhash (d->curlib, NULL, NULL, d->currnid.nid);
102 if (info) {
103 if (strcmp (info->name, d->currnid.name)) {
104 error (__FILE__ ": NID `0x%08X' repeated in library `%s'", d->currnid.nid, d->libname);
105 d->error = 1;
107 } else {
108 info = fixedpool_alloc (d->result->infopool);
109 memcpy (info, &d->currnid, sizeof (struct nidinfo));
110 hashtable_inserthash (d->curlib, NULL, info, d->currnid.nid);
112 } else {
113 error (__FILE__ ": missing function or variable definition");
114 d->error = 1;
116 d->currnid.name = NULL;
117 d->currnid.nid = 0;
118 d->currnid.numargs = -1;
122 static
123 const char *dup_string (struct xml_data *d, const char *txt, size_t len)
125 char *result;
127 result = &d->result->buffer[d->buffer_pos];
128 memcpy (result, txt, len);
129 result[len] = '\0';
130 d->buffer_pos += len + 1;
132 return (const char *) result;
135 static
136 void char_hndl (void *data, const char *txt, int txtlen)
138 struct xml_data *d = (struct xml_data *) data;
140 switch (d->scope) {
141 case XMLS_FUNCTION:
142 case XMLS_VARIABLE:
143 if (d->last == XMLE_NAME) {
144 if (d->currnid.name) {
145 error (__FILE__ ": repeated name in function/variable");
146 d->error = 1;
147 } else {
148 d->currnid.name = dup_string (d, txt, txtlen);
150 } else if (d->last == XMLE_NID || d->last == XMLE_NUMARGS) {
151 char buffer[256];
153 if (txtlen > sizeof (buffer) - 1)
154 txtlen = sizeof (buffer) - 1;
155 memcpy (buffer, txt, txtlen);
156 buffer[txtlen] = '\0';
158 if (d->last == XMLE_NID) {
159 if (d->currnid.nid) {
160 error (__FILE__ ": nid repeated in function/variable");
161 d->error = 1;
162 } else {
163 d->currnid.nid = 0;
164 sscanf (buffer, "0x%X", &d->currnid.nid);
166 } else {
167 d->currnid.numargs = -1;
168 sscanf (buffer, "%d", &d->currnid.numargs);
171 break;
172 case XMLS_LIBRARY:
173 if (d->last == XMLE_NAME) {
174 d->libname = dup_string (d, txt, txtlen);
175 if (d->curlib) {
176 error (__FILE__ ": current lib is not null");
177 d->error = 1;
178 } else {
179 d->curlib = hashtable_search (d->result->libs, (void *) d->libname, NULL);
180 if (!d->curlib) {
181 d->curlib = hashtable_alloc (d->result->pool, 128, NULL, &hashtable_pointer_compare);
182 hashtable_insert (d->result->libs, (void *) d->libname, d->curlib);
186 break;
190 struct nidstable *nids_load (const char *xmlpath)
192 XML_Parser p;
193 struct xml_data data;
194 size_t size;
195 void *buf;
197 buf = read_file (xmlpath, &size);
198 if (!buf) {
199 return NULL;
202 p = XML_ParserCreate (NULL);
203 if (!p) {
204 error (__FILE__ ": can't create XML parser");
205 free (buf);
206 return 0;
209 data.error = 0;
210 data.curlib = NULL;
211 data.libname = NULL;
212 data.currnid.name = NULL;
213 data.currnid.nid = 0;
214 data.currnid.numargs = 0;
215 data.scope = XMLS_LIBRARY;
216 data.last = XMLE_DEFAULT;
218 data.result =
219 (struct nidstable *) xmalloc (sizeof (struct nidstable));
220 data.result->pool =
221 hashpool_create (256, 8192);
222 data.result->libs =
223 hashtable_alloc (data.result->pool, 32, &hashtable_hash_string,
224 &hashtable_string_compare);
225 data.result->infopool = fixedpool_create (sizeof (struct nidinfo), 8192, 0);
227 data.buffer_pos = 0;
228 data.result->buffer = buf;
229 buf = xmalloc (size);
231 memcpy (buf, data.result->buffer, size);
233 XML_SetUserData (p, (void *) &data);
234 XML_SetElementHandler (p, &start_hndl, &end_hndl);
235 XML_SetCharacterDataHandler (p, &char_hndl);
237 if (!XML_Parse (p, buf, size, 1)) {
238 error (__FILE__ ": parse error at line %d:\n %s\n", XML_GetCurrentLineNumber (p),
239 XML_ErrorString (XML_GetErrorCode (p)));
240 data.error = 1;
243 XML_ParserFree (p);
244 free (buf);
246 if (data.error) {
247 nids_free (data.result);
248 return NULL;
251 return data.result;
254 static
255 void print_level2 (void *key, void *value, unsigned int hash, void *arg)
257 struct nidinfo *info = value;
258 report (" NID: 0x%08X ", info->nid);
259 if (info->isvariable) report ("(Variable)");
260 else report ("Num args: %d", info->numargs);
261 report (" Name: %s\n", info->name);
264 static
265 void print_level1 (void *key, void *value, unsigned int hash, void *arg)
267 hashtable lib = (hashtable) value;
268 report (" %s:\n", (char *) key);
269 hashtable_traverse (lib, &print_level2, NULL);
270 report ("\n");
273 void nids_print (struct nidstable *nids)
275 report ("Libraries:\n");
276 hashtable_traverse (nids->libs, &print_level1, NULL);
280 struct nidinfo *nids_find (struct nidstable *nids, const char *library, unsigned int nid)
282 hashtable lib;
284 lib = hashtable_search (nids->libs, (void *) library, NULL);
285 if (lib) return hashtable_searchhash (lib, NULL, NULL, nid);
286 return NULL;
290 #ifdef TEST_NIDS
291 int main (int argc, char **argv)
293 struct nidstable *nids = NULL;
295 nids = nids_load (argv[1]);
296 if (nids) {
297 nids_print (nids);
298 nids_free (nids);
300 return 0;
303 #endif /* TEST_NIDS */