diff --git a/binr/rasm2/Makefile b/binr/rasm2/Makefile index ed6b790718..361cfaaa5c 100644 --- a/binr/rasm2/Makefile +++ b/binr/rasm2/Makefile @@ -1,5 +1,5 @@ BIN=rasm2 BINDEPS=r_asm r_parse r_syscall r_anal r_reg BINDEPS+=r_flag r_cons r_lang r_util - +CFLAGS+=-I../../shlr/spp include ../rules.mk diff --git a/binr/rasm2/rasm2.c b/binr/rasm2/rasm2.c index 2e8541ac69..4a49c14c5a 100644 --- a/binr/rasm2/rasm2.c +++ b/binr/rasm2/rasm2.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "../blob/version.c" static RLib *l = NULL; @@ -382,11 +383,11 @@ int main (int argc, char *argv[]) { &__lib_asm_cb, &__lib_asm_dt, NULL); r_lib_add_handler (l, R_LIB_TYPE_ANAL, "analysis/emulation plugins", &__lib_anal_cb, &__lib_anal_dt, NULL); - + path = r_sys_getenv (R_LIB_ENV); if (path && *path) r_lib_opendir (l, path); - + if (1) { char *homeplugindir = r_str_home (R2_HOMEDIR "/plugins"); // eprintf ("OPENDIR (%s)\n", homeplugindir); @@ -592,6 +593,13 @@ int main (int argc, char *argv[]) { } } else { content = r_file_slurp (file, &length); + Output out; + out.fout = NULL; + out.cout = r_strbuf_new (""); + r_strbuf_init (out.cout); + struct Proc proc; + spp_proc_set (&proc, "asm", 1); + if (content) { if (len && len > 0 && len < length) length = len; @@ -608,7 +616,10 @@ int main (int argc, char *argv[]) { } else if (analinfo) { ret = show_analinfo ((const char *)buf, offset); } else { - ret = rasm_asm (content, offset, length, a->bits, bin); + spp_eval (content, &out); + char *spp_out = strdup (r_strbuf_get (out.cout)); + ret = rasm_asm (spp_out, offset, length, a->bits, bin); + free (spp_out); } ret = !ret; free (content); diff --git a/libr/util/Makefile b/libr/util/Makefile index 166a21d736..d4da0cb6db 100644 --- a/libr/util/Makefile +++ b/libr/util/Makefile @@ -14,6 +14,8 @@ OBJS+=utf8.o strbuf.o lib.o name.o spaces.o OBJS+=diff.o bdiff.o stack.o queue.o tree.o des.o OBJS+=punycode.o +include spp.mk + # DO NOT BUILD r_big api (not yet used and its buggy) ifeq (1,0) ifeq (${HAVE_LIB_GMP},1) @@ -41,11 +43,11 @@ endif endif EXTRA_PRE+=sdb_version -#$(SDBLIB) include ../rules.mk include sdb.mk + sync-regex regex-sync: -rm -rf src/ cvs -qd anoncvs@anoncvs.ca.openbsd.org:/cvs get -P src/lib/libc/regex diff --git a/libr/util/spp.mk b/libr/util/spp.mk new file mode 100644 index 0000000000..aa6a227c71 --- /dev/null +++ b/libr/util/spp.mk @@ -0,0 +1,6 @@ +SPPPATH=../../shlr/spp/ +SPP_OBJS=spp.o +SPPOBJS=$(addprefix ${SPPPATH},${SPP_OBJS}) +OBJS+=$(SPPOBJS) + +$(shell cp ${SPPPATH}/config.def.h ${SPPPATH}/config.h) diff --git a/shlr/Makefile b/shlr/Makefile index d31ee4eb13..1445b8c1cb 100644 --- a/shlr/Makefile +++ b/shlr/Makefile @@ -45,6 +45,7 @@ MODS+=gdb MODS+=qnx SDB_URL=git://github.com/radare/sdb #SDB_URL=/Users/pancake/prg/sdb +SPP_URL=git://github.com/radare/spp PWD=$(shell pwd) SDB_CONFIG=${PWD}/sdb-config.mk @@ -280,3 +281,13 @@ www-sync-t sync-www-t: sync-www www-sync: www-sync-m www-sync-p www-sync-t @echo webui sync done + + +spp-sync: + rm -rf spp + git clone --depth 1 ${SPP_URL} spp + +spp: spp-sync + cd spp ; $(MAKE) + +.PHONY: spp diff --git a/shlr/spp/.gitignore b/shlr/spp/.gitignore new file mode 100644 index 0000000000..bb686bd3bf --- /dev/null +++ b/shlr/spp/.gitignore @@ -0,0 +1,3 @@ +out.php +test.php +config.h diff --git a/shlr/spp/BUGS b/shlr/spp/BUGS new file mode 100644 index 0000000000..993d045ebf --- /dev/null +++ b/shlr/spp/BUGS @@ -0,0 +1,12 @@ +Known bugs and missfeatures +=========================== + +* Argument parsing is not correct + +* Add includeonce into 'spp' + +* set variable names with middle dash doesnt works + <{set foo-bar cow}> + <{ifeq foo-bar}> + <{trace failed}> + <{endif}> diff --git a/shlr/spp/LICENSE b/shlr/spp/LICENSE new file mode 100644 index 0000000000..5a021148a7 --- /dev/null +++ b/shlr/spp/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) +Copyright (c) 2009-2016 pancake + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/shlr/spp/Makefile b/shlr/spp/Makefile new file mode 100644 index 0000000000..7742950dcb --- /dev/null +++ b/shlr/spp/Makefile @@ -0,0 +1,42 @@ +override CFLAGS+=-g -Wall -MD +PREFIX?=/usr +BINDIR=${DESTDIR}${PREFIX}/bin +INSTALL_BIN=install -m 0755 +OBJ=spp.o main.o p/strbuf.o +ODF=$(subst .o,.d,$(OBJ)) +BIN=spp + +all: ${BIN} + +config.h: + cp config.def.h config.h + +${BIN}: config.h ${OBJ} + ${CC} ${LDFLAGS} -o ${BIN} ${OBJ} + +symlinks: + ln -s ${BIN} acr + ln -s ${BIN} cpp + ln -s ${BIN} pod + ln -s ${BIN} sh + +test: + @for a in t/*spp* ; do \ + printf "Testing $$a... " ; \ + ./spp -tspp -o out.txt $$a ; \ + if [ -z "`cat out.txt | grep BUG`" ]; then echo ok ; else echo oops ; fi ; \ + cat out.txt | grep BUG ; \ + rm -f out.txt ; \ + true ; \ + done + +install: + ${INSTALL_BIN} ${BIN} ${BINDIR} + +uninstall: + rm -f ${BINDIR}/${BIN} + +clean: + -rm -f ${BIN} ${OBJ} ${ODF} + +-include ${ODF} diff --git a/shlr/spp/README.md b/shlr/spp/README.md new file mode 100644 index 0000000000..1b46b1ad38 --- /dev/null +++ b/shlr/spp/README.md @@ -0,0 +1,41 @@ +spp +=== + +Author: pancake nopcodeorg> +License: MIT + +Description +----------- +SPP stands for Simple Pre-Processor. + +The primary use of spp is as a templating language, with +similarities to PHP and CPP. Allowing to embed scripts +in any language in some specific places of the document. + +Configuration +------------- +SPP binary can be configured by changing the values in the config.h file, this way you can specify which preprocessors you want to include in the parser. + + # Edit the config.h file before typing 'make' + +See config.def.h as an example + +Build +----- + $ make + +Installation +------------ + + $ make install PREFIX=/usr + +Embedding +--------- + +There are no embedding issues with the MIT license and the +amount if code is pretty low (~400 LOC), and use the apis: + + struct Proc p = {0}; + spp_proc_set (&p, "sh", 99); + char *res = spp_eval(&p, "hello {{echo orld}}" + printf ("(%s)\n", res); diff --git a/shlr/spp/config.def.h b/shlr/spp/config.def.h new file mode 100644 index 0000000000..83dfa7002c --- /dev/null +++ b/shlr/spp/config.def.h @@ -0,0 +1,20 @@ +#include "p/sh.h" +#include "p/spp.h" +#include "p/acr.h" +#include "p/pod.h" +#include "p/cpp.h" +#include "p/asm.h" + +struct Proc *procs[] = { + &spp_proc, + &cpp_proc, + &pod_proc, + &acr_proc, + &sh_proc, + &asm_proc, + NULL +}; + +DEFAULT_PROC(spp) + +#define DEBUG 0 diff --git a/shlr/spp/main.c b/shlr/spp/main.c new file mode 100644 index 0000000000..89d0e09147 --- /dev/null +++ b/shlr/spp/main.c @@ -0,0 +1,139 @@ +/* MIT (C) pancake (at) nopcode (dot) org */ + +#include "spp.h" + +extern struct Proc *procs[]; +extern struct Proc *proc; +extern struct Arg *args; + +static void spp_help(char *argv0) { + int i; + char supported[128] = ""; + for( i = 0; procs[i]; ++i ) { + if (i) strcat (supported, ","); + strcat (supported, procs[i]->name); + } + printf("Usage: %s [-othesv] [file] [...]\n", argv0); + printf( " -o [file] set output file (stdout)\n" + " -t [type] define processor type (%s)\n" + " -e [str] evaluate this string with the selected proc\n" + " -s [str] show this string before anything\n" + " -l list all built-in preprocessors\n" + " -L list keywords registered by the processor\n" + " -n do not read from stdin\n" + " -v show version information\n", supported); + if (proc) { + printf ("%s specific flags:\n", proc->name); + for(i = 0; args[i].flag; i++) { + printf (" %s %s\n", args[i].flag, args[i].desc); + } + } + exit(0); +} + +int main(int argc, char **argv) { + int dostdin = 1; + int i, j; + Output out; + out.fout = stdout; + char *arg; + + spp_proc_set (proc, argv[0], 0); + + if (argc < 2) + spp_io (stdin, &out); + else { + for(i = 1; i < argc; i++) { + /* check preprocessor args */ + if (args) + for(j = 0; args[j].flag; j++) { + if (!memcmp (argv[i], args[j].flag, 2)) { + if (args[j].has_arg) { + GET_ARG (arg, argv, i); + args[j].callback (arg); + } else { + args[j].callback (NULL); + } + continue; + } + } + + /* TODO: Add these flags in Arg[] */ + if (!memcmp (argv[i], "-o", 2)) { + GET_ARG (arg, argv, i); + if (arg != NULL) { + if (!strcmp (arg, "buff")) { + out.fout = NULL; + out.cout = r_strbuf_new (""); + r_strbuf_init (out.cout); + } else { + out.cout = NULL; + out.fout = fopen (arg, "w"); + } + } + if (!out.cout && (arg == NULL || out.fout == NULL)) { + fprintf (stderr, "Cannot open output file\n"); + exit (1); + } + } else + if (!memcmp (argv[i],"-t", 2)) { + GET_ARG (arg, argv, i); + spp_proc_set (proc, arg, 1); + } else + if (!strcmp (argv[i],"-v")) { + printf ("spp-%s\n", VERSION); + exit (1); + } else + if (!strcmp (argv[i],"-h")) { + /* show help */ + spp_help (argv[0]); + } else + if (!strcmp (argv[i],"-n")) { + dostdin = 0; + } else + if (!strcmp (argv[i],"-l")) { + spp_proc_list (); + exit (0); + } else + if (!strcmp (argv[i],"-L")) { + spp_proc_list_kw (); + exit (0); + } else + if (!strcmp (argv[i],"-s")) { + GET_ARG (arg, argv, i); + if (arg == NULL) arg = ""; + fprintf (out.fout, "%s\n", arg); + } else + if (!strcmp (argv[i],"-e")) { + GET_ARG (arg, argv, i); + if (arg == NULL) { + arg = ""; + } + spp_eval (arg, &out); + } else { + if (i == argc) { + fprintf (stderr, "No file specified.\n"); + } else { + spp_file (argv[i], &out); + dostdin = 0; + + if (!out.fout) { + D printf ("%s\n", r_strbuf_get (out.cout)); + r_strbuf_free (out.cout); + } + } + } + } + if (dostdin) { + spp_io (stdin, &out); + } + } + + if (proc->eof) + proc->eof ("", &out); + if (out.fout) { + fclose (out.fout); + } + + return 0; +} diff --git a/shlr/spp/p/acr.h b/shlr/spp/p/acr.h new file mode 100644 index 0000000000..d381621109 --- /dev/null +++ b/shlr/spp/p/acr.h @@ -0,0 +1,60 @@ +/* CPP */ + +static char *pkgname = NULL; +static char *version = NULL; +static char **slurp_ptr = NULL; + +static int slurp_args(char *buf) +{ + if (slurp_ptr) { + *slurp_ptr = strdup(buf); + slurp_ptr = NULL; + return 1; + } + return 0; +} + +TAG_CALLBACK(acr_default) +{ + //printf("acr keyword(%s)\n", buf); + + if (slurp_args(buf)) + return 0; + + if (!strcmp(buf, "PKGNAME")) { + slurp_ptr = &pkgname; + } else + if (!strcmp(buf, "VERSION")) { + slurp_ptr = &version; + } + return 0; +} + +TAG_CALLBACK(acr_eof) +{ + printf("Report:\n pkgname: %s\n version: %s\n", pkgname, version); + return 0; +} + +struct Tag acr_tags[] = { + { NULL, acr_default }, + { NULL } +}; + +struct Arg acr_args[] = { + { NULL } +}; + +struct Proc acr_proc = { + .name = "acr", + .tags = (struct Tag **)acr_tags, + .args = (struct Arg **)acr_args, + .token = " ", + .eof = &acr_eof, + .tag_pre = NULL, + .tag_post = NULL, + .multiline = NULL, + .default_echo = 1, + .chop = 0, + .tag_begin = 0, +}; diff --git a/shlr/spp/p/asm.h b/shlr/spp/p/asm.h new file mode 100644 index 0000000000..bca578b1e4 --- /dev/null +++ b/shlr/spp/p/asm.h @@ -0,0 +1,65 @@ +TAG_CALLBACK(asm_default) +{ + do_printf (out, "%s", buf); + return 0; +} + +TAG_CALLBACK(asm_include) +{ + if (echo[ifl]) { + spp_file(buf, out); + } + return 0; +} + +TAG_CALLBACK(asm_arch) +{ + do_printf (out, ".arch %s\n", buf); + return 0; +} + +TAG_CALLBACK(asm_bits) +{ + do_printf (out, ".bits %s\n", buf); + return 0; +} + +TAG_CALLBACK(asm_string) +{ + do_printf (out, ".string %s\n", buf); + return 0; +} + +PUT_CALLBACK(asm_fputs) +{ + do_printf (out, "%s", buf); + return 0; +} + +struct Tag asm_tags[] = { + { "include", asm_include }, + { "arch", asm_arch }, + { "bits", asm_bits }, + { "string", asm_string }, + { NULL, asm_default }, + { NULL } +}; + +struct Arg asm_args[] = { + { NULL } +}; + +struct Proc asm_proc = { + .name = "asm", + .tags = (struct Tag **)asm_tags, + .args = (struct Arg **)asm_args, + .token = " ", + .eof = NULL, + .tag_pre = ".", + .tag_post = "\n", + .multiline = "\\\n", + .default_echo = 1, + .fputs = asm_fputs, + .chop = 0, + .tag_begin = 0, +}; \ No newline at end of file diff --git a/shlr/spp/p/cpp.h b/shlr/spp/p/cpp.h new file mode 100644 index 0000000000..d6222d98ca --- /dev/null +++ b/shlr/spp/p/cpp.h @@ -0,0 +1,186 @@ +/* CPP */ + +TAG_CALLBACK(cpp_default) +{ + do_printf (out, "DEFAULT: (%s)\n", buf); + return 0; +} + +TAG_CALLBACK(cpp_error) +{ + do_printf (out,"\n"); + if (echo[ifl] && buf != NULL) { + do_printf (out, "ERROR: %s (line=%d)\n", buf, lineno); + return 1; + } + return 0; +} + +TAG_CALLBACK(cpp_warning) +{ + do_printf (out,"\n"); + if (echo[ifl] && buf != NULL) { + do_printf (out, "WARNING: line %d: %s\n", lineno, buf); + } + return 0; +} + +TAG_CALLBACK(cpp_if) +{ + char *var = getenv (buf + ((*buf == '!') ? 1 : 0)); + if (var && *var=='1') + echo[ifl + 1] = 1; + else echo[ifl + 1] = 0; + if (*buf=='!') echo[ifl+1] = !!!echo[ifl+1]; + return 1; +} + +TAG_CALLBACK(cpp_ifdef) +{ + char *var = getenv (buf); + if (var) { + echo[ifl + 1] = 1; + } else { + echo[ifl + 1] = 0; + } + return 1; +} + +TAG_CALLBACK(cpp_else) +{ + echo[ifl] = echo[ifl]?0:1; + return 0; +} + +TAG_CALLBACK(cpp_ifndef) +{ + cpp_ifdef(buf, out); + cpp_else(buf, out); + return 1; +} + +static struct cpp_macro_t { + char *name; + char *args; + char *body; +} cpp_macros[10]; +static int cpp_macros_n = 0; + +static void cpp_macro_add(char *name, char *args, char *body) +{ + char *ptr; + cpp_macros[cpp_macros_n].args = strdup(args); + cpp_macros[cpp_macros_n].body = strdup(body); + ptr = strchr(name, '('); + if (ptr) + ptr[1]='\0'; + cpp_macros[cpp_macros_n].name = strdup(name); + cpp_macros_n++; +} + +PUT_CALLBACK(cpp_fputs) +{ + int i; + for (i = 0; i < cpp_macros_n; i++) { + if (strstr(buf, cpp_macros[i].name)) { + fprintf (stderr, "MACRO (%s) HIT\n", + cpp_macros[i].name); + } + } + do_printf (out, "%s", buf); + return 0; +} + +TAG_CALLBACK(cpp_define) +{ + char *eq = strchr(buf, ' '); + if (eq) { + char *ptr = eq + 1; + char *macro = strchr(buf, '('); + *eq = '\0'; + if (macro) { + /*macro[0]='\0'; */ + ptr = strchr(macro+1, ')'); + if (ptr==NULL) { + fprintf(stderr, "Invalid syntax\n"); + return 1; + } + ptr = ptr + 1; + fprintf(stderr, "REGISTER MACRO:\n"); + fprintf(stderr, " name: %s\n", buf); + fprintf(stderr, " args: %s\n", macro); + fprintf(stderr, " body: %s\n", ptr+1); + cpp_macro_add(buf,macro,ptr+1); + /* TODO: Name is "BUF(". for funny strstr */ + } + r_sys_setenv (buf, ptr); + } else r_sys_setenv (buf, ""); + return 0; +} + +TAG_CALLBACK(cpp_endif) +{ + return -1; +} + +TAG_CALLBACK(cpp_include) +{ + if (echo[ifl]) { + spp_file (buf, out); + } + return 0; +} + +struct Tag cpp_tags[] = { + { "ifdef", cpp_ifdef }, + { "ifndef", cpp_ifndef }, + { "endif", cpp_endif }, + { "if", cpp_if }, + { "else", cpp_else }, + { "include", cpp_include }, + { "define", cpp_define }, + { "error", cpp_error }, + { "warning", cpp_warning }, + { NULL, cpp_default }, + { NULL } +}; + +/* arguments */ + +ARG_CALLBACK(cpp_arg_i) +{ + printf("INCLUDEDIR(%s)\n", arg); + return 0; +} + +ARG_CALLBACK(cpp_arg_d) +{ + // TODO: handle r_sys_setenv==-1 + char *eq = strchr(arg, '='); + if (eq) { + *eq = '\0'; + r_sys_setenv (arg, eq + 1); + } else r_sys_setenv (arg, ""); + return 0; +} + +struct Arg cpp_args[] = { + { "-I", "add include directory", 1, cpp_arg_i }, + { "-D", "define value of variable", 1, cpp_arg_d }, + { NULL } +}; + +struct Proc cpp_proc = { + .name = "cpp", + .tags = (struct Tag **)cpp_tags, + .args = (struct Arg **)cpp_args, + .token = " ", + .eof = NULL, + .tag_pre = "#", + .tag_post = "\n", + .multiline = "\\\n", + .default_echo = 1, + .fputs = cpp_fputs, + .chop = 0, + .tag_begin = 1, +}; diff --git a/shlr/spp/p/pod.h b/shlr/spp/p/pod.h new file mode 100644 index 0000000000..a5791de1c3 --- /dev/null +++ b/shlr/spp/p/pod.h @@ -0,0 +1,55 @@ +/* CPP */ + +TAG_CALLBACK(pod_default) +{ + do_printf (out, "DEFAULT: (%s)\n", buf); + return 0; +} + +TAG_CALLBACK(pod_cut) +{ + do_printf (out, "\n"); + echo[ifl] = 0; + return 0; +} + +TAG_CALLBACK(pod_head1) +{ + int i, len = strlen (buf); + echo[ifl] = 1; + do_printf (out,"\n"); + if (buf==NULL) { + return 0; + } + do_printf (out, "%s\n", buf); + for(i = 0; i < len; i++) { + do_printf (out, "%c", '='); + } + do_printf (out, "\n"); + return 0; +} + +struct Tag pod_tags[] = { + { "head1", pod_head1 }, + { "cut", pod_cut }, + { NULL, pod_default }, + { NULL } +}; + +struct Arg pod_args[] = { + { NULL } +}; + +struct Proc pod_proc = { + .name = "pod", + .tags = (struct Tag **)pod_tags, + .args = (struct Arg **)pod_args, + .token = " ", + .eof = NULL, + .tag_pre = "=", + .tag_post = "\n", + .multiline = NULL, + .default_echo = 0, + .chop = 0, + .tag_begin = 1, +}; diff --git a/shlr/spp/p/r_strbuf.h b/shlr/spp/p/r_strbuf.h new file mode 100644 index 0000000000..cfab164ac2 --- /dev/null +++ b/shlr/spp/p/r_strbuf.h @@ -0,0 +1,32 @@ +#if NO_UTIL + +#ifndef R_STRBUF_H +#define R_STRBUF_H + +#include +#include +#include +#include +#include + +typedef struct { + int len; + char *ptr; + int ptrlen; + char buf[64]; +} RStrBuf; + +#define R_FREE(x) { free(x); x = NULL; } +#define R_NEW0(x) (x*)calloc(1,sizeof(x)) + +#define R_STRBUF_SAFEGET(sb) (r_strbuf_get (sb) ? r_strbuf_get (sb) : "") +RStrBuf *r_strbuf_new(const char *s); +bool r_strbuf_set(RStrBuf *sb, const char *s); +int r_strbuf_append(RStrBuf *sb, const char *s); +char *r_strbuf_get(RStrBuf *sb); +void r_strbuf_free(RStrBuf *sb); +void r_strbuf_fini(RStrBuf *sb); +void r_strbuf_init(RStrBuf *sb); +#endif // R_STRBUF_H + +#endif // NO_UTIL \ No newline at end of file diff --git a/shlr/spp/p/sh.h b/shlr/spp/p/sh.h new file mode 100644 index 0000000000..6e224e009a --- /dev/null +++ b/shlr/spp/p/sh.h @@ -0,0 +1,87 @@ +/* SH */ + +// TODO: use popen for {{pipe/endpipe}} + +#if 0 +static char *eof = NULL; +static char *input = NULL; +#endif + +TAG_CALLBACK(sh_default) +{ + //if (out != stdout) { + // pipe stdout to out fd + //} +#if 0 + ptr = strstr(buf, "<<"); + if (ptr) { + *ptr='\0'; + for(ptr = ptr+2;*ptr==' ';ptr=ptr+1); + free(eof); + eof = strdup(ptr); + return; + } + + // printf("system(%s)\n", buf); + if (eof) +#endif + system(buf); + return 0; +} + +static int sh_pipe_enabled = 0; +static char *sh_pipe_cmd = NULL; + +TAG_CALLBACK(sh_pipe) +{ + sh_pipe_enabled = 1; + free (sh_pipe_cmd); + sh_pipe_cmd = strdup (buf); + return 0; +} + +TAG_CALLBACK(sh_endpipe) +{ + sh_pipe_enabled = 0; + free (sh_pipe_cmd); + sh_pipe_cmd = NULL; + return 0; +} + +PUT_CALLBACK(sh_fputs) +{ + if (sh_pipe_enabled) { + char str[1024]; // XXX + sprintf (str, "echo '%s' | %s", buf, sh_pipe_cmd); // XXX + system (str); + } else { + do_printf (out, "%s", buf); + } + return 0; +} + +struct Tag sh_tags[] = { + { "pipe", sh_pipe }, + { "endpipe", sh_endpipe }, + { NULL, sh_default }, + { NULL } +}; + +struct Arg sh_args[] = { + { NULL } +}; + +struct Proc sh_proc = { + .name = "sh", + .tags = (struct Tag **)sh_tags, + .args = (struct Arg **)sh_args, + .eof = NULL, + .token = NULL, + .tag_pre = "{{", + .tag_post = "}}", + .fputs = sh_fputs, + .multiline = "\\\n", + .default_echo = 1, + .chop = 0, + .tag_begin = 0, +}; diff --git a/shlr/spp/p/spp.h b/shlr/spp/p/spp.h new file mode 100644 index 0000000000..de84fe9d47 --- /dev/null +++ b/shlr/spp/p/spp.h @@ -0,0 +1,413 @@ +/* Mini MCMS :: renamed to 'spp'? */ + +static char *spp_var_get(char *var) +{ +// fprintf(stderr, "GET(%s)\n", var); + return getenv(var); +} + +static int spp_var_set(const char *var, const char *val) +{ +// fprintf(stderr, "SET(%s)(%s)\n", var, val); + return r_sys_setenv(var, val); +} + +/* Should be dynamic buffer */ +static char *cmd_to_str(const char *cmd) +{ + char *out = (char *)malloc(4096); + int ret = 0, len = 0, outlen = 4096; + FILE *fd = popen(cmd, "r"); + while(fd) { + len += ret; + ret = fread(out+len, 1, 1023, fd); + if (ret<1) { + pclose(fd); + fd = NULL; + } + if (ret+1024>outlen) { + outlen += 4096; + out = realloc (out, outlen); + } + } + out[len]='\0'; + return out; +} + +TAG_CALLBACK(spp_set) +{ + char *eq, *val = ""; + if (!echo[ifl]) return 0; + for(eq=buf;eq[0];eq++) { + switch(eq[0]) { + case '-': + case '.': + eq[0]='_'; + break; + } + } + eq = strchr(buf, ' '); + if (eq) { + *eq = '\0'; + val = eq + 1; + } + if (spp_var_set (buf, val) == -1) + fprintf (stderr, "Invalid variable name '%s' at line %d\n", buf, lineno); + return 0; +} + +TAG_CALLBACK(spp_get) +{ + char *var; + if (!echo[ifl]) return 0; + var = spp_var_get(buf); + if (var) { + do_printf (out, "%s", var); + } + return 0; +} + +TAG_CALLBACK(spp_getrandom) +{ + int max; + if (!echo[ifl]) return 0; + srandom(getpid()); // TODO: change this to be portable + max = atoi(buf); + max = (int)(rand()%max); + do_printf(out, "%d", max); + return 0; +} + +TAG_CALLBACK(spp_add) +{ + char res[32]; + char *var, *eq = strchr (buf, ' '); + int ret = 0; + if (!echo[ifl]) return 0; + if (eq) { + *eq = '\0'; + var = spp_var_get (buf); + if (var != NULL) + ret = atoi (var); + ret += atoi (eq + 1); + sprintf (res, "%d", ret); + r_sys_setenv (buf, res); + } else { /* syntax error */ } + return 0; +} + +TAG_CALLBACK(spp_sub) +{ + char *eq = strchr(buf, ' '); + char *var; + int ret = 0; + if (!echo[ifl]) return 0; + if (eq) { + *eq = '\0'; + var = spp_var_get(buf); + if (var == NULL) ret = 0; + else ret = atoi(var); + ret -= atoi(eq+1); + r_sys_setenv(buf, eq + 1); + } else { /* syntax error */ } + return 0; +} + +// XXX This method needs some love +TAG_CALLBACK(spp_trace) +{ + char b[1024]; + if (!echo[ifl]) return 0; + snprintf(b, 1023, "echo '%s' > /dev/stderr", buf); + system(b); + return 0; +} + +/* TODO: deprecate */ +TAG_CALLBACK(spp_echo) +{ + if (!echo[ifl]) return 0; + do_printf (out, "%s", buf); + // TODO: add variable replacement here?? not necessary, done by {{get}} + return 0; +} + +TAG_CALLBACK(spp_error) +{ + if (!echo[ifl]) return 0; + fprintf(stderr, "ERROR: %s (line=%d)\n", buf, lineno); + exit(1); + return 0; +} + +TAG_CALLBACK(spp_system) +{ + char *str; + if (!echo[ifl]) return 0; + str = cmd_to_str(buf); + do_printf (out, "%s", str); + free(str); + return 0; +} + +TAG_CALLBACK(spp_include) +{ + char *incdir; + if (!echo[ifl]) return 0; + incdir = getenv("SPP_INCDIR"); + if (incdir) { + char *b = strdup(incdir); + b = realloc(b, strlen(b)+strlen(buf)+3); + strcat(b, "/"); + strcat(b, buf); + spp_file(b, out); + } else spp_file(buf, out); + return 0; +} + +TAG_CALLBACK(spp_if) +{ + char *var = spp_var_get(buf); + if (var && *var!='0' && *var != '\0') + echo[ifl+1] = 1; + else echo[ifl+1] = 0; + return 1; +} + +/* {{ ifeq $path / }} */ +TAG_CALLBACK(spp_ifeq) +{ + char *value = buf; + char *eq = strchr(buf, ' '); + if (eq) { + *eq = '\0'; + value = spp_var_get(value); + if (value && !strcmp(value, eq+1)) { + echo[ifl+1] = 1; + } else echo[ifl+1] = 0; +//fprintf(stderr, "IFEQ(%s)(%s)=%d\n", buf, eq+1, echo[ifl]); + } else { + value = spp_var_get(buf); + if (value==NULL || *value=='\0') + echo[ifl+1] = 1; + else echo[ifl+1] = 0; +//fprintf(stderr, "IFEQ(%s)(%s)=%d\n", buf, value, echo[ifl]); + } + return 1; +} + +TAG_CALLBACK(spp_hex) +{ + int i; + for(i = 0; buf[i]; i++) { + if (buf[i] >= '0' && buf[i] <= '9') { + int b; + unsigned int ch; + b = buf[i + 2]; + buf[i + 2] = '\0'; + sscanf(buf + i, "%02x", &ch); + do_printf (out, "%c", ch); + buf[i + 2] = b; + buf = buf + 2; + } + } + return 0; +} + +TAG_CALLBACK(spp_grepline) +{ + FILE *fd; + char b[1024]; + char *ptr; + int line; + + if (!echo[ifl]) return 1; + ptr = strchr(buf, ' '); + if (ptr) { + *ptr= '\0'; + fd = fopen (buf, "r"); + line = atoi (ptr+1); + if (fd) { + while (!feof (fd) && line--) + fgets(b, 1023, fd); + fclose (fd); + do_printf (out, "%s", b); + } else { + fprintf(stderr, "Unable to open '%s'\n", buf); + } + } + return 0; +} + +TAG_CALLBACK(spp_else) +{ + echo[ifl] = echo[ifl] ? 0 : 1; + return 0; +} + +TAG_CALLBACK(spp_ifnot) +{ + spp_if (buf, out); + spp_else (buf, out); + return 1; +} + +TAG_CALLBACK(spp_ifin) +{ + char *var, *ptr; + if (!echo[ifl]) return 1; + ptr = strchr (buf, ' '); + echo[ifl + 1] = 0; + if (ptr) { + *ptr='\0'; + var = getenv(buf); + if (strstr (ptr + 1, var)) { + echo[ifl + 1] = 1; + } + } + return 1; +} + +TAG_CALLBACK(spp_endif) +{ + return -1; +} + +TAG_CALLBACK(spp_default) +{ + if (!echo[ifl]) return 0; + if (buf[-1] != ';') /* commented tag */ + fprintf (stderr, "WARNING: invalid command(%s) at line %d\n", buf, lineno); + return 0; +} + +static FILE *spp_pipe_fd = NULL; + +TAG_CALLBACK(spp_pipe) +{ + spp_pipe_fd = popen (buf, "w"); + return 0; +} + +static char *spp_switch_str = NULL; + +TAG_CALLBACK(spp_switch) +{ + char *var = spp_var_get (buf); + if (var) + spp_switch_str = strdup (var); + else spp_switch_str = strdup (""); + return 1; +} + +TAG_CALLBACK(spp_case) +{ + echo[ifl] = strcmp (buf, spp_switch_str)?0:1; + return 0; +} + +TAG_CALLBACK(spp_endswitch) +{ + free (spp_switch_str); + spp_switch_str = NULL; + return -1; +} + +TAG_CALLBACK(spp_endpipe) +{ + /* TODO: Get output here */ + int ret = 0, len = 0; + int outlen = 4096; + char *str = (char *)malloc (4096); + do { + len += ret; + ret = fread (str + len, 1, 1023, spp_pipe_fd); + if (ret + 1024 > outlen) { + outlen += 4096; + str = realloc (str, outlen); + } + } while (ret > 0); + str[len] = '\0'; + do_printf (out, "%s", str); + if (spp_pipe_fd) { + pclose (spp_pipe_fd); + } + spp_pipe_fd = NULL; + return 0; +} + +PUT_CALLBACK(spp_fputs) +{ + if (spp_pipe_fd) { + fprintf (spp_pipe_fd, "%s", buf); + } else { + do_printf (out, "%s", buf); + } + return 0; +} + +struct Tag spp_tags[] = { + { "get", spp_get }, + { "hex", spp_hex }, + { "getrandom", spp_getrandom }, + { "grepline", spp_grepline }, + { "set", spp_set }, + { "add", spp_add }, + { "sub", spp_sub }, + { "switch", spp_switch }, + { "case", spp_case }, + { "endswitch", spp_endswitch }, + { "echo", spp_echo }, + { "error", spp_error }, + { "trace", spp_trace }, + { "ifin", spp_ifin }, + { "ifnot", spp_ifnot }, + { "ifeq", spp_ifeq }, + { "if", spp_if }, + { "else", spp_else }, + { "endif", spp_endif }, + { "pipe", spp_pipe }, + { "endpipe", spp_endpipe }, + { "include", spp_include }, + { "system", spp_system }, + { NULL, spp_default }, + { NULL } +}; + +ARG_CALLBACK(spp_arg_i) +{ + r_sys_setenv ("SPP_INCDIR", arg); + return 0; +} + +ARG_CALLBACK(spp_arg_d) +{ + /* TODO: Handle error */ + char *eq = strchr (arg, '='); + if (eq) { + *eq = '\0'; + spp_var_set (arg, eq+1); + } else spp_var_set (arg, ""); + return 0; +} + +struct Arg spp_args[] = { + { "-I", "add include directory", 1, spp_arg_i }, + { "-D", "define value of variable", 1, spp_arg_d }, + { NULL } +}; + +struct Proc spp_proc = { + .name = "spp", + .tags = (struct Tag **)spp_tags, + .args = (struct Arg **)spp_args, + .token = " ", + .eof = NULL, + .tag_pre = "<{", + .tag_post = "}>", + .chop = 1, + .fputs = spp_fputs, + .multiline = NULL, + .default_echo = 1, + .tag_begin = 0, +}; diff --git a/shlr/spp/p/strbuf.c b/shlr/spp/p/strbuf.c new file mode 100644 index 0000000000..d7af06c1df --- /dev/null +++ b/shlr/spp/p/strbuf.c @@ -0,0 +1,89 @@ +/* radare - LGPL - Copyright 2013-2014 - pancake */ +#if NO_UTIL + +#include "r_strbuf.h" + + +RStrBuf *r_strbuf_new(const char *str) { + RStrBuf *s = R_NEW0 (RStrBuf); + if (str) r_strbuf_set (s, str); + return s; +} + +void r_strbuf_init(RStrBuf *sb) { + memset (sb, 0, sizeof (RStrBuf)); +} + +bool r_strbuf_set(RStrBuf *sb, const char *s) { + int l; + if (!sb) return false; + if (!s) { + r_strbuf_init (sb); + return true; + } + l = strlen (s); + if (l >= sizeof (sb->buf)) { + char *ptr = sb->ptr; + if (!ptr || l+1 > sb->ptrlen) { + ptr = malloc (l + 1); + if (!ptr) return false; + sb->ptrlen = l + 1; + sb->ptr = ptr; + } + memcpy (ptr, s, l+1); + } else { + sb->ptr = NULL; + memcpy (sb->buf, s, l+1); + } + sb->len = l; + return true; +} + +int r_strbuf_append(RStrBuf *sb, const char *s) { + int l = strlen (s); + if (l < 1) { + return false; + } + if ((sb->len + l + 1) < sizeof (sb->buf)) { + memcpy (sb->buf + sb->len, s, l + 1); + R_FREE (sb->ptr); + } else { + int newlen = sb->len + l + 128; + char *p = sb->ptr; + bool allocated = true; + if (!sb->ptr) { + p = malloc (newlen); + if (p && sb->len > 0) { + memcpy (p, sb->buf, sb->len); + } + } else if (sb->len + l + 1 > sb->ptrlen) { + p = realloc (sb->ptr, newlen); + } else { + allocated = false; + } + if (allocated) { + if (!p) return false; + sb->ptr = p; + sb->ptrlen = newlen; + } + memcpy (p + sb->len, s, l + 1); + } + sb->len += l; + return true; +} + +char *r_strbuf_get(RStrBuf *sb) { + return sb? (sb->ptr? sb->ptr: sb->buf) : NULL; +} + +void r_strbuf_free(RStrBuf *sb) { + r_strbuf_fini (sb); + free (sb); +} + +void r_strbuf_fini(RStrBuf *sb) { + if (sb && sb->ptr) + R_FREE (sb->ptr); +} + +#endif // NO_UTIL \ No newline at end of file diff --git a/shlr/spp/spp.c b/shlr/spp/spp.c new file mode 100644 index 0000000000..44c1197a08 --- /dev/null +++ b/shlr/spp/spp.c @@ -0,0 +1,356 @@ +/* MIT (C) pancake (at) nopcode (dot) org */ + +#include "spp.h" +#include "config.h" + +char *lbuf = NULL; +int lbuf_s = 1024; +int lbuf_n = 0; +int incmd = 0; +int lineno = 1; +int printed = 0; +char *tag_pre, *tag_post, *token; +int tag_begin, echo[MAXIFL]; +int ifl = 0; /* conditional nest level */ + + +void spp_run(char *buf, Output *out) { + int i, ret; + char *tok; + + D fprintf(stderr, "SPP_RUN(%s)\n", buf); + if (proc->chop) { + for (; IS_SPACE (*buf); buf++); + for (tok = buf + strlen(buf) - 1; IS_SPACE (*tok); tok--) { + *tok='\0'; + } + } + + if (token) { + tok = strstr (buf, token); + if (tok) { + *tok = '\0'; + tok = tok + 1; + } else { + tok = buf; + } + } else { + tok = buf; + } + for (i = 0; tags[i].callback; i++) { + D fprintf (stderr, "NAME=(%s)\n", tok); + if ((tags[i].name == NULL) || (!strcmp (buf, tags[i].name))) { + if (out->fout) { + fflush (out->fout); + } + ret = tags[i].callback (tok, out); + if (ret) { + ifl += ret; + if (ifl < 0 || ifl >= MAXIFL) { + fprintf (stderr, "Nested conditionals parsing error.\n"); + return; + } + } + break; + } + } +} + +/* XXX : Do not dump to temporally files!! */ +char *spp_run_str(char *buf) { + char *b; + Output tmp; + tmp.fout = NULL; + tmp.cout = r_strbuf_new(""); + spp_run (buf, &tmp); + b = strdup (r_strbuf_get (tmp.cout)); + r_strbuf_free (tmp.cout); + return b; +} + +void lbuf_strcat(char *dst, char *src) { + int len = strlen (src); + if ((len + lbuf_n) > lbuf_s) + lbuf = realloc (lbuf, lbuf_s << 1); + memcpy (lbuf + lbuf_n, src, len + 1); + lbuf_n += len; +} + +void do_printf(Output *out, char *str, ...) { + va_list ap; + va_start (ap, str); + if (out->fout) { + vfprintf (out->fout, str, ap); + } else { + char tmp[4096]; + vsnprintf (tmp, sizeof (tmp), str, ap); + r_strbuf_append (out->cout, tmp); + } + va_end(ap); +} + +#if NO_UTIL +int r_sys_setenv(const char *key, const char *value) { +#if __UNIX__ || __CYGWIN__ && !defined(MINGW32) + if (!key) { + return 0; + } + if (!value) { + unsetenv (key); + return 0; + } + return setenv (key, value, 1); +#elif __WINDOWS__ + SetEnvironmentVariable (key, (LPSTR)value); + return 0; // TODO. get ret +#else +#warning r_sys_setenv : unimplemented for this platform + return 0; +#endif +} +#endif + +void do_fputs(Output *out, char *str) { + int i; + for (i = 0;i <= ifl; i++) { + if (!echo[i]) { + return; + } + } + if (str[0]) { + printed = 1; + } + if (proc->fputs) { + proc->fputs (out, str); + } + else { + if (out->fout) { + fprintf (out->fout, "%s", str); + } + } +} + +void spp_eval(char *buf, Output *out) { + char *ptr, *ptr2; + char *ptrr = NULL; + int delta; + + printed = 0; +retry: + /* per word */ + if (tag_pre == NULL) { + do { + ptr = strstr (buf, token); + if (ptr) { + *ptr = '\0'; + } + delta = strlen (buf) - 1; + if (buf[delta] == '\n') { + buf[delta] = '\0'; + } + if (*buf) { + spp_run (buf, out); + } + buf = ptr + 1; + } while (ptr); + return; + } + + if (tag_post == NULL) { + /* handle per line here ? */ + return; + } + + // TODO: do it in scope! + delta = strlen (tag_post); + + /* (pre) tag */ + if (!buf) { + return; + } + ptr = strstr (buf, tag_pre); + if (ptr) { + D printf ("==> 0.0 (%s)\n", ptr); + incmd = 1; + if (!tag_begin || (tag_begin && ptr == buf)) { + *ptr = '\0'; + ptr = ptr + strlen (tag_pre);; + do_fputs (out, buf); + D printf ("==> 0 (%s)\n", ptr); + } + ptrr = strstr (ptr + strlen (tag_pre), tag_pre); + } + + /* (post) tag */ + if (!ptr) { + do_fputs (out, buf); + return; + } else { + ptr2 = strstr (ptr, tag_post); + } + if (ptr2) { + *ptr2 = '\0'; + if (ptrr) { + if (ptrr < ptr2) { + char *p = strdup (ptr2 + 2); + char *s = spp_run_str (ptrr + strlen (tag_pre)); + D fprintf(stderr, "strcpy(%s)(%s)\n",ptrr, s); + strcpy(ptrr, s); + free(s); + ptr[-2] = tag_pre[0]; // XXX -2 check underflow? + + D fprintf(stderr, "strcat(%s)(%s)\n",ptrr, p); + strcat(ptrr, p); + buf = ptr-2; + D fprintf(stderr, "CONTINUE (%s)\n", buf); + ptrr = NULL; + goto retry; + } + } + incmd = 0; + if (lbuf && lbuf[0]) { + D printf("==> 1 (%s)\n", lbuf); + if (ptr) { + lbuf_strcat (lbuf, buf); + do_fputs (out, lbuf); + spp_run (ptr, out); + } else { + lbuf_strcat (lbuf, buf); + D printf ("=(1)=> spp_run(%s)\n", lbuf); + spp_run (lbuf+delta, out); + D printf ("=(1)=> spp_run(%s)\n", lbuf); + } + lbuf[0]='\0'; + lbuf_n = 0; + } else { + D printf ("==> 2 (%s)\n", ptr); + if (ptr) { + D printf (" ==> 2.1: run(%s)\n", ptr); + spp_run (ptr, out); + buf = ptr2 + delta; + if (buf[0] == '\n' && printed) { + buf++; + } + D printf (" ==> 2.1: continue(%s)\n", ptr2 + delta); + goto retry; + } else { + do_fputs (out, "\n"); + } + } + do_fputs (out, ptr2 + delta); + } else { + D printf ("==> 3\n"); + if (ptr) { + lbuf_strcat (lbuf, ptr); + } else { + if (lbuf == NULL) { + // XXX should never happen + fprintf (stderr, "syntax error?\n"); + return; + } + if (buf[0]) { + if (incmd) { + lbuf_strcat (lbuf, buf); + } + else { + do_fputs (out, buf); + } + } else { + do_fputs (out, buf); + } + } + } +} + +/* TODO: detect nesting */ +void spp_io(FILE *in, Output *out) { + char buf[4096]; + int lines; + if (lbuf == NULL) { + lbuf = malloc (4096); + } + if (lbuf == NULL) { + fprintf (stderr, "Out of memory.\n"); + return; + } + lbuf[0]='\0'; + while(!feof(in)) { + buf[0]='\0'; // ??? + fgets (buf, 1023, in); + if (feof (in)) break; + lines = 1; + if (!memcmp (buf, "#!", 2)) { + fgets (buf, 1023, in); + if (feof (in)) break; + lines++; + } + if (proc->multiline) { + while (1) { + char *eol = buf + strlen (buf) - strlen (proc->multiline); + if (!strcmp (eol, proc->multiline)) { + D fprintf(stderr, "Multiline detected!\n"); + fgets (eol, 1023, in); + if (feof(in)) break; + lines++; + } else break; + } + } + spp_eval (buf, out); + lineno += lines; + } + do_fputs (out, lbuf); +} + +int spp_file(const char *file, Output *out) { + FILE *in = fopen (file, "r"); + D fprintf(stderr, "SPP-FILE(%s)\n", file); + if (in) { + spp_io (in, out); + fclose (in); + return 1; + } else fprintf (stderr, "Cannot find '%s'\n", file); + return 0; +} + +void spp_proc_list_kw() { + int i; + for (i = 0; tags[i].name; i++) + printf ("%s\n", tags[i].name); +} + +void spp_proc_list() { + int i; + for (i=0;procs[i];i++) { + printf ("%s\n", procs[i]->name); + } +} + +void spp_proc_set(struct Proc *p, char *arg, int fail) { + int i, j; + if (arg) + for (j = 0; procs[j]; j++) { + if (!strcmp (procs[j]->name, arg)) { + proc = procs[j]; + D printf ("SET PROC:(%s)(%s)\n", arg, proc->name); + break; + } + } + if (arg && *arg && !procs[j] && fail) { + fprintf (stderr, "Invalid preprocessor name '%s'\n", arg); + return; + } + if (proc == NULL) + proc = p; + + if (proc != NULL) { + // TODO: wtf! + tag_pre = proc->tag_pre; + tag_post = proc->tag_post; + for (i = 0; i < MAXIFL; i++) + echo[i] = proc->default_echo; + token = proc->token; + tag_begin = proc->tag_begin; + args = (struct Arg*)proc->args; + tags = (struct Tag*)proc->tags; + } +} diff --git a/shlr/spp/spp.h b/shlr/spp/spp.h new file mode 100644 index 0000000000..1d2349bf3a --- /dev/null +++ b/shlr/spp/spp.h @@ -0,0 +1,95 @@ +#ifndef _INCLUDE_SPP_H_ +#define _INCLUDE_SPP_H_ + +#include +#include +#include +#include +#if NO_UTIL +#include "p/r_strbuf.h" +int r_sys_setenv(const char *key, const char *value); +#else +#include +#endif + +#ifdef __WINDOWS__ +#include +#define popen _popen +#define pclose _pclose +#define srandom srand +#define snprintf _snprintf +#endif + +#define VERSION "1.0" + +#define MAXIFL 128 + +extern int ifl; +extern int echo[MAXIFL]; +extern int lineno; + +#define GET_ARG(x,y,i) if (y[i][2]) x = y[i] + 2; else x = y[++i] + +#define DEFAULT_PROC(x) \ +struct Tag *tags = (struct Tag *)&x##_tags; \ +struct Arg *args = (struct Arg *)&x##_args; \ +struct Proc *proc = &x##_proc; + +typedef struct { + RStrBuf *cout; + FILE *fout; + int size; +} Output; + +#define ARG_CALLBACK(x) int x (char *arg) +/* XXX swap arguments ?? */ +#define TAG_CALLBACK(x) int x (char *buf, Output *out) +#define PUT_CALLBACK(x) int x (Output *out, char *buf) +#define IS_SPACE(x) ((x==' ')||(x=='\t')||(x=='\r')||(x=='\n')) + +struct Tag { + const char *name; + TAG_CALLBACK((*callback)); +}; + +struct Arg { + const char *flag; + const char *desc; + int has_arg; + ARG_CALLBACK((*callback)); +}; + +struct Proc { + const char *name; + struct Tag **tags; + struct Arg **args; + TAG_CALLBACK ((*eof)); + PUT_CALLBACK ((*fputs)); + char *tag_pre; + char *tag_post; + char *token; + char *multiline; + int chop; + int tag_begin; + int default_echo; +}; + + + +int spp_file(const char *file, Output *out); +void spp_run(char *buf, Output *out); +void spp_eval(char *buf, Output *out); +void spp_io(FILE *in, Output *out); +void do_printf(Output *out, char *str, ...) __attribute__ ((format (printf, 2, 3))); + +void spp_proc_list(); +void spp_proc_list_kw(); +void spp_proc_set(struct Proc *p, char *arg, int fail); + +#if DEBUG +#define D if (1) +#else +#define D if (0) +#endif + +#endif diff --git a/shlr/spp/t/asminc b/shlr/spp/t/asminc new file mode 100644 index 0000000000..34af12d8ce --- /dev/null +++ b/shlr/spp/t/asminc @@ -0,0 +1 @@ +mov eax, 0x44 diff --git a/shlr/spp/t/hello.acr b/shlr/spp/t/hello.acr new file mode 100644 index 0000000000..e0884c551e --- /dev/null +++ b/shlr/spp/t/hello.acr @@ -0,0 +1,5 @@ +PKGNAME spp +VERSION 0.1 +CONTACT pancake ; pancake@nopcode.org + +LANG_C diff --git a/shlr/spp/t/hello.asm b/shlr/spp/t/hello.asm new file mode 100644 index 0000000000..faed543bd7 --- /dev/null +++ b/shlr/spp/t/hello.asm @@ -0,0 +1,2 @@ +.include t/asminc +add eax, 0x1 diff --git a/shlr/spp/t/hello.cpp b/shlr/spp/t/hello.cpp new file mode 100644 index 0000000000..927db03826 --- /dev/null +++ b/shlr/spp/t/hello.cpp @@ -0,0 +1,34 @@ + +This is a hello cpp world + +#include t/hello2.cpp + +#define visible 1 +#if visible +This text is visible +#endif + +#if !visible +This text is not visible +#endif + +#ifdef SECRET + + UG + BUGB B GBUG + UG G BU + BUGBUGBUGBU + BUG BUGBUGBUGBUGBUGBUG + BUGBUGBUGBUGBUGBUGBUGBUG + BUGBUGBUGBUGBUGBUGBUGBUG + BUG BUGBUGBUGBUGBUGBUG + BUGBUGBUGBU + UG G BU + BUGB B GBUG + UG + +#endif + +#error Oops + +this will not be visible diff --git a/shlr/spp/t/hello.pod b/shlr/spp/t/hello.pod new file mode 100644 index 0000000000..df347879c9 --- /dev/null +++ b/shlr/spp/t/hello.pod @@ -0,0 +1,10 @@ +This is a pod file + +=head1 Title of the article + +this really rocks +OMG this is another line + +=cut + +fuck :) diff --git a/shlr/spp/t/hello.sh b/shlr/spp/t/hello.sh new file mode 100644 index 0000000000..27a34fb99e --- /dev/null +++ b/shlr/spp/t/hello.sh @@ -0,0 +1,9 @@ +hello {{echo world}} + +This is a multiline test {{\ +\ +for a in hello world ; do\ + echo $a ;\ +done\ +\ +}} diff --git a/shlr/spp/t/hello.spp b/shlr/spp/t/hello.spp new file mode 100644 index 0000000000..9c22cd8264 --- /dev/null +++ b/shlr/spp/t/hello.spp @@ -0,0 +1,17 @@ + --- +<{ set arch x86-32 }> + +hello <{echo world}> +path=<{system echo $PATH}> +arch = <{ get arch }> + +<{ ifeq arch x86-32 }> +FOO IS ENABLED +<{ endif }> + +<{ pipe perl -ne 's/World/Stupid/g;print;' }> +Hello World +<{ endpipe }> + --- + +Hello <{echo world <{echo :D}> ==}>--> diff --git a/shlr/spp/t/hello2.cpp b/shlr/spp/t/hello2.cpp new file mode 100644 index 0000000000..631178d8f3 --- /dev/null +++ b/shlr/spp/t/hello2.cpp @@ -0,0 +1 @@ +This message is from hello2.cpp diff --git a/shlr/spp/t/hex.spp b/shlr/spp/t/hex.spp new file mode 100644 index 0000000000..f579da26e0 --- /dev/null +++ b/shlr/spp/t/hex.spp @@ -0,0 +1,3 @@ +Binary: <{hex 41 42 43}> +<{set line 34}> +GrepLine: <{grepline /etc/services <{get line}>}> diff --git a/shlr/spp/t/macro.cpp b/shlr/spp/t/macro.cpp new file mode 100644 index 0000000000..8ec52164d5 --- /dev/null +++ b/shlr/spp/t/macro.cpp @@ -0,0 +1,7 @@ +#define FOO 1 +#define MAX(x,y) (x>y)?x:y + +main() +{ + printf("%d\n", MAX(3,10)); +} diff --git a/shlr/spp/t/multi.cpp b/shlr/spp/t/multi.cpp new file mode 100644 index 0000000000..244ce15fd7 --- /dev/null +++ b/shlr/spp/t/multi.cpp @@ -0,0 +1,5 @@ +#define FOO \ + Hello \ + World + +FOO diff --git a/shlr/spp/t/multi.sh b/shlr/spp/t/multi.sh new file mode 100644 index 0000000000..bc5c111be0 --- /dev/null +++ b/shlr/spp/t/multi.sh @@ -0,0 +1,2 @@ +{{ for a in hello \ +world; do echo $a; done }} diff --git a/shlr/spp/t/multiline.cpp b/shlr/spp/t/multiline.cpp new file mode 100644 index 0000000000..2cdfb30f65 --- /dev/null +++ b/shlr/spp/t/multiline.cpp @@ -0,0 +1,2 @@ +#define FOO hello \ +world diff --git a/shlr/spp/t/nest.cpp b/shlr/spp/t/nest.cpp new file mode 100644 index 0000000000..197e109eee --- /dev/null +++ b/shlr/spp/t/nest.cpp @@ -0,0 +1,12 @@ +#define ONE 1 +#define TWO 0 + +#if ONE + +HELLO WORLD +#if TWO +BUG: Nested conditionals +#endif + +THIS IS NICE +#endif diff --git a/shlr/spp/t/nest.spp b/shlr/spp/t/nest.spp new file mode 100644 index 0000000000..794cac03de --- /dev/null +++ b/shlr/spp/t/nest.spp @@ -0,0 +1,46 @@ +Hello <{echo world <{echo :D}> ==}>--> + +<{set a secret message}> +<{system echo $a}> +<{ifeq a <{get a}>}> /* always true */ + <{set var <{get PATH}>}> + Path is <{get var}> + Path is <{get PATH}> + Path is <{system echo $var}> + <{echo Path is <{get PATH}>}> +<{endif}> + +<{set yes 1}> +<{set no 0}> + +<{if yes}> + 1 INNER VISIBLE TEXT + <{if no}> + 2 BUG: INVISIBLE TEXT + <{if no}> + BUG fuck + <{if yes}> + BUG TRAP + <{endif}> + BUG fuck + <{endif}> + BUG: no one loves me + <{endif}> + <{if yes}> + HELLO WORLD + <{endif}> + 3 INNER VISIBLE TEXT +<{endif}> + +VISIBLE TEXT + +<{if yes}> + YES DO IT +<{endif}> + +<{if no}> + <{if yes}> + BUG: THIS IS A TRAP + <{endif}> + BUG: NO DONT DO IT +<{endif}> diff --git a/shlr/spp/t/nest2.spp b/shlr/spp/t/nest2.spp new file mode 100644 index 0000000000..0eba19b53e --- /dev/null +++ b/shlr/spp/t/nest2.spp @@ -0,0 +1,22 @@ +<{set foo 2}> +<{set bar 3}> + +<{ifeq foo 3}> +BUG 1 +<{ifeq bar 4}> +BUG 2 +<{else}> +BUG 3 +<{endif}> +BUG 4 +<{endif}> + +<{ifeq foo 2}> +Fine! +<{ifeq bar 3}> +Perfect +<{else}> +BUG 5 +<{endif}> +Cool :D +<{endif}> diff --git a/shlr/spp/t/nest3.spp b/shlr/spp/t/nest3.spp new file mode 100644 index 0000000000..f096c9af3f --- /dev/null +++ b/shlr/spp/t/nest3.spp @@ -0,0 +1,12 @@ +<{set foo 2}> +<{set bar 2}> + +<{ifeq foo 3}> + BUG 1 + <{switch bar}> + <{case 1}> + BUG 2 + <{case 3}> + BUG 3 + <{endswitch}> +<{endif}> diff --git a/shlr/spp/t/oneliner.spp b/shlr/spp/t/oneliner.spp new file mode 100644 index 0000000000..6983e057ac --- /dev/null +++ b/shlr/spp/t/oneliner.spp @@ -0,0 +1 @@ +<{set var 1}><{ifeq var 1}>its true<{else}>BUG: false conditional check in oneliner ifeq<{endif}> diff --git a/shlr/spp/t/random.spp b/shlr/spp/t/random.spp new file mode 100644 index 0000000000..d347fb9c3a --- /dev/null +++ b/shlr/spp/t/random.spp @@ -0,0 +1,10 @@ +<{set var <{getrandom 2}>}> + +Value: <{get var}> +<{ifeq var 0}> + Zero value +<{endif}> + +<{ifeq var 1}> + One value +<{endif}> diff --git a/shlr/spp/t/spp.cgi b/shlr/spp/t/spp.cgi new file mode 100755 index 0000000000..ac25fa79d7 --- /dev/null +++ b/shlr/spp/t/spp.cgi @@ -0,0 +1,32 @@ +#!/usr/bin/spp +Content-Type: text/html +Status: 200 OK + + + + radare + + + + +Hello <{system echo beep }> +
+hello <{system echo world}> + + +<{switch QUERY_STRING}> +<{case foo}> + foo +<{case bar}> + bar +<{endswitch}> + +<{ifeq QUERY_STRING foo}> + go back
+<{else}> + click here
+<{endif}> + +
+<{system export | perl -ne 's/\n/
/ ;print'}> +