forked from gabordemooij/citrine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.c
209 lines (201 loc) · 6.79 KB
/
util.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <math.h>
#include <stdint.h>
#include <unistd.h>
#include <dlfcn.h>
#include "citrine.h"
char* np;
/**
* Determines the size of the specified file.
*/
int fsize(char* filename) {
int size;
FILE* fh;
fh = fopen(filename, "rb");
if(fh != NULL){
if( fseek(fh, 0, SEEK_END) ){
fclose(fh);
return -1;
}
size = ftell(fh);
fclose(fh);
return size;
}
return -1;
}
/**
* Serializer Serialize
* Serializes an pre-aligned abstract syntax tree along with
* its addressbook.
*/
void ctr_serializer_serialize(ctr_tnode* t) {
FILE *f;
f = fopen(ctr_mode_compile_save_as,"wb");
if (!f) { printf("Unable to open file!"); exit(1); }
memcpy( ctr_malloc_chunk, ctr_default_header, sizeof(ctr_ast_header));/* append to addressbook, new header */
fwrite(ctr_malloc_chunk, sizeof(char), ctr_malloc_measured_size_code+ctr_malloc_measured_size_addressbook, f);
fclose(f);
}
/**
* Serializer Show Information
* Outputs information about the specified AST file.
*/
void ctr_serializer_info(char* filename) {
FILE *f;
char* str;
size_t s = 0;
s = fsize(filename);
np = calloc(sizeof(char),s);
if (!np) { printf("no memory.\n"); exit(1);}
f = fopen(filename,"rb");
fread(np, sizeof(char), s, f);
fclose(f);
ctr_default_header = (ctr_ast_header*) (np);
printf("Citrine AST-FILE INFO:\n");
str = (char*) malloc(sizeof(char) * 11);
*(str + 10) = '\0';
strncpy(str, ctr_default_header->version, 10);
printf("Version and Identification Code : %s \n", ctr_default_header->version);
printf("Number of Pointer Swizzles : %lu \n", (long) ctr_default_header->num_of_swizzles);
printf("Size of Addressbook : %lu \n", (long) ctr_default_header->size_of_address_book);
printf("Start Original Memory Block (OB): %p \n", (char*) ctr_default_header->start_block);
printf("Program Entry Point (PEP) : %p \n", (char*) ctr_default_header->program_entry_point);
}
/**
* Serializer Unserialize
* Loads an AST file in memory and recalculates (unswizzles) the
* stale pointers in the tree, then returns the root AST node to
* start the program.
*/
ctr_tnode* ctr_serializer_unserialize(char* filename) {
FILE *f;
uint64_t j=0;
size_t s = 0;
uintptr_t p; /* addressbook entry */
uintptr_t p2; /* corrected address entry */
uintptr_t ob; /* old base */
uint64_t cnt; /* counter */
uintptr_t tp; /* the new pointer (replacement) */
uintptr_t otp; /* the old pointer (to be replaced) */
uintptr_t pe; /* pe */
uintptr_t sz;
s = fsize(filename);
np = malloc(sizeof(char)*s);
if (!np) { printf("no memory.\n"); exit(1);}
f = fopen(filename,"rb");
fread(np, sizeof(char), s, f);
fclose(f);
ctr_default_header = (ctr_ast_header*) (np);
sz = ctr_default_header->size_of_address_book;
ob = ctr_default_header->start_block;
pe = ctr_default_header->program_entry_point;
cnt = ctr_default_header->num_of_swizzles;
ctr_malloc_swizzle_adressbook = (uintptr_t*) (np + sizeof(ctr_ast_header));
pe = pe - (uintptr_t) ob;
pe = pe + (uintptr_t) np;
/* perform pointer swizzling to restore the tree from the image */
for(j = 0; j<cnt; j++) {
p = (uintptr_t) *(ctr_malloc_swizzle_adressbook); /* p is an old address */
p2 = p - (uintptr_t) ob + (uintptr_t) np; /* subtract the base from p and add the new base */
otp = *((uintptr_t* )p2); /* retrieve the old pointer from p2 */
if (otp != 0) {
tp = otp - (uintptr_t) ob + (uintptr_t) np; /* correct the pointer for the new base address */
*((uintptr_t* )p2) = tp; /* replace the old pointer with the new one */
}
ctr_malloc_swizzle_adressbook += 1; /* take an address from the book */
}
return (ctr_tnode*) pe;
}
/**
* DebugTree
*
* For debugging purposes, prints the internal AST.
*/
void ctr_internal_debug_tree(ctr_tnode* ti, int indent) {
char* str;
char* vbuf;
ctr_tlistitem* li;
ctr_tnode* t;
if (indent>20) exit(1);
li = ti->nodes;
t = li->node;
while(1) {
int i;
for (i=0; i<indent; i++) printf(" ");
str = calloc(40, sizeof(char));
switch (t->type) {
case CTR_AST_NODE_EXPRASSIGNMENT: str = "ASSIGN\0"; break;
case CTR_AST_NODE_EXPRMESSAGE: str = "MESSAG\0"; break;
case CTR_AST_NODE_UNAMESSAGE: str = "UMSSAG\0"; break;
case CTR_AST_NODE_KWMESSAGE: str = "KMSSAG\0"; break;
case CTR_AST_NODE_BINMESSAGE: str = "BMSSAG\0"; break;
case CTR_AST_NODE_LTRSTRING: str = "STRING\0"; break;
case CTR_AST_NODE_REFERENCE: str = "REFRNC\0"; break;
case CTR_AST_NODE_LTRNUM: str = "NUMBER\0"; break;
case CTR_AST_NODE_CODEBLOCK: str = "CODEBL\0"; break;
case CTR_AST_NODE_RETURNFROMBLOCK: str = "RETURN\0"; break;
case CTR_AST_NODE_PARAMLIST: str = "PARAMS\0"; break;
case CTR_AST_NODE_INSTRLIST: str = "INSTRS\0"; break;
case CTR_AST_NODE_ENDOFPROGRAM: str = "EOPROG\0"; break;
case CTR_AST_NODE_NESTED: str = "NESTED\0"; break;
case CTR_AST_NODE_LTRBOOLFALSE: str = "BFALSE\0"; break;
case CTR_AST_NODE_LTRBOOLTRUE: str = "BLTRUE\0"; break;
case CTR_AST_NODE_LTRNIL: str = "LTRNIL\0"; break;
default: str = "UNKNW?\0"; break;
}
vbuf = calloc(sizeof(char),t->vlen+1);
strncpy(vbuf, t->value, t->vlen);
printf("%s %s (%p)\n", str, vbuf, (void*) t);
if (t->nodes) ctr_internal_debug_tree(t, indent + 1);
if (!li->next) break;
li = li->next;
t = li->node;
}
}
/**
* @internal
* Internal plugin loader.
* Tries to locate a plugin by its name.
*
* In Citrine a plugin is loaded automatically as soon as a symbol
* has been enountered that cannot be found in global scope.
*
* Before raising an error Citrine will attempt to load a plugin
* to meet the dependency.
*
* To install a plugin, copy the plugin folder to the mods folder
* in the working directory of your script.
*
* So, for instance, to install the 'Coffee Percolator Plugin',
* we copy the libctrpercolator.so in folder mods/percolator/,
* the resulting path is: mods/percolator/libctrpercolator.so.
*
* General path format:
*
* mods/X/libctrX.so
*
* where X is the name of the object the plugin offers in lowercase.
*
* On loading, the plugin will get a chance to add its objects to the world
* through a constructor function.
*/
void* ctr_internal_plugin_find(ctr_object* key) {
ctr_object* modNameObject = ctr_internal_cast2string(key);
void* handle;
char pathNameMod[1024];
char* modName;
char* modNameLow;
char* realPathModName = NULL;
CTR_2CSTR(modName, modNameObject);
modNameLow = modName;
for ( ; *modNameLow; ++modNameLow) *modNameLow = tolower(*modNameLow);
snprintf(pathNameMod, 1024,"mods/%s/libctr%s.so", modName, modName);
realPathModName = realpath(pathNameMod, NULL);
if (access(realPathModName, F_OK) == -1) return NULL;
handle = dlopen(realPathModName, RTLD_NOW);
return handle;
}