comp.c (11251B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdbool.h> 5 #include <signal.h> 6 #include <unistd.h> 7 8 #include "tokenizer.h" 9 #include "util.h" 10 #include "appendsnprintf.h" 11 12 #define MAXOUTLEN 512 13 14 // globals for memory management 15 char *tofree[256]; 16 int freeptr = 0; 17 bool neededmemptr = false; 18 19 // globals for structs 20 char *structname; 21 22 // globals for errors 23 pid_t pid; 24 int linecount = 0; 25 char *currentLine; 26 char *errmsg; 27 28 //# error handler that will be triggered by signal when there is a syntax error and will print information 29 void errorhandle(int type){ 30 fprintf(stderr, "err:%d (%s)\n", linecount, currentLine); 31 fprintf(stderr, "%s\n", errmsg); 32 33 exit(1); 34 } 35 36 //# this function will check if the value given is null, if it is, it will cause a sig segv and set the error msg 37 static void checkNULL(void *value, char *msg){ 38 if (value == NULL) { 39 errmsg = msg; 40 kill(pid, SIGSEGV); 41 } 42 } 43 44 char *names[] = { 45 "defun", // takes a func name, func return type, and args // 0 46 "endfun", // takes no args // 1 47 "let", // takes a name and type, then a value (immutable) // 2 48 "set", // same as above but mutable values // 3 49 "if", // takes a condition // 4 50 "endif", // takes no args // 5 51 "elif", // same as if, but only executes if the prev statment didnt // 6 52 "else", // its else! // 7 53 "for", // takes a iterator and type, a start point, a condition, and an increment // 8 54 "endfor", // takes no args // 9 55 "symbol", // takes a name and return type and args // 10 56 // arithmetic 57 "+", // 11 58 "-", // 12 59 "*", // 13 60 "/", // 14 61 // comparison 62 "=", // 15 63 "!=", // 16 64 "<", // 17 65 ">", // 18 66 "<=", // 19 67 ">=", // 20 68 69 "exit", // takes an int // 21 70 "return", // takes an int // 22 71 72 "alloc", // takes a size and allocates a block of it // 23 73 74 "struct", // takes a name for the struct // 24 75 "endstruct", // takes nothing // 25 76 77 "def", // takes a name and type does not asign // 26 78 79 "sizeof", // takes a datatype and returns its size // 27 80 81 "defunptr" // takes the same stuff as defun but outputs it in fuction ptr form 82 }; 83 84 // function prototype for recursion of the compile function 85 static char *compile(astNode *node); 86 87 //# this function will convert the zpy style variable defintion, to the c style 88 static char *vartypeToC(char *str, char *out){ 89 char *name = malloc(strlen(str)); 90 char *type = malloc(strlen(str)); 91 92 int j = 0, i = 0; 93 94 for (; i < strlen(str); i++){ 95 if (str[i] == ':'){ 96 break; 97 } 98 name[i] = str[i]; 99 } 100 name[i] = '\0'; 101 i++; 102 103 if (i > strlen(str)) checkNULL(NULL, "expected var type, got nothing"); 104 105 for (; i < strlen(str); i++){ 106 if (str[i] == ':'){ 107 break; 108 } 109 type[j] = str[i]; 110 j++; 111 } 112 type[j] = '\0'; 113 114 char *outbuf = calloc(0, 64); 115 outbuf = appendsnprintf(outbuf, MAXOUTLEN, "%s %s", type, name); 116 out = appendsnprintf(out, MAXOUTLEN, "%s", outbuf); 117 free(type); 118 free(name); 119 return out; 120 } 121 122 //# this function will give the user the variable name, without its type, which is useful for translation 123 static char *getVarName(char *exp){ 124 char *out = malloc(strlen(exp)); 125 memcpy(out, exp, strlen(exp)); 126 char *pos = strchr(out, ':'); 127 if (pos == NULL) checkNULL(NULL, "expected var type, got nothing"); 128 pos[0] = '\0'; 129 return out; 130 } 131 132 //# this function will give the user the type, without its name, which is useful for translation 133 static char *getVarType(char *exp){ 134 char *out = malloc(strlen(exp)); 135 char *pos = strchr(exp, ':')+1; 136 if (pos == NULL) checkNULL(NULL, "expected var type, got nothing"); 137 memcpy(out, pos, strlen(pos) + 1); 138 return out; 139 } 140 //# this will convert mathmatical expressions, to the c style of maths 141 static char *reversepolishToC(astNode *exp, char *out){ 142 out = appendsnprintf(out, MAXOUTLEN, "%s ", exp->args[0]); 143 if (exp->func[0] == '=') out = appendsnprintf(out, MAXOUTLEN, "=="); 144 else out = appendsnprintf(out, MAXOUTLEN, "%s", exp->func); 145 out = appendsnprintf(out, MAXOUTLEN, " %s", exp->args[1]); 146 return out; 147 } 148 149 //# this is a recursive loop that will call the compile function recursivly to flatten the tree 150 static astNode *processChildren(astNode *node){ 151 for (int i = 0; i < 8; i++){ 152 if (node->children[i] != NULL){ 153 node->args[i] = compile(node->children[i]); 154 node->children[i] = NULL; 155 } 156 } 157 return node; 158 } 159 160 //# this function will do the bulk of converting from zpy into c code 161 static char *compile(astNode *node){ 162 char *out = calloc(0, MAXOUTLEN); 163 node = processChildren(node); 164 if (strcmp(names[0], node->func) == 0){ // converting function definitions 165 checkNULL(node->args[0], "expected func name"); 166 checkNULL(node->args[1], "expected return type"); 167 out = appendsnprintf(out, MAXOUTLEN, "%s %s(", node->args[1], node->args[0]); 168 int i = 2; 169 while (node->args[i] != NULL){ 170 if (i != 2) out = appendsnprintf(out, MAXOUTLEN, ","); 171 out = vartypeToC(node->args[i], out); 172 i++; 173 } 174 out = appendsnprintf(out, MAXOUTLEN, "){\n"); 175 } 176 else if (strcmp(names[1], node->func) == 0){ // converting ending function definitions 177 out = appendsnprintf(out, MAXOUTLEN, "}\n"); 178 } 179 else if (strcmp(names[2], node->func) == 0){ // converting variable declarations 180 checkNULL(node->args[0], "expected var name"); 181 checkNULL(node->args[1], "expected var value"); 182 out = vartypeToC(node->args[0], out); 183 out = appendsnprintf(out, MAXOUTLEN, " = %s;\n", node->args[1]); 184 } 185 else if (strcmp(names[3], node->func) == 0){ // converting vairable reasignments 186 checkNULL(node->args[0], "expected var name"); 187 checkNULL(node->args[1], "expected var value"); 188 out = appendsnprintf(out, MAXOUTLEN, "%s = %s;\n", node->args[0], node->args[1]); 189 } 190 else if (strcmp(names[4], node->func) == 0){ // converting if statments 191 checkNULL(node->args[0], "expected sub expression"); 192 out = appendsnprintf(out, MAXOUTLEN, "if (%s", node->args[0]); 193 out = appendsnprintf(out, MAXOUTLEN, "){\n"); 194 } 195 else if (strcmp(names[5], node->func) == 0){ // converting ending if statments 196 out = appendsnprintf(out, MAXOUTLEN, "}\n"); 197 } 198 else if (strcmp(names[6], node->func) == 0){ // converting elif (else if) statments 199 checkNULL(node->args[0], "expected sub expression"); 200 out = appendsnprintf(out, MAXOUTLEN, "}else if (%s", node->args[0]); 201 out = appendsnprintf(out, MAXOUTLEN, "){\n"); 202 } 203 else if (strcmp(names[7], node->func) == 0){ // converting else statments 204 out = appendsnprintf(out, MAXOUTLEN, "}\n"); 205 out = appendsnprintf(out, MAXOUTLEN, "else{"); 206 } 207 else if (strcmp(names[8], node->func) == 0){ // converting for loop statments 208 checkNULL(node->args[0], "expected iterator"); 209 checkNULL(node->args[1], "expected iterator value"); 210 checkNULL(node->args[2], "expected condition"); 211 checkNULL(node->args[3], "expected iterator increment"); 212 out = appendsnprintf(out, MAXOUTLEN, "for ("); 213 out = vartypeToC(node->args[0], out); 214 out = appendsnprintf(out, MAXOUTLEN, " = %s;", node->args[1]); 215 out = appendsnprintf(out, MAXOUTLEN, "%s", node->args[2]); 216 out = appendsnprintf(out, MAXOUTLEN, "; %s+=%s){", getVarName(node->args[0]), node->args[3]); 217 } 218 else if (strcmp(names[9], node->func) == 0){ // converting end for loop statments 219 out = appendsnprintf(out, MAXOUTLEN, "}\n"); 220 } 221 else if (strcmp(names[10], node->func) == 0){ // converting symbol definition statments 222 checkNULL(node->args[0], "expected symbol type"); 223 checkNULL(node->args[1], "expected symbol name"); 224 out = appendsnprintf(out, MAXOUTLEN, "%s %s(", node->args[1], node->args[0]); 225 int i = 2; 226 while (node->args[i] != NULL){ 227 if (i != 2) out = appendsnprintf(out, MAXOUTLEN, ",", node->args[i]); 228 out = vartypeToC(node->args[i], out); 229 i++; 230 } 231 out = appendsnprintf(out, MAXOUTLEN, ");\n"); 232 } 233 else if (strcmp(names[21], node->func) == 0){ //converting exit statments 234 checkNULL(node->args[0], "expected exit code"); 235 out = appendsnprintf(out, MAXOUTLEN, "exit(%s);\n", node->args[0]); 236 } 237 else if (strcmp(names[22], node->func) == 0){ 238 for (int i = 0; i < 256; i++){ 239 if (tofree[i] != NULL){ 240 out = appendsnprintf(out, MAXOUTLEN, "free(%s);\n", tofree[i]); 241 } else{ 242 for (int j = 0; j < 256; j++){ 243 tofree[j] = NULL; 244 } 245 freeptr = 0; 246 break; 247 } 248 } 249 checkNULL(node->args[0], "expected return value"); // converting return statments 250 out = appendsnprintf(out, MAXOUTLEN, "return %s;\n", node->args[0]); 251 } 252 else if (strcmp(names[23], node->func) == 0){ // converting memory allocation statments 253 checkNULL(node->args[0], "expected alloc size"); 254 out = appendsnprintf(out, MAXOUTLEN, "malloc(%s)", node->args[0]); 255 neededmemptr = true; 256 } 257 else if (strcmp(names[24], node->func) == 0){ // converting struct definiton statments 258 checkNULL(node->args[0], "expected type name"); 259 out = appendsnprintf(out, MAXOUTLEN, "typedef struct %s %s;\n", node->args[0], node->args[0]); 260 out = appendsnprintf(out, MAXOUTLEN, "typedef struct %s {", node->args[0]); 261 structname = node->args[0]; 262 } 263 else if (strcmp(names[25], node->func) == 0){ // converting struct end statments 264 out = appendsnprintf(out, MAXOUTLEN, "} %s", structname); 265 structname = NULL; 266 } 267 else if (strcmp(names[26], node->func) == 0){ // converting variable definition statments 268 checkNULL(node->args[0], "expected variable definition"); 269 out = vartypeToC(node->args[0], out); 270 } 271 else if (strcmp(names[27], node->func) == 0){ // converting sizeof statments 272 checkNULL(node->args[0], "expected variable type"); 273 out = appendsnprintf(out, MAXOUTLEN, "sizeof(%s)", node->args[0]); 274 } 275 else if (strcmp(names[28], node->func) == 0){ // converting function pointer definition staments 276 checkNULL(node->args[0], "expected function ptr type"); 277 checkNULL(node->args[0], "expected function ptr name"); 278 out = appendsnprintf(out, MAXOUTLEN, "%s (*%s)", node->args[1], node->args[0]); 279 int i = 2; 280 while (node->args[i] != NULL){ 281 if (i != 2) out = appendsnprintf(out, MAXOUTLEN, ","); 282 else out = appendsnprintf(out, MAXOUTLEN, "("); 283 out = appendsnprintf(out, MAXOUTLEN, "%s", getVarType(node->args[i])); 284 i++; 285 } 286 out = appendsnprintf(out, MAXOUTLEN, ")"); 287 } 288 289 else { 290 // arithmetic operators and comparitors 291 for (int i = 0; i < 9; i++){ 292 checkNULL(node->func, "expected func name"); 293 if (strcmp(names[11+i], node->func) == 0){ 294 out = reversepolishToC(node, out); 295 goto end; 296 } 297 } 298 299 // converting user defined function calls 300 checkNULL(node->func, "expected func name"); 301 out = appendsnprintf(out, MAXOUTLEN, "%s(", node->func); 302 int i = 0; 303 while (node->args[i] != NULL){ 304 if (i != 0) out = appendsnprintf(out, MAXOUTLEN, ",", node->args[i]); 305 out = appendsnprintf(out, MAXOUTLEN, "%s", node->args[i]); 306 i++; 307 } 308 out = appendsnprintf(out, MAXOUTLEN, ")"); 309 } 310 end: 311 return out; 312 } 313 314 //# this function sets up the signal handler for the error msgs 315 void CompilerInit(){ 316 signal(SIGSEGV, &errorhandle); 317 pid = getpid(); 318 } 319 320 //# the exposed compiler function that will fully process an astNode tree 321 void Compile(astNode *line, FILE *f, char* strline){ 322 currentLine = strline; 323 char *code = compile(line); 324 if (neededmemptr == true){ 325 tofree[freeptr] = line->args[0]; 326 freeptr++; 327 neededmemptr = false; 328 } 329 int len = strlen(code); 330 if (code[len-2] == ';' || code[len-2] == '{' || code[len-2] == '}') fprintf(f, "%s", code); 331 else fprintf(f, "%s;\n", code); 332 linecount++; 333 free(code); 334 }