* Add ragg2 -I to prepend include path directories
* Enhacements in r_egg library - Add support for including files - bla.r@include($PATH); - Proper support for goto() keyword - Add support to get and set environment variables (need more work) - PATH@env(/bin); - Fix /* */ comment parsing code
This commit is contained in:
parent
8933c45e0d
commit
1b440bf9d2
|
@ -12,6 +12,7 @@ static int usage () {
|
|||
" -F output native format (osx=mach0, linux=elf, ..)\n"
|
||||
" -o [file] output file\n"
|
||||
" -O use default output file (filename without extension or a.out)\n"
|
||||
" -I add include path\n"
|
||||
" -s show assembler\n"
|
||||
" -x show hexpairs (enabled by default)\n"
|
||||
" -X execute\n"
|
||||
|
@ -59,10 +60,10 @@ int main(int argc, char **argv) {
|
|||
const char *ofile = NULL;
|
||||
int ofileauto = 0;
|
||||
RBuffer *b;
|
||||
REgg *egg;
|
||||
int c, i;
|
||||
REgg *egg = r_egg_new ();
|
||||
|
||||
while ((c = getopt (argc, argv, "ha:b:f:o:sxXk:FO")) != -1) {
|
||||
while ((c = getopt (argc, argv, "ha:b:f:o:sxXk:FOI:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
arch = optarg;
|
||||
|
@ -80,6 +81,9 @@ int main(int argc, char **argv) {
|
|||
case 'O':
|
||||
ofileauto = 1;
|
||||
break;
|
||||
case 'I':
|
||||
r_egg_lang_include_path (egg, optarg);
|
||||
break;
|
||||
case 'F':
|
||||
#if __APPLE__
|
||||
format = "mach0";
|
||||
|
@ -129,17 +133,16 @@ int main(int argc, char **argv) {
|
|||
free (p);
|
||||
if (fd == -1) {
|
||||
eprintf ("cannot open file '%s'\n", optarg);
|
||||
exit (1);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (ofile) {
|
||||
if (openfile (ofile, ISEXEC) == -1) {
|
||||
eprintf ("cannot open file '%s'\n", optarg);
|
||||
return 1;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
egg = r_egg_new ();
|
||||
r_egg_setup (egg, arch, bits, 0, os);
|
||||
if (!strcmp (argv[optind], "-")) {
|
||||
char buf[1024];
|
||||
|
@ -151,7 +154,7 @@ int main(int argc, char **argv) {
|
|||
} else {
|
||||
if (!r_egg_include (egg, argv[optind], 0)) {
|
||||
eprintf ("Cannot open '%s'\n", argv[optind]);
|
||||
return 1;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
r_egg_compile (egg);
|
||||
|
|
|
@ -33,7 +33,11 @@ R_API void r_egg_free (REgg *egg) {
|
|||
}
|
||||
|
||||
R_API void r_egg_reset (REgg *egg) {
|
||||
// XXX: memory leak
|
||||
r_egg_lang_include_init (egg);
|
||||
r_buf_free (egg->src);
|
||||
r_buf_free (egg->buf);
|
||||
egg->src = r_buf_new ();
|
||||
egg->buf = r_buf_new ();
|
||||
}
|
||||
|
||||
R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os) {
|
||||
|
@ -71,9 +75,8 @@ R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const c
|
|||
egg->endian = endian;
|
||||
}
|
||||
if (egg->emit) {
|
||||
if (egg->emit->init) {
|
||||
if (egg->emit->init)
|
||||
egg->emit->init (egg);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
154
libr/egg/lang.c
154
libr/egg/lang.c
|
@ -27,6 +27,7 @@ enum {
|
|||
INLINE,
|
||||
SYSCALL,
|
||||
SYSCALLBODY,
|
||||
GOTO,
|
||||
LAST
|
||||
};
|
||||
|
||||
|
@ -34,6 +35,8 @@ enum {
|
|||
static int pushargs = 0;
|
||||
static int nsyscalls = 0;
|
||||
static char *syscallbody = NULL;
|
||||
static char *includefile = NULL;
|
||||
static char *setenviron = NULL;
|
||||
static int commentmode = 0;
|
||||
static int varsize = 'l';
|
||||
static int varxs = 0;
|
||||
|
@ -64,28 +67,57 @@ static int stackfixed = 0;
|
|||
static int oc = '\n';
|
||||
static int mode = NORMAL;
|
||||
|
||||
static char *trim(char *s) {
|
||||
char *o;
|
||||
for (o=s; *s; s++)
|
||||
if (isspace (*s)) {
|
||||
*s = 0;
|
||||
break;
|
||||
static char *find_include(const char *prefix, const char *file) {
|
||||
char *pfx, *ret, *env = r_sys_getenv (R_EGG_INCDIR_ENV);
|
||||
//eprintf ("find_include (%s,%s)\n", prefix, file);
|
||||
if (!prefix) prefix = "";
|
||||
else if (*prefix=='$') {
|
||||
char *out = r_sys_getenv (prefix+1);
|
||||
pfx = out? out: strdup ("");
|
||||
} else pfx = strdup (prefix);
|
||||
|
||||
if (env) {
|
||||
char *str, *ptr = strchr (env, ':');
|
||||
// eprintf ("MUST FIND IN PATH (%s)\n", env);
|
||||
str = env;
|
||||
while (str) {
|
||||
if (ptr) {
|
||||
*ptr = 0;
|
||||
}
|
||||
ret = r_str_concatf (NULL, "%s/%s", pfx, file);
|
||||
{
|
||||
char *filepath = r_str_concatf (NULL, "%s/%s/%s", str, pfx, file);
|
||||
// eprintf ("try (%s)\n", filepath);
|
||||
if (r_file_exist (filepath)) {
|
||||
free (env);
|
||||
free (pfx);
|
||||
return filepath;
|
||||
}
|
||||
free (filepath);
|
||||
}
|
||||
if (!ptr) break;
|
||||
str = ptr+1;
|
||||
ptr = strchr (str, ':');
|
||||
}
|
||||
return o;
|
||||
free (env);
|
||||
} else ret = r_str_concatf (NULL, "%s/%s", pfx, file);
|
||||
free (pfx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rcc_set_callname(const char *s) {
|
||||
free (callname);
|
||||
callname = NULL;
|
||||
nargs = 0;
|
||||
while (*s==' '||*s=='\t') s++; // skip prefixed spaces (should never happen)
|
||||
callname = trim (strdup (s));
|
||||
pushargs = !((!strcmp (s, "goto")) || (!strcmp (s, "break")));
|
||||
R_API void r_egg_lang_include_path (REgg *egg, const char *path) {
|
||||
char *env = r_sys_getenv (R_EGG_INCDIR_ENV);
|
||||
if (!env || !*env) {
|
||||
r_egg_lang_include_init (egg);
|
||||
env = r_sys_getenv (R_EGG_INCDIR_ENV);
|
||||
}
|
||||
env = r_str_concatf (NULL, "%s:%s", path, env);
|
||||
r_sys_setenv (R_EGG_INCDIR_ENV, env);
|
||||
free (env);
|
||||
}
|
||||
|
||||
static void rcc_reset_callname() {
|
||||
R_FREE (callname);
|
||||
nargs = 0;
|
||||
R_API void r_egg_lang_include_init (REgg *egg) {
|
||||
r_sys_setenv (R_EGG_INCDIR_ENV, ".:"R_EGG_INCDIR_PATH);
|
||||
}
|
||||
|
||||
static const char *skipspaces(const char *s) {
|
||||
|
@ -102,6 +134,29 @@ static const char *skipspaces(const char *s) {
|
|||
return s;
|
||||
}
|
||||
|
||||
static char *trim(char *s) {
|
||||
char *o;
|
||||
for (o=s; *s; s++)
|
||||
if (isspace (*s)) {
|
||||
*s = 0;
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
static void rcc_set_callname(const char *s) {
|
||||
free (callname);
|
||||
callname = NULL;
|
||||
nargs = 0;
|
||||
callname = trim (strdup (skipspaces (s)));
|
||||
pushargs = !((!strcmp (s, "goto")) || (!strcmp (s, "break")));
|
||||
}
|
||||
|
||||
static void rcc_reset_callname() {
|
||||
R_FREE (callname);
|
||||
nargs = 0;
|
||||
}
|
||||
|
||||
#define SYNTAX_ATT 0
|
||||
#if SYNTAX_ATT
|
||||
#define FRAME_FMT ".LC%d_%d_frame%d"
|
||||
|
@ -152,6 +207,8 @@ static void rcc_element(REgg *egg, char *str) {
|
|||
|
||||
if (context) {
|
||||
nargs = 0;
|
||||
if (mode == GOTO)
|
||||
mode = NORMAL; // XXX
|
||||
while (p) {
|
||||
*p = '\0';
|
||||
p = (char *)skipspaces (p+1);
|
||||
|
@ -181,6 +238,10 @@ static void rcc_element(REgg *egg, char *str) {
|
|||
nsyscalls++;
|
||||
R_FREE (dstvar);
|
||||
break;
|
||||
case GOTO:
|
||||
elem[elem_n] = 0;
|
||||
e->jmp (egg, elem, 0);
|
||||
break;
|
||||
default:
|
||||
p = strchr (str, ',');
|
||||
if (p) {
|
||||
|
@ -333,6 +394,12 @@ static void rcc_fun(REgg *egg, const char *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
|
||||
|
@ -351,7 +418,9 @@ static void rcc_fun(REgg *egg, const char *str) {
|
|||
}
|
||||
} else
|
||||
if (strstr (ptr, "include")) {
|
||||
eprintf ("TODO: include directive\n");
|
||||
free (includefile);
|
||||
includefile = strdup (skipspaces (str));
|
||||
slurp = 0;
|
||||
} else
|
||||
if (strstr (ptr, "alias")) {
|
||||
mode = ALIAS;
|
||||
|
@ -377,11 +446,16 @@ static void rcc_fun(REgg *egg, const char *str) {
|
|||
} else {
|
||||
//e->jmp (egg, ctxpush[context], 0);
|
||||
if (context>0) {
|
||||
// WTF?
|
||||
eprintf ("LABEL %d\n", context);
|
||||
r_egg_printf (egg, "\n%s:\n", str);
|
||||
} else {
|
||||
// goto()
|
||||
e->jmp (egg, str, 0);
|
||||
if (!strcmp (str, "goto")) {
|
||||
mode = GOTO;
|
||||
} else {
|
||||
// call() // or maybe jmp?
|
||||
e->call (egg, str, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -414,7 +488,6 @@ static void rcc_context(REgg *egg, int delta) {
|
|||
emit->get_while_end (egg, str, ctxpush[context-1], get_frame_label (2));
|
||||
free (endframe);
|
||||
endframe = strdup (str);
|
||||
free (callname);
|
||||
rcc_set_callname ("if");
|
||||
}
|
||||
if (!strcmp (callname, "if")) {
|
||||
|
@ -530,6 +603,38 @@ static void rcc_next(REgg *egg) {
|
|||
char *str, *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")) {
|
||||
|
@ -686,8 +791,10 @@ R_API int r_egg_lang_parsechar(REgg *egg, char c) {
|
|||
}
|
||||
/* comments */
|
||||
if (skipline) {
|
||||
if (c != '\n')
|
||||
if (c != '\n') {
|
||||
oc = c;
|
||||
return 0;
|
||||
}
|
||||
skipline = 0;
|
||||
}
|
||||
if (mode == DATA)
|
||||
|
@ -710,6 +817,7 @@ R_API int r_egg_lang_parsechar(REgg *egg, char c) {
|
|||
quotelinevar = 1;
|
||||
} else r_egg_printf (egg, "%c", c);
|
||||
}
|
||||
oc = c;
|
||||
return 0;
|
||||
} else {
|
||||
r_egg_printf (egg, "\n");
|
||||
|
@ -720,6 +828,7 @@ R_API int r_egg_lang_parsechar(REgg *egg, char c) {
|
|||
if (commentmode) {
|
||||
if (c=='/' && oc == '*')
|
||||
commentmode = 0;
|
||||
oc = c;
|
||||
return 0;
|
||||
} else if (c=='*' && oc == '/')
|
||||
commentmode = 1;
|
||||
|
@ -782,6 +891,7 @@ R_API int r_egg_lang_parsechar(REgg *egg, char c) {
|
|||
case '/':
|
||||
if (oc == '/')
|
||||
skipline = 1;
|
||||
else elem[elem_n++] = c;
|
||||
break;
|
||||
default:
|
||||
elem[elem_n++] = c;
|
||||
|
|
|
@ -1,2 +1,18 @@
|
|||
INCDIR@alias(i/);
|
||||
sys.r@include(INCDIR);
|
||||
#INCDIR@alias(i/);
|
||||
|
||||
/*
|
||||
TODO: we need ragg2 to setup OS ARCH BITS environs
|
||||
use environment to set/get values
|
||||
OS@env(osx);
|
||||
syscalls.r@include($OS);
|
||||
|
||||
use ragg2 -I to add new include path
|
||||
*/
|
||||
|
||||
#INCDIR@env(/usr/include/r_egg);
|
||||
INCDIR@env(t); # INCDIR=t
|
||||
sys.r@include($INCDIR); # find t/sys.r
|
||||
|
||||
main@global() {
|
||||
exit(43);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
/* TODO: all bins must contain a jmp main */
|
||||
/* entrypoint */
|
||||
:jmp main
|
||||
//main();
|
||||
goto(main);
|
||||
//:jmp main
|
||||
|
||||
|
||||
puts@global() {
|
||||
//write(1,.arg0);
|
||||
/* do nothing */
|
||||
: mov edx, 3
|
||||
/* : mov ecx, 0x10000002a */
|
||||
|
@ -15,20 +19,21 @@ puts@global() {
|
|||
}
|
||||
|
||||
exit@global() {
|
||||
: mov ebx, `.arg0`
|
||||
: mov eax, 1
|
||||
: push eax
|
||||
: int 0x80
|
||||
}
|
||||
|
||||
main@global(128)
|
||||
{
|
||||
main@global(128) {
|
||||
.var0 = 3;
|
||||
.var4 = "counter";
|
||||
exit(0);
|
||||
{
|
||||
puts(.var4);
|
||||
.var0 -= 1;
|
||||
} while(.var0);
|
||||
exit()
|
||||
|
||||
/* comment */
|
||||
.var0 = 3;
|
||||
.var4 = "coconut";
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
exit@syscall(1);
|
||||
@syscall() {
|
||||
: int 0x88
|
||||
}
|
||||
main@global() {
|
||||
exit(0);
|
||||
}
|
|
@ -5,6 +5,9 @@
|
|||
#include <r_util.h>
|
||||
#include <r_syscall.h>
|
||||
|
||||
#define R_EGG_INCDIR_ENV "EGG_INCDIR"
|
||||
#define R_EGG_INCDIR_PATH PREFIX"/lib/radare2/"R2_VERSION"/egg"
|
||||
|
||||
typedef struct r_egg_t {
|
||||
RBuffer *src;
|
||||
RBuffer *buf;
|
||||
|
@ -102,5 +105,7 @@ R_API void r_egg_append(REgg *egg, const char *src);
|
|||
/* lang.c */
|
||||
R_API char *r_egg_mkvar(REgg *egg, char *out, const char *_str, int delta);
|
||||
R_API int r_egg_lang_parsechar(REgg *egg, char c);
|
||||
R_API void r_egg_lang_include_path (REgg *egg, const char *path);
|
||||
R_API void r_egg_lang_include_init (REgg *egg);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -471,6 +471,7 @@ R_API void r_str_writef(int fd, const char *fmt, ...) {
|
|||
}
|
||||
|
||||
/*
|
||||
* first argument must be allocated
|
||||
* return: the pointer ptr resized to string size.
|
||||
*/
|
||||
R_API char *r_str_concat(char *ptr, const char *string) {
|
||||
|
@ -487,7 +488,7 @@ R_API char *r_str_concat(char *ptr, const char *string) {
|
|||
}
|
||||
|
||||
R_API char *r_str_concatf(char *ptr, const char *fmt, ...) {
|
||||
char string[1024];
|
||||
char string[4096];
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
vsnprintf (string, sizeof (string), fmt, ap);
|
||||
|
|
Loading…
Reference in New Issue