2 * $Id: unit.c,v 1.4 2007/07/22 13:33:26 khansen Exp $
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
13 * Revision 1.1 2004/06/30 07:56:00 kenth
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
41 #define SAFE_FREE(m) if ((m) != NULL) { free(m); m = NULL; }
43 /*---------------------------------------------------------------------------*/
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 */
55 /* Reads a 24-bit integer (big-endian) */
56 static unsigned int get_3(FILE *fp
)
59 result
= get_2(fp
) << 8; /* High 16 bits */
60 result
|= get_1(fp
); /* Low byte */
63 /* Reads an int (big-endian) */
64 static unsigned int get_4(FILE *fp
)
67 /* Assumes little-endian machine!! */
68 result
= get_2(fp
) << 16; /* High 16 bits */
69 result
|= get_2(fp
); /* Low 16 bits */
72 /* Reads a string prepended by 8-bit length */
73 static char *get_str_8(FILE *fp
)
77 int len
= get_1(fp
) + 1;
78 /* Allocate space for string */
79 s
= (char *)malloc(len
+ 1);
81 /* Read string from file */
83 /* 0-terminate string */
86 /* Return the new string */
89 /* Reads a string prepended by 16-bit length */
90 static char *get_str_16(FILE *fp
)
94 int len
= get_2(fp
) + 1;
95 /* Allocate space for string */
96 s
= (char *)malloc(len
+ 1);
98 /* Read string from file */
101 /* Return the new string */
104 #define get_bytes_8(f) (unsigned char *)get_str_8(f)
105 #define get_bytes_16(f) (unsigned char *)get_str_16(f)
107 /*--------------------------------------------------------------------------*/
110 * Reads a constant from file.
111 * @param fp File handle
112 * @param u Unit in which constant is loaded
113 * @param i Index of constant in unit's constant array
115 static void get_const(FILE *fp
, unit
*u
, int i
)
117 constant
*cnst
= &u
->constants
[i
];
119 cnst
->name
= get_str_8(fp
);
121 cnst
->type
= get_1(fp
);
123 switch (cnst
->type
) {
124 case INT_8
: cnst
->integer
= get_1(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
125 case INT_16
: cnst
->integer
= get_2(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
126 case INT_24
: cnst
->integer
= get_3(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
127 case INT_32
: cnst
->integer
= get_4(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
128 case STR_8
: cnst
->string
= get_str_8(fp
); cnst
->type
= STRING_CONSTANT
; break;
129 case STR_16
: cnst
->string
= get_str_16(fp
); cnst
->type
= STRING_CONSTANT
; break;
132 /* Error, invalid type */
133 fprintf(stderr
, "%s(0x%lx): get_const(): bad constant type (%.2X)\n", u
->name
, ftell(fp
), cnst
->type
);
141 * Reads constant array from file.
142 * @param fp File handle
143 * @param u Unit whose constants array will be populated
145 static void get_constants(FILE *fp
, unit
*u
)
148 /* Read the number of constants */
149 int count
= get_2(fp
);
150 /* Allocate the list */
152 u
->constants
= (constant
*)malloc(sizeof(constant
) * count
);
158 for (i
=0; i
<count
; i
++) {
161 /* Set count field */
162 u
->const_count
= count
;
166 * Reads imported symbol from file.
167 * @param fp File handle
169 * @param i External index
171 static void get_ext(FILE *fp
, unit
*u
, int i
)
173 external
*ext
= &u
->externals
[i
];
175 ext
->unit
= get_1(fp
);
177 ext
->name
= get_str_8(fp
);
183 * Reads imported symbol array from file.
184 * @param fp File handle
185 * @param u Unit whose externals array will be populated
187 static void get_externals(FILE *fp
, unit
*u
)
191 /* Read the number of imported symbols */
193 /* Allocate the list */
195 u
->externals
= (external
*)malloc(sizeof(external
) * count
);
200 /* Read imported symbols */
201 for (i
=0; i
<count
; i
++) {
204 /* Set count field */
205 u
->ext_count
= count
;
209 * Reads an expression from file.
210 * @param fp File handle
211 * @param dest Pointer to pointer where expression should be stored
212 * @param u Owner unit
214 static void get_expr_recursive(FILE *fp
, expression
**dest
, unit
*u
)
217 /* Allocate space for expression */
218 expression
*exp
= (expression
*)malloc( sizeof(expression
) );
220 /* Read expression type */
225 case INT_8
: exp
->integer
= get_1(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
226 case INT_16
: exp
->integer
= get_2(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
227 case INT_24
: exp
->integer
= get_3(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
228 case INT_32
: exp
->integer
= get_4(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
229 case STR_8
: exp
->string
= get_str_8(fp
); exp
->type
= STRING_EXPRESSION
; break;
230 case STR_16
: exp
->string
= get_str_16(fp
); exp
->type
= STRING_EXPRESSION
; break;
233 case LOCAL
: exp
->local_id
= get_2(fp
); exp
->type
= LOCAL_EXPRESSION
; break;
234 case EXTRN
: exp
->extrn_id
= get_2(fp
); exp
->type
= EXTERNAL_EXPRESSION
;break;
236 /* Current address */
237 case PC
: ; exp
->type
= PC_EXPRESSION
; break;
239 /* Arithmetic, binary */
256 get_expr_recursive(fp
, &exp
->op_expr
.lhs
, u
);
257 get_expr_recursive(fp
, &exp
->op_expr
.rhs
, u
);
258 exp
->op_expr
.operator = type
;
259 exp
->type
= OPERATOR_EXPRESSION
;
262 /* Arithmetic, unary */
269 get_expr_recursive(fp
, &exp
->op_expr
.lhs
, u
);
270 exp
->op_expr
.rhs
= NULL
;
271 exp
->op_expr
.operator = type
;
272 exp
->type
= OPERATOR_EXPRESSION
;
276 fprintf(stderr
, "%s(0x%lx): get_expr(): invalid expression type (%.2X)\n", u
->name
, ftell(fp
), type
);
278 exp
->type
= INTEGER_EXPRESSION
;
284 /* Set result pointer */
289 * Reads expressions from file.
290 * @param fp File handle
291 * @param u Unit whose expressions array to populate
293 static void get_expressions(FILE *fp
, unit
*u
)
297 /* Read the number of expressions */
299 /* Allocate the list */
301 u
->expressions
= (expression
**)malloc(sizeof(expression
*) * count
);
304 u
->expressions
= NULL
;
306 /* Read expressions */
307 for (i
=0; i
<count
; i
++) {
308 get_expr_recursive(fp
, &u
->expressions
[i
], u
);
311 u
->expr_count
= count
;
315 * Reads a segment from file.
316 * @param fp File handle
317 * @param seg Where to store segment
319 static void get_segment(FILE *fp
, segment
*seg
)
322 seg
->size
= get_3(fp
);
325 /* Allocate mem for bytecodes */
326 seg
->bytes
= (unsigned char *)malloc(seg
->size
);
327 if (seg
->bytes
!= NULL
) {
329 fread(seg
->bytes
, 1, seg
->size
, fp
);
337 /*--------------------------------------------------------------------------*/
340 * Reads a unit from file.
341 * @param filename Name of the unit
342 * @param u Pointer to struct to fill in
344 int unit_read(char *filename
, unit
*u
)
348 unsigned short magic
;
349 unsigned char version
;
353 /* Attempt to open file */
354 fp
= fopen(filename
, "rb");
356 /* Error, couldn't open it */
361 u
->dataseg
.bytes
= NULL
;
363 u
->codeseg
.bytes
= NULL
;
366 /* Read magic number */
368 /* Verify magic number */
369 if (magic
!= A_MAGIC
) {
370 /* Error, bad magic number */
375 /* Verify version: should be 1.0 */
376 if (version
!= A_VERSION
) {
377 /* Error, bad version */
380 /* Read exported constants */
381 get_constants(fp
, u
);
382 /* Read # of units explicitly imported from */
384 /* Read unit names */
385 for (i
=0; i
<count
; i
++) {
388 /* Read imported symbols */
389 get_externals(fp
, u
);
391 get_segment(fp
, &u
->dataseg
);
393 get_segment(fp
, &u
->codeseg
);
394 /* Read expressions */
395 get_expressions(fp
, u
);
404 /*--------------------------------------------------------------------------*/
407 * Finalizes a constant.
408 * @param c Constant to finalize
410 static void finalize_constant(constant
*c
)
412 if (c
->type
== STRING_CONSTANT
) {
413 SAFE_FREE(c
->string
);
419 * Finalizes an external.
420 * @param e External to finalize
422 static void finalize_external(external
*e
)
428 * Finalizes an expression.
429 * @param e Expression to finalize
431 static void finalize_expression(expression
*e
)
433 if (e
== NULL
) { return; }
435 case STRING_EXPRESSION
:
436 SAFE_FREE(e
->string
);
439 case OPERATOR_EXPRESSION
:
440 finalize_expression(e
->op_expr
.lhs
);
441 finalize_expression(e
->op_expr
.rhs
);
452 * Finalizes a bytecode segment.
453 * @param s Segment to finalize
455 static void finalize_segment(segment
*s
)
460 /*--------------------------------------------------------------------------*/
464 * @param u Unit to finalize
466 void unit_finalize(unit
*u
)
469 /* Finalize the constants */
470 for (i
=0; i
<u
->const_count
; i
++) {
471 finalize_constant(&u
->constants
[i
]);
473 SAFE_FREE(u
->constants
);
474 /* Finalize the externals */
475 for (i
=0; i
<u
->ext_count
; i
++) {
476 finalize_external(&u
->externals
[i
]);
478 SAFE_FREE(u
->externals
);
479 /* Finalize expressions */
480 for (i
=0; i
<u
->expr_count
; i
++) {
481 finalize_expression(u
->expressions
[i
]);
483 SAFE_FREE(u
->expressions
);
484 /* Finalize bytecode segments */
485 finalize_segment(&u
->dataseg
);
486 finalize_segment(&u
->codeseg
);