remove some redundant comments
[xorcyst.git] / unit.c
blob24df9c3d9efd82e0d4ea02b4c02236364008acd3
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);
93 return s;
95 #define get_bytes_8(f) (unsigned char *)get_str_8(f)
96 #define get_bytes_16(f) (unsigned char *)get_str_16(f)
98 /*--------------------------------------------------------------------------*/
101 * Reads a constant from file.
102 * @param fp File handle
103 * @param u Unit in which constant is loaded
104 * @param i Index of constant in unit's constant array
106 static void get_const(FILE *fp, unit *u, int i)
108 constant *cnst = &u->constants[i];
109 cnst->name = get_str_8(fp);
110 cnst->type = get_1(fp);
111 switch (cnst->type) {
112 case INT_8: cnst->integer = get_1(fp); cnst->type = INTEGER_CONSTANT; break;
113 case INT_16: cnst->integer = get_2(fp); cnst->type = INTEGER_CONSTANT; break;
114 case INT_24: cnst->integer = get_3(fp); cnst->type = INTEGER_CONSTANT; break;
115 case INT_32: cnst->integer = get_4(fp); cnst->type = INTEGER_CONSTANT; break;
116 case STR_8: cnst->string = get_str_8(fp); cnst->type = STRING_CONSTANT; break;
117 case STR_16: cnst->string = get_str_16(fp); cnst->type = STRING_CONSTANT; break;
119 default:
120 fprintf(stderr, "%s(0x%lx): get_const(): bad constant type (%.2X)\n", u->name, ftell(fp), cnst->type);
121 break;
123 cnst->unit = u;
127 * Reads constant array from file.
128 * @param fp File handle
129 * @param u Unit whose constants array will be populated
131 static void get_constants(FILE *fp, unit *u)
133 int i;
134 int count = get_2(fp);
135 if (count > 0) {
136 u->constants = (constant *)malloc(sizeof(constant) * count);
137 } else {
138 u->constants = NULL;
140 for (i=0; i<count; i++) {
141 get_const(fp, u, i);
143 u->const_count = count;
147 * Reads imported symbol from file.
148 * @param fp File handle
149 * @param u Unit
150 * @param i External index
152 static void get_ext(FILE *fp, unit *u, int i)
154 external *ext = &u->externals[i];
155 ext->unit = get_1(fp);
156 ext->name = get_str_8(fp);
157 ext->from = u;
161 * Reads imported symbol array from file.
162 * @param fp File handle
163 * @param u Unit whose externals array will be populated
165 static void get_externals(FILE *fp, unit *u)
167 int i;
168 int count;
169 count = get_2(fp);
170 if (count > 0) {
171 u->externals = (external *)malloc(sizeof(external) * count);
172 } else {
173 u->externals = NULL;
175 for (i=0; i<count; i++) {
176 get_ext(fp, u, i);
178 u->ext_count = count;
182 * Reads an expression from file.
183 * @param fp File handle
184 * @param dest Pointer to pointer where expression should be stored
185 * @param u Owner unit
187 static void get_expr_recursive(FILE *fp, expression **dest, unit *u)
189 unsigned char type;
190 expression *exp = (expression *)malloc( sizeof(expression) );
191 if (exp != NULL) {
192 type = get_1(fp);
193 switch (type) {
194 case INT_8: exp->integer = get_1(fp); exp->type = INTEGER_EXPRESSION; break;
195 case INT_16: exp->integer = get_2(fp); exp->type = INTEGER_EXPRESSION; break;
196 case INT_24: exp->integer = get_3(fp); exp->type = INTEGER_EXPRESSION; break;
197 case INT_32: exp->integer = get_4(fp); exp->type = INTEGER_EXPRESSION; break;
198 case STR_8: exp->string = get_str_8(fp); exp->type = STRING_EXPRESSION; break;
199 case STR_16: exp->string = get_str_16(fp); exp->type = STRING_EXPRESSION; break;
201 case LOCAL: exp->local_id = get_2(fp); exp->type = LOCAL_EXPRESSION; break;
202 case EXTRN: exp->extrn_id = get_2(fp); exp->type = EXTERNAL_EXPRESSION;break;
204 case PC: ; exp->type = PC_EXPRESSION; break;
206 case OP_PLUS:
207 case OP_MINUS:
208 case OP_MUL:
209 case OP_DIV:
210 case OP_MOD:
211 case OP_SHL:
212 case OP_SHR:
213 case OP_AND:
214 case OP_OR:
215 case OP_XOR:
216 case OP_EQ:
217 case OP_NE:
218 case OP_LT:
219 case OP_GT:
220 case OP_LE:
221 case OP_GE:
222 get_expr_recursive(fp, &exp->op_expr.lhs, u);
223 get_expr_recursive(fp, &exp->op_expr.rhs, u);
224 exp->op_expr.operator = type;
225 exp->type = OPERATOR_EXPRESSION;
226 break;
228 case OP_NOT:
229 case OP_NEG:
230 case OP_LO:
231 case OP_HI:
232 case OP_UMINUS:
233 case OP_BANK:
234 get_expr_recursive(fp, &exp->op_expr.lhs, u);
235 exp->op_expr.rhs = NULL;
236 exp->op_expr.operator = type;
237 exp->type = OPERATOR_EXPRESSION;
238 break;
240 default:
241 fprintf(stderr, "%s(0x%lx): get_expr(): invalid expression type (%.2X)\n", u->name, ftell(fp), type);
242 exp->integer = 0;
243 exp->type = INTEGER_EXPRESSION;
244 break;
247 exp->unit = u;
248 *dest = exp;
252 * Reads expressions from file.
253 * @param fp File handle
254 * @param u Unit whose expressions array to populate
256 static void get_expressions(FILE *fp, unit *u)
258 int i;
259 int count;
260 count = get_2(fp);
261 if (count > 0) {
262 u->expressions = (expression **)malloc(sizeof(expression *) * count);
263 } else {
264 u->expressions = NULL;
266 for (i=0; i<count; i++) {
267 get_expr_recursive(fp, &u->expressions[i], u);
269 u->expr_count = count;
273 * Reads a segment from file.
274 * @param fp File handle
275 * @param seg Where to store segment
277 static void get_segment(FILE *fp, segment *seg)
279 seg->size = get_3(fp);
280 if (seg->size > 0) {
281 seg->bytes = (unsigned char *)malloc(seg->size);
282 if (seg->bytes != NULL) {
283 fread(seg->bytes, 1, seg->size, fp);
285 } else {
286 seg->bytes = NULL;
290 /*--------------------------------------------------------------------------*/
293 * Reads a unit from file.
294 * @param filename Name of the unit
295 * @param u Pointer to struct to fill in
297 int unit_read(char *filename, unit *u)
299 FILE *fp;
300 int count, i;
301 unsigned short magic;
302 unsigned char version;
304 u->name = filename;
305 fp = fopen(filename, "rb");
306 if (fp == NULL) {
307 u->const_count = 0;
308 u->ext_count = 0;
309 u->expr_count = 0;
310 u->dataseg.size = 0;
311 u->dataseg.bytes = NULL;
312 u->codeseg.size = 0;
313 u->codeseg.bytes = NULL;
314 return 0;
317 magic = get_2(fp);
318 if (magic != A_MAGIC) {
319 /* Error, bad magic number */
320 return 0;
323 version = get_1(fp);
324 if (version != A_VERSION) {
325 /* Error, bad version */
326 return 0;
329 get_constants(fp, u);
331 /* Read # of units explicitly imported from */
332 count = get_1(fp);
333 /* Read unit names */
334 for (i=0; i<count; i++) {
335 get_str_8(fp);
338 get_externals(fp, u);
339 get_segment(fp, &u->dataseg);
340 get_segment(fp, &u->codeseg);
341 get_expressions(fp, u);
343 fclose(fp);
345 /* Success */
346 return 1;
349 /*--------------------------------------------------------------------------*/
352 * Finalizes a constant.
353 * @param c Constant to finalize
355 static void finalize_constant(constant *c)
357 if (c->type == STRING_CONSTANT) {
358 SAFE_FREE(c->string);
360 SAFE_FREE(c->name);
364 * Finalizes an external.
365 * @param e External to finalize
367 static void finalize_external(external *e)
369 SAFE_FREE(e->name);
373 * Finalizes an expression.
374 * @param e Expression to finalize
376 static void finalize_expression(expression *e)
378 if (e == NULL) { return; }
379 switch (e->type) {
380 case STRING_EXPRESSION:
381 SAFE_FREE(e->string);
382 break;
384 case OPERATOR_EXPRESSION:
385 finalize_expression(e->op_expr.lhs);
386 finalize_expression(e->op_expr.rhs);
387 break;
389 default:
390 /* Nada */
391 break;
393 SAFE_FREE(e);
397 * Finalizes a bytecode segment.
398 * @param s Segment to finalize
400 static void finalize_segment(segment *s)
402 SAFE_FREE(s->bytes);
405 /*--------------------------------------------------------------------------*/
408 * Finalizes a unit.
409 * @param u Unit to finalize
411 void unit_finalize(unit *u)
413 int i;
414 for (i=0; i<u->const_count; i++) {
415 finalize_constant(&u->constants[i]);
417 SAFE_FREE(u->constants);
419 for (i=0; i<u->ext_count; i++) {
420 finalize_external(&u->externals[i]);
422 SAFE_FREE(u->externals);
424 for (i=0; i<u->expr_count; i++) {
425 finalize_expression(u->expressions[i]);
427 SAFE_FREE(u->expressions);
429 finalize_segment(&u->dataseg);
430 finalize_segment(&u->codeseg);