Usermode - Fixed GAS/NASM detection
[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 SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile)
22 {
23         tStringList     strings = {0};
24         tScript_Function        *fcn;
25         FILE    *fp;
26          int    fcn_hdr_offset = 0;
27          int    fcn_count = 0;
28          int    strtab_ofs;
29          int    i;
30
31         void _put8(uint8_t val)
32         {
33                 fwrite(&val, 1, 1, fp);
34         }
35         void _put32(uint32_t val)
36         {
37                 _put8(val & 0xFF);
38                 _put8(val >> 8);
39                 _put8(val >> 16);
40                 _put8(val >> 24);
41         }
42
43         fp = fopen(DestFile, "wb");
44         if(!fp) return 1;
45         
46         // Create header
47         fwrite("SSBC\r\n\xBC\x55", 8, 1, fp);
48         _put32(0);      // Function count, to be filled
49         _put32(0);      // String count
50         _put32(0);      // String table offset
51         // TODO: Variant info
52
53         fcn_hdr_offset = ftell(fp);
54
55         // Create function descriptors
56         for(fcn = Script->Functions; fcn; fcn = fcn->Next, fcn_count ++)
57         {
58                 _put32( StringList_GetString(&strings, fcn->Name, strlen(fcn->Name)) );
59                 _put32( 0 );    // Code offset
60                 // TODO: Namespace
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( i = 0; i < fcn->ArgumentCount; i ++ )
71                 {
72                         _put32( StringList_GetString(&strings, fcn->Arguments[i].Name, strlen(fcn->Arguments[i].Name)) );
73                         _put8( fcn->Arguments[i].Type );
74                 }
75         }
76
77         // Put function code in
78         for(fcn = Script->Functions; fcn; fcn = fcn->Next)
79         {
80                 char    *code;
81                  int    len, code_pos;
82         
83                 // Fix header   
84                 code_pos = ftell(fp);
85                 fseek(fp, SEEK_SET, fcn_hdr_offset + 4);
86                 _put32( code_pos );
87                 fseek(fp, SEEK_SET, code_pos );
88
89                 fcn_hdr_offset += 4+4+1+1+(4+1)*fcn->ArgumentCount;
90                 
91                 // Write code
92                 if( !fcn->BCFcn )       Bytecode_ConvertFunction(fcn);
93                 code = Bytecode_SerialiseFunction(fcn->BCFcn, &len, &strings);
94                 fwrite(code, len, 1, fp);
95                 free(code);
96         }
97
98         // String table
99         strtab_ofs = ftell(fp);
100         {
101                  int    string_offset = strtab_ofs + (4+4)*strings.Count;
102                 tString *str;
103                 // Array
104                 for(str = strings.Head; str; str = str->Next)
105                 {
106                         _put32(str->Length);
107                         _put32(string_offset);
108                         string_offset += str->Length + 1;
109                 }
110                 // Data
111                 for(str = strings.Head; str;)
112                 {
113                         tString *nextstr = str->Next;
114                         fwrite(str->Data, str->Length, 1, fp);
115                         _put8(0);
116                         free(str);
117                         str = nextstr;
118                 }
119                 strings.Head = NULL;
120                 strings.Tail = NULL;
121         }
122
123         // Fix header
124         fseek(fp, 8, SEEK_SET);
125         _put32(fcn_count);
126         _put32(strings.Count);
127         _put32(strtab_ofs);
128
129         fclose(fp);
130
131         return 0;
132 }
133

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