static void rcc_pushstr(REgg *egg, char *str, int filter) { int dotrim = 1; int i, j, len; REggEmit *e = egg->remit; e->comment (egg, "encode %s string (%s) (%s)", filter? "filtered": "unfiltered", str, callname); if (filter) for (i=0; str[i]; i++) { if (str[i]=='\\') { switch (str[i+1]) { case 't': str[i]='\t'; break; case 'n': str[i]='\n'; break; case 'e': str[i]='\x1b'; break; default: dotrim = 0; break; } if (dotrim) memmove (str+i+1, str+i+2, strlen (str+i+2)); } } len = strlen (str); j = (len-len%e->size)+e->size; e->set_string (egg, dstvar, str, j); free (dstvar); dstvar = NULL; }
/* 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_context(REgg *egg, int delta) { REggEmit *emit = egg->remit; char str[64]; if (CTX>31 || CTX <0) return; nestedi[CTX]++; if (callname && CTX>0) {// && delta>0) { // set_nested (callname); //eprintf (" - - - - - - - set nested d=%d c=%d (%s)\n", delta, context-1, callname); //shownested(); } CTX += delta; lastctxdelta = delta; if (CTX == 0 && delta < 0) { if (mode != NAKED) emit->frame_end (egg, stackframe+stackfixed, nbrackets); if (mode == NORMAL) /* XXX : commenting this makes hello.r unhappy! TODO: find a cleaner alternative */ stackframe = 0; mode = NORMAL; } else { /* conditional block */ //eprintf ("Callname is (%s)\n", callname); const char *elm = skipspaces (elem); const char *cn = callname; //if (nested[context-1]) #if 0 if (delta<0 && context>0) { eprintf ("close bracket foo!!!\n"); shownested (); cn = strdup (nested[context-1]); eprintf ("STATEMENT cn=(%s) idx=%d (%s)\n", cn, context-1, nested[context-1]); eprintf ("CNTXXXPUSH (%s)\n", ctxpush[context-1]); #if 0 if (!strcmp (cn, "while")) { emit->while_end (egg, get_frame_label (context-1)); //char *var = get_frame_label (0); //emit->jmp (egg, var, 0); return; } #endif } #endif //eprintf ("ELEM (%s)\n", elm); //eprintf ("END BLOCK %d, (%s)\n", context, nested[context-1]); //eprintf ("CN = (%s) %d (%s) delta=%d\n", cn, context, nested[context-1], delta); if (cn) { //if (callname) { // handle 'foo() {' /* TODO: this must be an array */ char *b, *g, *e, *n; emit->comment (egg, "cond frame %s (%s)", cn, elm); /* TODO: simplify with a single for */ b = strchr (elem, '<'); /* below */ g = strchr (elem, '>'); /* greater */ e = strchr (elem, '='); /* equal */ n = strchr (elem, '!'); /* negate */ if (!strcmp (cn, "while")) { char lab[128]; sprintf (lab, "__begin_%d_%d_%d", nfunctions, CTX-1, nestedi[CTX-1]); emit->get_while_end (egg, str, ctxpush[CTX-1], lab); //get_frame_label (2)); //get_frame_label (2)); //eprintf ("------ (%s)\n", ctxpush[context-1]); // free (endframe); // XXX: endframe is deprecated, must use set_nested only if (delta>0) { set_nested (egg, str); } rcc_set_callname ("if"); // append 'if' body } if (!strcmp (cn, "if")) { //emit->branch (egg, b, g, e, n, varsize, get_end_frame_label (egg)); // HACK HACK :D sprintf (str, "__end_%d_%d_%d", nfunctions, CTX-1, nestedi[CTX-1]); nestede[CTX-1] = strdup (str); sprintf (str, "__end_%d_%d_%d", nfunctions, CTX, nestedi[CTX-1]); emit->branch (egg, b, g, e, n, varsize, str); if (CTX>0) { /* XXX .. */ } rcc_reset_callname (); } //else eprintf ("Unknown statement (%s)(%s)\n", cn, elem); } // handle '{ ..' } }