Rizin
unix-like reverse engineering framework and cli tools
lang.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2018 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "config.h"
5 #include <rz_lang.h>
6 #include <rz_util.h>
7 #include <rz_cons.h>
8 
9 RZ_LIB_VERSION(rz_lang);
10 
12 static RzLang *__lang = NULL;
13 
15  if (p && p->fini) {
16  p->fini(__lang);
17  }
18 }
19 
21  RzLang *lang = RZ_NEW0(RzLang);
22  if (!lang) {
23  return NULL;
24  }
25  lang->user = NULL;
26  lang->langs = rz_list_new();
27  if (!lang->langs) {
28  rz_lang_free(lang);
29  return NULL;
30  }
32  lang->defs = rz_list_new();
33  if (!lang->defs) {
34  rz_lang_free(lang);
35  return NULL;
36  }
39  for (int i = 0; i < RZ_ARRAY_SIZE(lang_static_plugins); i++) {
41  }
42 
43  return lang;
44 }
45 
46 RZ_API void rz_lang_free(RzLang *lang) {
47  if (lang) {
48  __lang = NULL;
49  rz_lang_undef(lang, NULL);
50  rz_list_free(lang->langs);
51  rz_list_free(lang->defs);
52  // TODO: remove langs plugins
53  free(lang);
54  }
55 }
56 
57 // XXX: This is only used actually to pass 'core' structure
58 // TODO: when language bindings are done we will need an api to
59 // define symbols from C to the language namespace
60 // XXX: Depcreate!!
61 RZ_API void rz_lang_set_user_ptr(RzLang *lang, void *user) {
62  lang->user = user;
63 }
64 
65 RZ_API bool rz_lang_define(RzLang *lang, const char *type, const char *name, void *value) {
66  RzLangDef *def;
68  rz_list_foreach (lang->defs, iter, def) {
69  if (!rz_str_casecmp(name, def->name)) {
70  def->value = value;
71  return true;
72  }
73  }
75  if (!def) {
76  return false;
77  }
78  def->type = strdup(type);
79  def->name = strdup(name);
80  def->value = value;
81  rz_list_append(lang->defs, def);
82  return true;
83 }
84 
86  free(def->name);
87  free(def->type);
88  free(def);
89 }
90 
91 RZ_API void rz_lang_undef(RzLang *lang, const char *name) {
92  if (name && *name) {
93  RzLangDef *def;
95  /* No _safe loop necessary because we return immediately after the delete. */
96  rz_list_foreach (lang->defs, iter, def) {
97  if (!name || !rz_str_casecmp(name, def->name)) {
98  rz_list_delete(lang->defs, iter);
99  break;
100  }
101  }
102  } else {
103  rz_list_free(lang->defs);
104  lang->defs = NULL;
105  }
106 }
107 
109  if (lang && lang->cur && lang->cur->setup) {
110  return lang->cur->setup(lang);
111  }
112  return false;
113 }
114 
116  if (foo && (!rz_lang_get_by_name(lang, foo->name))) {
117  if (foo->init) {
118  foo->init(lang);
119  }
120  rz_list_append(lang->langs, foo);
121  return true;
122  }
123  return false;
124 }
125 
127  RzListIter *iter;
128  RzLangPlugin *h;
129  const char *p = rz_str_lchr(ext, '.');
130  if (p) {
131  ext = p + 1;
132  }
133  rz_list_foreach (lang->langs, iter, h) {
134  if (!rz_str_casecmp(h->ext, ext)) {
135  return h;
136  }
137  }
138  return NULL;
139 }
140 
142  RzListIter *iter;
143  RzLangPlugin *h;
144  rz_list_foreach (lang->langs, iter, h) {
145  if (!rz_str_casecmp(h->name, name)) {
146  return h;
147  }
148  if (h->alias && !rz_str_casecmp(h->alias, name)) {
149  return h;
150  }
151  }
152  return NULL;
153 }
154 
155 RZ_API bool rz_lang_use(RzLang *lang, const char *name) {
157  if (h) {
158  lang->cur = h;
159  return true;
160  }
161  return false;
162 }
163 
164 // TODO: store in rz_lang and use it from the plugin?
165 RZ_API bool rz_lang_set_argv(RzLang *lang, int argc, char **argv) {
166  if (lang->cur && lang->cur->set_argv) {
167  return lang->cur->set_argv(lang, argc, argv);
168  }
169  return false;
170 }
171 
172 RZ_API int rz_lang_run(RzLang *lang, const char *code, int len) {
173  if (lang->cur && lang->cur->run) {
174  return lang->cur->run(lang, code, len);
175  }
176  return false;
177 }
178 
179 RZ_API int rz_lang_run_string(RzLang *lang, const char *code) {
180  return rz_lang_run(lang, code, strlen(code));
181 }
182 
183 RZ_API int rz_lang_run_file(RzLang *lang, const char *file) {
184  int ret = false;
185  if (lang->cur) {
186  if (!lang->cur->run_file) {
187  if (lang->cur->run) {
188  size_t len;
189  char *code = rz_file_slurp(file, &len);
190  if (!code) {
191  eprintf("Could not open '%s'.\n", file);
192  return 0;
193  }
194  ret = lang->cur->run(lang, code, (int)len);
195  free(code);
196  }
197  } else {
198  ret = lang->cur->run_file(lang, file);
199  }
200  }
201  return ret;
202 }
203 
204 /* TODO: deprecate or make it more modular .. reading from stdin in a lib! */
206  char buf[1024];
207  const char *p;
208 
209  if (!lang || !lang->cur) {
210  return false;
211  }
212 
213  if (lang->cur->prompt && lang->cur->prompt(lang)) {
214  return true;
215  }
216  /* init line */
218  RzLineHistory hist = line->history;
219  RzLineHistory histnull = { 0 };
220  RzLineCompletion oc = line->completion;
221  RzLineCompletion ocnull = { 0 };
222  char *prompt = strdup(line->prompt);
223  line->completion = ocnull;
224  line->history = histnull;
225 
226  /* foo */
227  for (;;) {
228  rz_cons_flush();
229  snprintf(buf, sizeof(buf) - 1, "%s> ", lang->cur->name);
231  p = rz_line_readline();
232  if (!p) {
233  break;
234  }
236  strncpy(buf, p, sizeof(buf) - 1);
237  if (*buf == '!') {
238  if (buf[1]) {
239  rz_sys_xsystem(buf + 1);
240  }
241  continue;
242  }
243  if (!memcmp(buf, ". ", 2)) {
244  char *file = rz_file_abspath(buf + 2);
245  if (file) {
246  rz_lang_run_file(lang, file);
247  free(file);
248  }
249  continue;
250  }
251  if (!strcmp(buf, "q")) {
252  free(prompt);
253  return true;
254  }
255  if (!strcmp(buf, "?")) {
256  RzLangDef *def;
257  RzListIter *iter;
258  eprintf(" ? - show this help message\n"
259  " !command - run system command\n"
260  " . file - interpret file\n"
261  " q - quit prompt\n");
262  eprintf("%s example:\n", lang->cur->name);
263  if (lang->cur->help) {
264  eprintf("%s", *lang->cur->help);
265  }
266  if (!rz_list_empty(lang->defs)) {
267  eprintf("variables:\n");
268  }
269  rz_list_foreach (lang->defs, iter, def) {
270  eprintf(" %s %s\n", def->type, def->name);
271  }
272  } else {
273  rz_lang_run(lang, buf, strlen(buf));
274  }
275  }
276  // XXX: leaking history
278  line->completion = oc;
279  line->history = hist;
280  clearerr(stdin);
281  printf("\n");
282  free(prompt);
283  return true;
284 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
static const char ext[]
Definition: apprentice.c:1981
#define RZ_LANG_STATIC_PLUGINS
Definition: config.h:24
static int value
Definition: cmd_api.c:93
RZ_API void rz_cons_flush(void)
Definition: cons.c:959
#define RZ_API
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
RZ_API const char * rz_line_readline(void)
Definition: dietline.c:913
RZ_API int rz_line_hist_add(const char *line)
Definition: dietline.c:382
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
RZ_LIB_VERSION(rz_lang)
RZ_API void rz_lang_undef(RzLang *lang, const char *name)
Definition: lang.c:91
RZ_API int rz_lang_run_string(RzLang *lang, const char *code)
Definition: lang.c:179
RZ_API int rz_lang_run(RzLang *lang, const char *code, int len)
Definition: lang.c:172
static RzLang * __lang
Definition: lang.c:12
RZ_API void rz_lang_def_free(RzLangDef *def)
Definition: lang.c:85
static RzLangPlugin * lang_static_plugins[]
Definition: lang.c:11
RZ_API void rz_lang_plugin_free(RzLangPlugin *p)
Definition: lang.c:14
RZ_API int rz_lang_prompt(RzLang *lang)
Definition: lang.c:205
RZ_API RzLangPlugin * rz_lang_get_by_name(RzLang *lang, const char *name)
Definition: lang.c:141
RZ_API void rz_lang_free(RzLang *lang)
Definition: lang.c:46
RZ_API RzLang * rz_lang_new(void)
Definition: lang.c:20
RZ_API void rz_lang_set_user_ptr(RzLang *lang, void *user)
Definition: lang.c:61
RZ_API int rz_lang_run_file(RzLang *lang, const char *file)
Definition: lang.c:183
RZ_API RzLangPlugin * rz_lang_get_by_extension(RzLang *lang, const char *ext)
Definition: lang.c:126
RZ_API bool rz_lang_set_argv(RzLang *lang, int argc, char **argv)
Definition: lang.c:165
RZ_API bool rz_lang_use(RzLang *lang, const char *name)
Definition: lang.c:155
RZ_API bool rz_lang_setup(RzLang *lang)
Definition: lang.c:108
RZ_API bool rz_lang_define(RzLang *lang, const char *type, const char *name, void *value)
Definition: lang.c:65
RZ_API bool rz_lang_add(RzLang *lang, RzLangPlugin *foo)
Definition: lang.c:115
void * p
Definition: libc.cpp:67
static RzMain foo[]
Definition: main.c:11
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API RzLine * rz_line_singleton(void)
Definition: line.c:15
RZ_API void rz_line_set_prompt(const char *prompt)
Definition: line.c:56
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int type
Definition: mipsasm.c:17
line
Definition: setup.py:34
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API char * rz_file_abspath(const char *file)
Definition: file.c:267
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API const char * rz_str_lchr(const char *str, char chr)
Definition: str.c:669
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121
#define rz_sys_xsystem(cmd)
Definition: rz_sys.h:83
#define RZ_NEW0(x)
Definition: rz_types.h:284
int(* PrintfCallback)(const char *str,...) RZ_PRINTF_CHECK(1
Definition: rz_types.h:233
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define h(i)
Definition: sha256.c:48
Definition: inftree9.h:24
Definition: gzappend.c:170
Definition: z80asm.h:102
const char ** help
Definition: rz_lang.h:32
bool(* setup)(RzLang *user)
Definition: rz_lang.h:35
int(* prompt)(RzLang *user)
Definition: rz_lang.h:37
const char * name
Definition: rz_lang.h:28
int(* set_argv)(RzLang *user, int argc, char **argv)
Definition: rz_lang.h:40
int(* run)(RzLang *user, const char *code, int len)
Definition: rz_lang.h:38
int(* run_file)(RzLang *user, const char *file)
Definition: rz_lang.h:39
void * user
Definition: rz_lang.h:19
RzList * defs
Definition: rz_lang.h:20
PrintfCallback cb_printf
Definition: rz_lang.h:22
struct rz_lang_plugin_t * cur
Definition: rz_lang.h:18
RzList * langs
Definition: rz_lang.h:21
RzListFree free
Definition: rz_list.h:21
const char * name
Definition: rz_main.h:17
static char * prompt(const char *str, const char *txt)
Definition: vmenus.c:30
int def(FILE *source, FILE *dest, int level)
Definition: zpipe.c:36