fix double deletion bug in symtab_remove()
[xorcyst.git] / unit.c
blob4a5db39ae7b59cc9176874b1105163cc629f962d
1 /*
2 * $Id: unit.c,v 1.4 2007/07/22 13:33:26 khansen Exp $
3 * $Log: unit.c,v $
4 * Revision 1.4 2007/07/22 13:33:26 khansen
5 * convert tabs to whitespaces
7 * Revision 1.3 2004/12/18 17:00:35 kenth
8 * improved error reporting slightly
10 * Revision 1.2 2004/12/16 13:20:07 kenth
11 * xorcyst 1.3.5
13 * Revision 1.1 2004/06/30 07:56:00 kenth
14 * Initial revision
18 /**
19 * (C) 2004 Kent Hansen
21 * The XORcyst is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
26 * The XORcyst is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with The XORcyst; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include "unit.h"
39 #include "objdef.h"
41 #define SAFE_FREE(m) if ((m) != NULL) { free(m); m = NULL; }
43 /*---------------------------------------------------------------------------*/
45 /* Reads a byte */
46 #define get_1(f) (unsigned char)fgetc(fp)
47 /* Reads a short (big-endian) */
48 static unsigned short get_2(FILE *fp)
50 unsigned short result;
51 result = get_1(fp) << 8; /* High byte */
52 result |= get_1(fp); /* Low byte */
53 return result;
55 /* Reads a 24-bit integer (big-endian) */
56 static unsigned int get_3(FILE *fp)
58 unsigned int result;
59 result = get_2(fp) << 8; /* High 16 bits */
60 result |= get_1(fp); /* Low byte */
61 return result;
63 /* Reads an int (big-endian) */
64 static unsigned int get_4(FILE *fp)
66 unsigned int result;
67 /* Assumes little-endian machine!! */
68 result = get_2(fp) << 16; /* High 16 bits */
69 result |= get_2(fp); /* Low 16 bits */
70 return result;
72 /* Reads a string prepended by 8-bit length */
73 static char *get_str_8(FILE *fp)
75 char *s;
76 int len = get_1(fp) + 1;
77 s = (char *)malloc(len + 1);
78 if (s != NULL) {
79 fread(s, 1, len, fp);
80 s[len] = '\0';
82 return s;
84 /* Reads a string prepended by 16-bit length */
85 static char *get_str_16(FILE *fp)
87 char *s;
88 int len = get_2(fp) + 1;
89 s = (char *)malloc(len + 1);
90 if (s != NULL) {
91 fread(s, 1, len, fp);
92 s[len] = '\0';
94 return s;
96 #define get_bytes_8(f) (unsigned char *)get_str_8(f)
97 #define get_bytes_16(f) (unsigned char *)get_str_16(f)
99 /*--------------------------------------------------------------------------*/
102 * Reads a constant from file.
103 * @param fp File handle
104 * @param u Unit in which constant is loaded
105 * @param i Index of constant in unit's constant array
107 static void get_const(FILE *fp, xasm_unit *u, int i)
109 xasm_constant *cnst = &u->constants[i];
110 cnst->name = get_str_8(fp);
111 cnst->type = get_1(fp);
112 switch (cnst->type) {
113 case XASM_INT_8: cnst->integer = get_1(fp); cnst->type = XASM_INTEGER_CONSTANT; break;
114 case XASM_INT_16: cnst->integer = get_2(fp); cnst->type = XASM_INTEGER_CONSTANT; break;
115 case XASM_INT_24: cnst->integer = get_3(fp); cnst->type = XASM_INTEGER_CONSTANT; break;
116 case XASM_INT_32: cnst->integer = get_4(fp); cnst->type = XASM_INTEGER_CONSTANT; break;
117 case XASM_STR_8: cnst->string = get_str_8(fp); cnst->type = XASM_STRING_CONSTANT; break;
118 case XASM_STR_16: cnst->string = get_str_16(fp); cnst->type = XASM_STRING_CONSTANT; break;
120 default:
121 fprintf(stderr, "%s(0x%lx): get_const(): bad constant type (%.2X)\n", u->name, ftell(fp), cnst->type);
122 break;
124 cnst->unit = u;
128 * Reads constant array from file.
129 * @param fp File handle
130 * @param u Unit whose constants array will be populated
132 static void get_constants(FILE *fp, xasm_unit *u)
134 int i;
135 int count = get_2(fp);
136 if (count > 0) {
137 u->constants = (xasm_constant *)malloc(sizeof(xasm_constant) * count);
138 } else {
139 u->constants = NULL;
141 for (i=0; i<count; i++) {
142 get_const(fp, u, i);
144 u->const_count = count;
148 * Reads imported symbol from file.
149 * @param fp File handle
150 * @param u Unit
151 * @param i External index
153 static void get_ext(FILE *fp, xasm_unit *u, int i)
155 xasm_external *ext = &u->externals[i];
156 ext->unit = get_1(fp);
157 ext->name = get_str_8(fp);
158 ext->from = u;
162 * Reads imported symbol array from file.
163 * @param fp File handle
164 * @param u Unit whose externals array will be populated
166 static void get_externals(FILE *fp, xasm_unit *u)
168 int i;
169 int count;
170 count = get_2(fp);
171 if (count > 0) {
172 u->externals = (xasm_external *)malloc(sizeof(xasm_external) * count);
173 } else {
174 u->externals = NULL;
176 for (i=0; i<count; i++) {
177 get_ext(fp, u, i);
179 u->ext_count = count;
183 * Reads an expression from file.
184 * @param fp File handle
185 * @param dest Pointer to pointer where expression should be stored
186 * @param u Owner unit
188 static void get_expr_recursive(FILE *fp, xasm_expression **dest, xasm_unit *u)
190 unsigned char type;
191 xasm_expression *exp = (xasm_expression *)malloc( sizeof(xasm_expression) );
192 if (exp != NULL) {
193 type = get_1(fp);
194 switch (type) {
195 case XASM_INT_8: exp->integer = get_1(fp); exp->type = XASM_INTEGER_EXPRESSION; break;
196 case XASM_INT_16: exp->integer = get_2(fp); exp->type = XASM_INTEGER_EXPRESSION; break;
197 case XASM_INT_24: exp->integer = get_3(fp); exp->type = XASM_INTEGER_EXPRESSION; break;
198 case XASM_INT_32: exp->integer = get_4(fp); exp->type = XASM_INTEGER_EXPRESSION; break;
199 case XASM_STR_8: exp->string = get_str_8(fp); exp->type = XASM_STRING_EXPRESSION; break;
200 case XASM_STR_16: exp->string = get_str_16(fp); exp->type = XASM_STRING_EXPRESSION; break;
202 case XASM_LOCAL: exp->local_id = get_2(fp); exp->type = XASM_LOCAL_EXPRESSION; break;
203 case XASM_EXTRN: exp->extrn_id = get_2(fp); exp->type = XASM_EXTERNAL_EXPRESSION;break;
205 case XASM_PC: ; exp->type = XASM_PC_EXPRESSION; break;
207 case XASM_OP_PLUS:
208 case XASM_OP_MINUS:
209 case XASM_OP_MUL:
210 case XASM_OP_DIV:
211 case XASM_OP_MOD:
212 case XASM_OP_SHL:
213 case XASM_OP_SHR:
214 case XASM_OP_AND:
215 case XASM_OP_OR:
216 case XASM_OP_XOR:
217 case XASM_OP_EQ:
218 case XASM_OP_NE:
219 case XASM_OP_LT:
220 case XASM_OP_GT:
221 case XASM_OP_LE:
222 case XASM_OP_GE:
223 get_expr_recursive(fp, &exp->op_expr.lhs, u);
224 get_expr_recursive(fp, &exp->op_expr.rhs, u);
225 exp->op_expr.operator = type;
226 exp->type = XASM_OPERATOR_EXPRESSION;
227 break;
229 case XASM_OP_NOT:
230 case XASM_OP_NEG:
231 case XASM_OP_LO:
232 case XASM_OP_HI:
233 case XASM_OP_UMINUS:
234 case XASM_OP_BANK:
235 get_expr_recursive(fp, &exp->op_expr.lhs, u);
236 exp->op_expr.rhs = NULL;
237 exp->op_expr.operator = type;
238 exp->type = XASM_OPERATOR_EXPRESSION;
239 break;
241 default:
242 fprintf(stderr, "%s(0x%lx): get_expr(): invalid expression type (%.2X)\n", u->name, ftell(fp), type);
243 exp->integer = 0;
244 exp->type = XASM_INTEGER_EXPRESSION;
245 break;
248 exp->unit = u;
249 *dest = exp;
253 * Reads expressions from file.
254 * @param fp File handle
255 * @param u Unit whose expressions array to populate
257 static void get_expressions(FILE *fp, xasm_unit *u)
259 int i;
260 int count;
261 count = get_2(fp);
262 if (count > 0) {
263 u->expressions = (xasm_expression **)malloc(sizeof(xasm_expression *) * count);
264 } else {
265 u->expressions = NULL;
267 for (i=0; i<count; i++) {
268 get_expr_recursive(fp, &u->expressions[i], u);
270 u->expr_count = count;
274 * Reads a segment from file.
275 * @param fp File handle
276 * @param seg Where to store segment
278 static void get_segment(FILE *fp, xasm_segment *seg)
280 seg->size = get_3(fp);
281 if (seg->size > 0) {
282 seg->bytes = (unsigned char *)malloc(seg->size);
283 if (seg->bytes != NULL) {
284 fread(seg->bytes, 1, seg->size, fp);
286 } else {
287 seg->bytes = NULL;
291 /*--------------------------------------------------------------------------*/
294 * Reads a unit from file.
295 * @param filename Name of the unit
296 * @param u Pointer to struct to fill in
298 int xasm_unit_read(const char *filename, xasm_unit *u)
300 FILE *fp;
301 int count, i;
302 unsigned short magic;
303 unsigned char version;
305 u->name = filename;
306 fp = fopen(filename, "rb");
307 if (fp == NULL) {
308 u->const_count = 0;
309 u->ext_count = 0;
310 u->expr_count = 0;
311 u->dataseg.size = 0;
312 u->dataseg.bytes = NULL;
313 u->codeseg.size = 0;
314 u->codeseg.bytes = NULL;
315 return 0;
318 magic = get_2(fp);
319 if (magic != XASM_MAGIC) {
320 /* Error, bad magic number */
321 return 0;
324 version = get_1(fp);
325 if (version != XASM_OBJ_VERSION) {
326 /* Error, bad version */
327 return 0;
330 get_constants(fp, u);
332 /* Read # of units explicitly imported from */
333 count = get_1(fp);
334 /* Read unit names */
335 for (i=0; i<count; i++) {
336 get_str_8(fp);
339 get_externals(fp, u);
340 get_segment(fp, &u->dataseg);
341 get_segment(fp, &u->codeseg);
342 get_expressions(fp, u);
344 fclose(fp);
346 /* Success */
347 return 1;
350 /*--------------------------------------------------------------------------*/
353 * Finalizes a constant.
354 * @param c Constant to finalize
356 static void finalize_constant(xasm_constant *c)
358 if (c->type == XASM_STRING_CONSTANT) {
359 SAFE_FREE(c->string);
361 SAFE_FREE(c->name);
365 * Finalizes an external.
366 * @param e External to finalize
368 static void finalize_external(xasm_external *e)
370 SAFE_FREE(e->name);
374 * Finalizes an expression.
375 * @param e Expression to finalize
377 static void finalize_expression(xasm_expression *e)
379 if (e == NULL) { return; }
380 switch (e->type) {
381 case XASM_STRING_EXPRESSION:
382 SAFE_FREE(e->string);
383 break;
385 case XASM_OPERATOR_EXPRESSION:
386 finalize_expression(e->op_expr.lhs);
387 finalize_expression(e->op_expr.rhs);
388 break;
390 default:
391 /* Nada */
392 break;
394 SAFE_FREE(e);
398 * Finalizes a bytecode segment.
399 * @param s Segment to finalize
401 static void finalize_segment(xasm_segment *s)
403 SAFE_FREE(s->bytes);
406 /*--------------------------------------------------------------------------*/
409 * Finalizes a unit.
410 * @param u Unit to finalize
412 void xasm_unit_finalize(xasm_unit *u)
414 int i;
415 for (i=0; i<u->const_count; i++) {
416 finalize_constant(&u->constants[i]);
418 SAFE_FREE(u->constants);
420 for (i=0; i<u->ext_count; i++) {
421 finalize_external(&u->externals[i]);
423 SAFE_FREE(u->externals);
425 for (i=0; i<u->expr_count; i++) {
426 finalize_expression(u->expressions[i]);
428 SAFE_FREE(u->expressions);
430 finalize_segment(&u->dataseg);
431 finalize_segment(&u->codeseg);
435 * Gets string representation of an operator (OP_*, see objdef.h).
436 * @param op Operator
437 * @return String representation of operator
439 const char *xasm_operator_to_string(int op)
441 switch (op) {
442 case XASM_OP_PLUS: return "+";
443 case XASM_OP_MINUS: return "-";
444 case XASM_OP_MUL: return "*";
445 case XASM_OP_DIV: return "/";
446 case XASM_OP_MOD: return "%";
447 case XASM_OP_SHL: return "<<";
448 case XASM_OP_SHR: return ">>";
449 case XASM_OP_AND: return "&";
450 case XASM_OP_OR: return "|";
451 case XASM_OP_XOR: return "^";
452 case XASM_OP_EQ: return "==";
453 case XASM_OP_NE: return "!=";
454 case XASM_OP_LT: return "<";
455 case XASM_OP_GT: return ">";
456 case XASM_OP_LE: return "<=";
457 case XASM_OP_GE: return ">=";
458 case XASM_OP_NOT: return "!";
459 case XASM_OP_NEG: return "~";
460 case XASM_OP_LO: return "<";
461 case XASM_OP_HI: return ">";
462 case XASM_OP_UMINUS: return "-";
463 case XASM_OP_BANK: return "^";
465 return "";