SpiderScript - More changes, cleaning up
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / bytecode_makefile.c
1 /*
2  * SpiderScript Library
3  * by John Hodge (thePowersGang)
4  * 
5  * bytecode_makefile.c
6  * - Generate a bytecode file
7  */
8 #include <stdlib.h>
9 #include "ast.h"
10 #include "bytecode_gen.h"
11 #include <stdio.h>
12 #include <string.h>
13
14 // === IMPORTS ===
15
16 // === PROTOTYPES ===
17
18 // === GLOBALS ===
19
20 // === CODE ===
21 int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile)
22 {
23         tStringList     strings = {0};
24         tAST_Function   *fcn;
25         FILE    *fp;
26          int    fcn_hdr_offset = 0;
27          int    fcn_count = 0;
28          int    strtab_ofs;
29
30         void _put8(uint8_t val)
31         {
32                 fwrite(&val, 1, 1, fp);
33         }
34         void _put32(uint32_t val)
35         {
36                 _put8(val & 0xFF);
37                 _put8(val >> 8);
38                 _put8(val >> 16);
39                 _put8(val >> 24);
40         }
41
42         fp = fopen(DestFile, "wb");
43         if(!fp) return 1;
44         
45         // Create header
46         fwrite("SSBC\r\n\xBC\x55", 8, 1, fp);
47         _put32(0);      // Function count, to be filled
48         _put32(0);      // String count
49         _put32(0);      // String table offset
50         // TODO: Variant info
51
52         fcn_hdr_offset = ftell(fp);
53
54         // Create function descriptors
55         for(fcn = Script->Script->Functions; fcn; fcn = fcn->Next, fcn_count ++)
56         {
57                 tAST_Node *arg;
58
59                 _put32( StringList_GetString(&strings, fcn->Name, strlen(fcn->Name)) );
60                 _put32( 0 );    // Code offset
61                 _put8( fcn->ReturnType );
62                 
63                 if(fcn->ArgumentCount > 255) {
64                         // ERROR: Too many args
65                         return 2;
66                 }
67                 _put8( fcn->ArgumentCount );
68
69                 // Argument types?
70                 for(arg = fcn->Arguments; arg; arg = arg->NextSibling)
71                 {
72                         _put32( StringList_GetString(&strings, arg->DefVar.Name, strlen(arg->DefVar.Name)) );
73                         _put8( arg->DefVar.DataType );
74                 }
75         }
76
77         // Put function code in
78         for(fcn = Script->Script->Functions; fcn; fcn = fcn->Next)
79         {
80                 char    *code;
81                  int    len, code_pos;
82                 tBC_Function    *bc_fcn;
83         
84                 // Fix header   
85                 code_pos = ftell(fp);
86                 fseek(fp, SEEK_SET, fcn_hdr_offset + 4);
87                 _put32( code_pos );
88                 fseek(fp, SEEK_SET, code_pos );
89
90                 fcn_hdr_offset += 4+4+1+1+(4+1)*fcn->ArgumentCount;
91                 
92                 // Write code
93                 bc_fcn = Bytecode_ConvertFunction(fcn);
94                 code = Bytecode_SerialiseFunction(bc_fcn, &len, &strings);
95                 Bytecode_DeleteFunction(bc_fcn);
96                 fwrite(code, len, 1, fp);
97                 free(code);
98         }
99
100         // String table
101         strtab_ofs = ftell(fp);
102         {
103                  int    string_offset = strtab_ofs + (4+4)*strings.Count;
104                 tString *str;
105                 // Array
106                 for(str = strings.Head; str; str = str->Next)
107                 {
108                         _put32(str->Length);
109                         _put32(string_offset);
110                         string_offset += str->Length + 1;
111                 }
112                 // Data
113                 for(str = strings.Head; str;)
114                 {
115                         tString *nextstr = str->Next;
116                         fwrite(str->Data, str->Length, 1, fp);
117                         _put8(0);
118                         free(str);
119                         str = nextstr;
120                 }
121                 strings.Head = NULL;
122                 strings.Tail = NULL;
123         }
124
125         // Fix header
126         fseek(fp, 8, SEEK_SET);
127         _put32(fcn_count);
128         _put32(strings.Count);
129         _put32(strtab_ofs);
130
131         fclose(fp);
132
133         return 0;
134 }
135

UCC git Repository :: git.ucc.asn.au