Ejemplo n.º 1
0
/* 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);
}
Ejemplo n.º 2
0
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);
				}
			}
		}
	}
}