/* TODO: split this function into several ones..quite long fun */ static void rcc_next(REgg *egg) { const char *ocn; REggEmit *e = egg->remit; char *str = NULL, *p, *ptr, buf[64]; int i; if (setenviron) { elem[elem_n - 1] = 0; r_sys_setenv (setenviron, elem); R_FREE (setenviron); return; } if (includefile) { char *p, *q, *path; // TODO: add support for directories elem[elem_n-1] = 0; path = find_include (elem, includefile); if (!path) { eprintf ("Cannot find include file '%s'\n", elem); return; } free (includefile); includefile = NULL; rcc_reset_callname (); p = q = r_file_slurp (path, NULL); if (p) { int oline = ++line; elem[0] = 0; // TODO: this must be a separate function elem_n = 0; line = 0; for (; *p; p++) r_egg_lang_parsechar (egg, *p); free (q); line = oline; } else { eprintf ("Cannot find '%s'\n", path); } free (path); return; } docall = 1; if (callname) { if (!strcmp (callname, "goto")) { if (nargs != 1) { eprintf ("Invalid number of arguments for goto()\n"); return; } e->jmp (egg, ctxpush[CTX], 0); rcc_reset_callname (); return; } if (!strcmp (callname, "break")) { e->trap (egg); rcc_reset_callname (); return; } ptr = strchr (callname, '='); if (ptr) { *ptr = '\0'; //ocn = ptr+1; // what is the point of this? } ocn = skipspaces (callname); if (!ocn) return; str = r_egg_mkvar (egg, buf, ocn, 0); if (!str) { eprintf ("Cannot mkvar\n"); return; } if (*ocn=='.') e->call (egg, str, 1); if (!strcmp (str, "while")) { char var[128]; if (lastctxdelta >= 0) exit (eprintf ("ERROR: Unsupported while syntax\n")); sprintf (var, "__begin_%d_%d_%d\n", nfunctions, CTX, nestedi[CTX-1]); e->while_end (egg, var); //get_frame_label (1)); #if 0 eprintf ("------------------------------------------ lastctx: %d\n", lastctxdelta); // TODO: the pushvar is required for the if(){}while(); constructions //char *pushvar = ctxpush[context+nbrackets-1]; /* TODO: support to compare more than one expression (LOGICAL OR) */ rcc_printf (" pop %%eax\n"); rcc_printf (" cmp $0, %%eax\n"); // XXX MUST SUPPORT != 0 COMPARE HERE /* TODO : Simplify!! */ //if (pushvar) // printf(" push %s /* wihle push */\n", pushvar); if (lastctxdelta<0) rcc_printf (" jnz %s\n", get_frame_label (1)); else rcc_printf (" jnz %s\n", get_frame_label (0)); //if (pushvar) // printf(" pop %%"R_AX" /* while pop */\n"); #endif nargs = 0; } else { for (i = 0; i < nsyscalls; i++) { if (!strcmp (str, syscalls[i].name)) { p = syscallbody; e->comment (egg, "set syscall args"); e->syscall_args (egg, nargs); docall = 0; e->comment (egg, "syscall"); r_egg_lang_parsechar (egg, '\n'); /* FIX parsing issue */ if (p) { for (; *p; p++) r_egg_lang_parsechar (egg, *p); } else { char *q, *s = e->syscall (egg, nargs); if (s) { for (q=s; *q; q++) r_egg_lang_parsechar (egg, *q); free (s); } else eprintf ("Cannot get @syscall payload\n"); } docall = 0; break; } } if (docall) for (i = 0; i < ninlines; i++) { if (!strcmp (str, inlines[i].name)) { p = inlines[i].body; docall = 0; e->comment (egg, "inline"); r_egg_lang_parsechar (egg, '\n'); /* FIX parsing issue */ for (; *p; p++) r_egg_lang_parsechar (egg, *p); docall = 0; break; } } if (docall) { e->comment (egg, "call in mode %d", mode); e->call (egg, str, 0); } } if (nargs > 0) e->restore_stack (egg, nargs*e->size); if (ocn) { // Used to call .var0() /* XXX: Probably buggy and wrong */ *buf = 0; free (str); str = r_egg_mkvar (egg, buf, ocn, 0); if (*buf) e->get_result (egg, buf); //else { eprintf("external symbol %s\n", ocn); } } /* store result of call */ if (dstvar) { if (mode != NAKED) { *buf = 0; free (str); str = r_egg_mkvar (egg, buf, dstvar, 0); if (*buf == 0) eprintf ("Cannot resolve variable '%s'\n", dstvar); else e->get_result (egg, buf); } R_FREE (dstvar); } rcc_reset_callname (); } else { int vs = 'l'; char type, *eq, *ptr = elem; elem[elem_n] = '\0'; ptr = (char*)skipspaces (ptr); if (*ptr) { eq = strchr (ptr, '='); if (eq) { char str2[64], *p, ch = *(eq-1); *eq = '\0'; eq = (char*) skipspaces (eq+1); p = r_egg_mkvar (egg, str2, ptr, 0); vs = varsize; if (is_var (eq)) { eq = r_egg_mkvar (egg, buf, eq, 0); if (varxs=='*') e->load (egg, eq, varsize); else /* XXX this is a hack .. must be integrated with pusharg */ if (varxs=='&') e->load_ptr (egg, eq); if (eq) { free (eq); eq = NULL; } type = ' '; } else type = '$'; vs = 'l'; // XXX: add support for != 'l' size e->mathop (egg, ch, vs, type, eq, p); free(p); } else { if (!strcmp (ptr, "break")) { // handle 'break;' e->trap (egg); rcc_reset_callname (); } else { e->mathop (egg, '=', vs, '$', ptr, NULL); } } } } free (str); }
static void rcc_fun(REgg *egg, const char *str) { char *ptr, *ptr2; REggEmit *e = egg->remit; str = skipspaces (str); if (CTX) { ptr = strchr (str, '='); if (ptr) { *ptr++ = '\0'; free (dstvar); dstvar = strdup (skipspaces (str)); ptr2 = (char *)skipspaces (ptr); if (*ptr2) rcc_set_callname (skipspaces (ptr)); } else { str = skipspaces (str); rcc_set_callname (skipspaces (str)); egg->remit->comment (egg, "rcc_fun %d (%s)", CTX, callname); } } else { ptr = strchr (str, '@'); if (ptr) { *ptr++ = '\0'; mode = NORMAL; if (strstr (ptr, "env")) { //eprintf ("SETENV (%s)\n", str); free (setenviron); setenviron = strdup (skipspaces (str)); slurp = 0; } else if (strstr (ptr, "fastcall")) { /* TODO : not yet implemented */ } else if (strstr (ptr, "syscall")) { if (*str) { mode = SYSCALL; dstvar = strdup (skipspaces (str)); } else { mode = INLINE; free (syscallbody); syscallbody = malloc (4096); // XXX hardcoded size dstval = syscallbody; R_FREE (dstvar); ndstval = 0; *syscallbody = '\0'; } } else if (strstr (ptr, "include")) { free (includefile); includefile = strdup (skipspaces (str)); slurp = 0; } else if (strstr (ptr, "alias")) { mode = ALIAS; dstvar = strdup (skipspaces (str)); } else if (strstr (ptr, "data")) { mode = DATA; ndstval = 0; dstvar = strdup (skipspaces (str)); dstval = malloc (4096); } else if (strstr (ptr, "naked")) { mode = NAKED; free (dstvar); dstvar = strdup (skipspaces (str)); dstval = malloc (4096); ndstval = 0; r_egg_printf (egg, "%s:\n", str); } else if (strstr (ptr, "inline")) { mode = INLINE; free (dstvar); dstvar = strdup (skipspaces (str)); dstval = malloc (4096); ndstval = 0; } else { // naked label if (*ptr) r_egg_printf (egg, "\n.%s %s\n", ptr, str); r_egg_printf (egg, "%s:\n", str); } } else { //e->jmp (egg, ctxpush[context], 0); if (CTX>0) { // WTF? eprintf ("LABEL %d\n", CTX); r_egg_printf (egg, "\n%s:\n", str); } else { if (!strcmp (str, "goto")) { mode = GOTO; } else { // call() // or maybe jmp? e->call (egg, str, 0); } } } } }