Rizin
unix-like reverse engineering framework and cli tools
egg_lang.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2010-2018 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_egg.h>
5 
6 #define CTX egg->context
7 
8 static inline int is_var(char *x) {
9  return x[0] == '.' || ((x[0] == '*' || x[0] == '&') && x[1] == '.');
10 }
11 
12 static inline int is_space(char c) {
13  return c == ' ' || c == '\t' || c == '\n' || c == '\r';
14 }
15 
16 static const char *skipspaces(const char *s) {
17  while (is_space(*s)) {
18  s++;
19  }
20  return s;
21 }
22 
23 static inline int is_op(char x) {
24  switch (x) {
25  case '-':
26  case '+':
27  return 1;
28  case '*':
29  case '/':
30  return 2;
31  case '^':
32  case '|':
33  case '&':
34  return 3;
35  default:
36  return 0;
37  }
38 }
39 
40 static inline int get_op(char **pos) {
41  while (**pos && !(is_op(**pos) && !is_var(*pos))) {
42  (*pos)++;
43  }
44  return (**pos) ? ((is_op(**pos)) + 1) : 0;
45 }
46 
47 /* chop word by space/tab/.. */
48 /* NOTE: ensure string does not starts with spaces */
49 static char *trim(char *s) {
50  char *o;
51  for (o = s; *o; o++) {
52  if (is_space(*o)) {
53  *o = 0;
54  }
55  }
56  return s;
57 }
58 
59 static void rcc_pushstr(RzEgg *egg, char *str, int filter);
60 static void rcc_context(RzEgg *egg, int delta);
61 
62 enum {
63  NORMAL = 0,
72  LAST
73 };
74 
75 static char *find_include(const char *prefix, const char *file) {
76  char *pfx = NULL, *ret = NULL, *env = rz_sys_getenv(RZ_EGG_INCDIR_ENV);
77  if (!prefix) {
78  prefix = "";
79  }
80  if (*prefix == '$') {
81  char *out = rz_sys_getenv(prefix + 1);
82  pfx = out ? out : strdup("");
83  } else {
84  pfx = strdup(prefix);
85  if (!pfx) {
86  free(env);
87  return NULL;
88  }
89  }
90 
91  if (env) {
92  char *str, *ptr = strchr(env, ':');
93  // eprintf ("MUST FIND IN PATH (%s)\n", env);
94  str = env;
95  while (str) {
96  if (ptr) {
97  *ptr = 0;
98  }
99  free(ret);
100  ret = rz_str_appendf(NULL, "%s/%s", pfx, file);
101  {
102  char *filepath = rz_str_appendf(NULL, "%s/%s/%s", str, pfx, file);
103  // eprintf ("try (%s)\n", filepath);
104  if (rz_file_exists(filepath)) {
105  free(env);
106  free(pfx);
107  free(ret);
108  return filepath;
109  }
110  free(filepath);
111  }
112  if (!ptr) {
113  break;
114  }
115  str = ptr + 1;
116  ptr = strchr(str, ':');
117  }
118  free(env);
119  } else {
120  ret = rz_str_appendf(NULL, "%s/%s", pfx, file);
121  }
122  free(pfx);
123  return ret;
124 }
125 
127  egg->lang.varsize = 'l';
128  /* do call or inline it ? */ // BOOL
129  egg->lang.docall = 1;
130  egg->lang.line = 1;
131  egg->lang.file = "stdin";
132  egg->lang.oc = '\n';
133  egg->lang.mode = NORMAL;
134 }
135 
137  int i, len;
138 
139  for (i = 0; i < egg->lang.nsyscalls; i++) {
140  RZ_FREE(egg->lang.syscalls[i].name);
141  RZ_FREE(egg->lang.syscalls[i].arg);
142  }
143  len = sizeof(egg->lang.ctxpush) / sizeof(char *);
144  for (i = 0; i < len; i++) {
145  RZ_FREE(egg->lang.ctxpush[i]);
146  }
147 }
148 
149 RZ_API void rz_egg_lang_include_path(RzEgg *egg, const char *path) {
150  char *tmp_ptr = NULL;
152  if (!env || !*env) {
154  free(env);
156  tmp_ptr = env;
157  }
158  env = rz_str_appendf(NULL, "%s:%s", path, env);
159  free(tmp_ptr);
161  free(env);
162 }
163 
165  char *prefix = rz_path_prefix(NULL);
166  char *s = rz_str_newf(".:%s/%s", prefix, RZ_EGG_INCDIR_PATH);
167  free(prefix);
169  free(s);
170 }
171 
172 static void rcc_set_callname(RzEgg *egg, const char *s) {
173  RZ_FREE(egg->lang.callname);
174  egg->lang.nargs = 0;
175  egg->lang.callname = trim(strdup(skipspaces(s)));
176  egg->lang.pushargs = !((!strcmp(s, "goto")) || (!strcmp(s, "break")));
177 }
178 
179 static void rcc_reset_callname(RzEgg *egg) {
180  RZ_FREE(egg->lang.callname);
181  egg->lang.nargs = 0;
182 }
183 
184 #define SYNTAX_ATT 0
185 #if SYNTAX_ATT
186 #define FRAME_FMT ".LC%d_%d_frame%d"
187 #define FRAME_END_FMT ".LC%d_%d_end_frame%d"
188 #else
189 #define FRAME_FMT "__%d_%d_frame%d"
190 #define FRAME_END_FMT "__%d_%d_end_frame%d"
191 #endif
192 
193 #if 0
194 static char *get_frame_label(int type) {
195  static char label[128];
196  int nf = egg->lang.nfunctions;
197  int nb = egg->lang.nbrackets;
198  int ct = context;
199  /* TODO: this type hack to substruct nb and ctx looks weird */
200 #if 1
201  if (type == 1) {
202  nb--;
203  } else if (type == 2) {
204  ct--;
205  }
206 #endif
207  /* THIS IS GAS_ONLY */
208  snprintf (label, sizeof (label), FRAME_FMT, nf, nb, ct);
209  return label;
210 }
211 
212 static char *get_end_frame_label(RzEgg *egg) {
213  static char label[128];
214  snprintf (label, sizeof (label) - 1, FRAME_END_FMT,
215  egg->lang.nfunctions, egg->lang.nbrackets, context - 1);
216 // eprintf ("--> (egg->lang.endframe: %d %d %d)\n", egg->lang.nfunctions, egg->lang.nbrackets, context);
217  // snprintf (label, sizeof (label)-1, "frame_end_%d_%d", egg->lang.nfunctions, egg->lang.nbrackets);
218  return label;
219 }
220 #endif
221 
222 static const char *find_alias(RzEgg *egg, const char *str) {
223  // do not forget to free return strings to avoid memory leak
224  char *p = (char *)str;
225  int i;
226  if (*str == '"') {
227  return strdup(str);
228  }
229  // strings could not means aliases
230  while (*p && !is_space(*p)) {
231  p++;
232  }
233  *p = '\x00';
234  for (i = 0; i < egg->lang.nalias; i++) {
235  if (!strcmp(str, egg->lang.aliases[i].name)) {
236  return strdup(egg->lang.aliases[i].content);
237  }
238  }
239  return NULL;
240  // only strings or alias could return valuable data
241 }
242 
243 static void rcc_internal_mathop(RzEgg *egg, const char *ptr, char *ep, char op) {
244  char *p, *q, *oldp; // avoid mem leak
245  char type = ' ';
246  char buf[64]; // may cause stack overflow
247  oldp = p = q = strdup(ptr);
248  if (get_op(&q)) {
249  *q = '\x00';
250  }
251  RzEggEmit *e = egg->remit;
252  while (*p && is_space(*p)) {
253  p++;
254  }
255  if (is_var(p)) {
256  p = rz_egg_mkvar(egg, buf, p, 0);
257  if (egg->lang.varxs == '*') {
258  e->load(egg, p, egg->lang.varsize);
259  RZ_FREE(oldp);
260  oldp = p = strdup(e->regs(egg, 0));
261  // XXX: which will go wrong in arm
262  // for reg used in emit.load in arm is r7 not r0
263  } else if (egg->lang.varxs == '&') {
264  e->load_ptr(egg, p);
265  RZ_FREE(oldp);
266  oldp = p = strdup(e->regs(egg, 0));
267  }
268  type = ' ';
269  } else {
270  type = '$';
271  }
272  if (*p) {
273  e->mathop(egg, op, egg->lang.varsize, type, p, ep);
274  }
275  if (p != oldp) {
276  RZ_FREE(p);
277  }
278  RZ_FREE(oldp);
279  RZ_FREE(ep);
280 }
281 
282 /*
283  * level 2: + -
284  * level 3: * /
285  * level 4: ^ $ |
286  */
287 static void rcc_mathop(RzEgg *egg, char **pos, int level) {
288  RzEggEmit *e = egg->remit;
289  int op_ret = level;
290  char op, *next_pos;
291 
292  while (**pos && is_space(**pos)) {
293  (*pos)++;
294  }
295  next_pos = *pos + 1;
296 
297  do {
298  op = (is_op(**pos) && !(is_var(*pos))) ? **pos : '=';
299  *pos = (is_op(**pos) && !(is_var(*pos))) ? *pos + 1 : *pos;
300  op_ret = get_op(&next_pos);
301  if (op_ret > level) {
302  rcc_mathop(egg, pos, op_ret);
303  rcc_internal_mathop(egg, e->regs(egg, op_ret - 1),
304  strdup(e->regs(egg, level - 1)), op);
305  next_pos = *pos + 1;
306  } else {
307  rcc_internal_mathop(egg, *pos, strdup(e->regs(egg, level - 1)), op);
308  *pos = next_pos;
309  next_pos++;
310  }
311  } while (**pos && op_ret >= level);
312 
313  /* following code block sould not handle '-' and '/' well
314  if (op_ret < level) {
315  rcc_internal_mathop(egg, p, strdup(e->regs(egg, level-1)) ,'=');
316  return;
317  }
318  op = *pos, *pos = '\x00', (*pos)++;
319  rcc_mathop(egg, pos, op_ret);
320  if (op_ret > level) {
321  rcc_internal_mathop(egg, p, strdup(e->regs(egg, op_ret-1)), op);
322  rcc_internal_mathop(egg, (char *)e->regs(egg, op_ret-1)
323  , strdup(e->regs(egg, level-1)), '=');
324  }
325  else rcc_internal_mathop(egg, p, strdup(e->regs(egg, level-1)), op);
326 */
327 }
328 
329 static void rcc_pusharg(RzEgg *egg, char *str) {
330  RzEggEmit *e = egg->remit;
331  char buf[64], *p = rz_egg_mkvar(egg, buf, str, 0);
332  if (!p) {
333  return;
334  }
335  RZ_FREE(egg->lang.ctxpush[CTX]);
336  egg->lang.ctxpush[CTX] = strdup(p); // INDEX IT WITH NARGS OR CONTEXT?!?
337  egg->lang.nargs++;
338  if (egg->lang.pushargs) {
339  e->push_arg(egg, egg->lang.varxs, egg->lang.nargs, p);
340  }
341  // egg->lang.ctxpush[context+egg->lang.nbrackets] = strdup(str); // use egg->lang.nargs??? (in callname)
342  free(p);
343 }
344 
345 static void rcc_element(RzEgg *egg, char *str) {
346  if (!egg || !str) {
347  return;
348  }
349  RzEggEmit *e = egg->remit;
350  char *ptr, *p = str + strlen(str);
351  int inside = 0;
352  int num, num2;
353  int i;
354 
355  if (CTX) {
356  if (egg->lang.slurp == '"') {
357  if (egg->lang.mode == NORMAL) {
358  if (!egg->lang.dstvar) {
359  egg->lang.dstvar = strdup(".fix0");
360  }
361  rcc_pushstr(egg, str, 1);
362  }
363  } else {
364  if (egg->lang.callname) {
365  if (strstr(egg->lang.callname, "while") || strstr(egg->lang.callname, "if")) {
366  egg->lang.conditionstr = strdup(str);
367  }
368  }
369  egg->lang.nargs = 0;
370  if (egg->lang.mode == GOTO) {
371  egg->lang.mode = NORMAL; // XXX
372  }
373  while (p-- != str) {
374  if (*p == '"') {
375  inside ^= 1;
376  } else if (*p == ',' && !inside) {
377  *p = '\0';
378  p = (char *)skipspaces(p + 1);
379  rcc_pusharg(egg, p);
380  }
381  }
382  rcc_pusharg(egg, str);
383  }
384  } else {
385  switch (egg->lang.mode) {
386  case ALIAS:
387  if (!egg->lang.dstvar) {
388  eprintf("does not set name or content for alias\n");
389  break;
390  }
391  e->equ(egg, egg->lang.dstvar, str);
392  if (egg->lang.nalias > 255) {
393  eprintf("global-buffer-overflow in aliases\n");
394  break;
395  }
396  for (i = 0; i < egg->lang.nalias; i++) {
397  if (!strcmp(egg->lang.dstvar, egg->lang.aliases[i].name)) {
398  RZ_FREE(egg->lang.aliases[i].name);
399  RZ_FREE(egg->lang.aliases[i].content);
400  break;
401  }
402  }
403  egg->lang.aliases[i].name = strdup(egg->lang.dstvar);
404  egg->lang.aliases[i].content = strdup(str);
405  egg->lang.nalias = (i == egg->lang.nalias) ? (egg->lang.nalias + 1) : egg->lang.nalias;
406  // allow alias overwrite
407  RZ_FREE(egg->lang.dstvar);
408  egg->lang.mode = NORMAL;
409  break;
410  case SYSCALL:
411  if (!egg->lang.dstvar) {
412  eprintf("does not set name or arg for syscall\n");
413  break;
414  }
415  if (egg->lang.nsyscalls > 255) {
416  eprintf("global-buffer-overflow in syscalls\n");
417  break;
418  }
419  {
420  bool found = false;
421  int idx = egg->lang.nsyscalls;
422  for (i = 0; i < egg->lang.nsyscalls; i++) {
423  if (!strcmp(egg->lang.dstvar, egg->lang.syscalls[i].name)) {
424  idx = i;
425  found = true;
426  break;
427  }
428  }
429  // XXX the mem for name and arg are not freed - MEMLEAK
430  RZ_FREE(egg->lang.syscalls[idx].name);
431  RZ_FREE(egg->lang.syscalls[idx].arg);
432  egg->lang.syscalls[idx].name = strdup(egg->lang.dstvar);
433  egg->lang.syscalls[idx].arg = strdup(str);
434  if (!found) {
435  egg->lang.nsyscalls++;
436  }
437  RZ_FREE(egg->lang.dstvar);
438  }
439  break;
440  case GOTO:
441  egg->lang.elem[egg->lang.elem_n] = 0;
442  e->jmp(egg, egg->lang.elem, 0);
443  break;
444  case INCLUDE:
445  str = ptr = (char *)find_alias(egg, skipspaces(str));
446  if (ptr) {
447  if (strchr(ptr, '"')) {
448  ptr = strchr(ptr, '"') + 1;
449  if ((p = strchr(ptr, '"'))) {
450  *p = '\x00';
451  } else {
452  eprintf("loss back quote in include directory\n");
453  }
454  egg->lang.includedir = strdup(ptr);
455  } else {
456  eprintf("wrong include syntax\n");
457  // for must use string to symbolize directory
458  egg->lang.includedir = NULL;
459  }
460  } else {
461  egg->lang.includedir = NULL;
462  }
463  RZ_FREE(str);
464  break;
465  default:
466  p = strchr(str, ',');
467  if (p) {
468  *p = '\0';
469  num2 = atoi(p + 1);
470  } else {
471  num2 = 0;
472  }
473  num = atoi(str) + num2;
474  egg->lang.stackframe = num;
475  egg->lang.stackfixed = num2;
476  if (egg->lang.mode != NAKED) {
477  e->frame(egg, egg->lang.stackframe + egg->lang.stackfixed);
478  }
479  }
480  egg->lang.elem[0] = 0;
481  egg->lang.elem_n = 0;
482  }
483 }
484 
485 static void rcc_pushstr(RzEgg *egg, char *str, int filter) {
486  int dotrim;
487  int i, j, len, ch;
488  RzEggEmit *e = egg->remit;
489 
490  e->comment(egg, "encode %s string (%s) (%s)",
491  filter ? "filtered" : "unfiltered", str, egg->lang.callname);
492 
493  // fixed by izhuer
494  if (filter) {
495  for (i = 0; str[i]; i++) {
496  dotrim = 0;
497  if (str[i] == '\\') {
498  switch (str[i + 1]) {
499  case 't':
500  str[i] = '\t';
501  dotrim = 1;
502  break;
503  case 'n':
504  str[i] = '\n';
505  dotrim = 1;
506  break;
507  case 'e':
508  str[i] = '\x1b';
509  dotrim = 1;
510  break;
511  case 'x':
512  ch = rz_hex_pair2bin(str + i + 2);
513  if (ch == -1) {
514  eprintf("%s:%d Error string format\n",
515  egg->lang.file, egg->lang.line);
516  }
517  str[i] = (char)ch;
518  dotrim = 3;
519  break;
520  default:
521  break;
522  }
523  if (dotrim) {
524  memmove(str + i + 1, str + i + dotrim + 1,
525  strlen(str + i + dotrim + 1) + 1);
526  }
527  // DO NOT forget the '\x00' terminate char
528  }
529  }
530  }
531 
532  len = strlen(str);
533  j = (len - len % e->size) + e->size;
534  e->set_string(egg, egg->lang.dstvar, str, j);
535  RZ_FREE(egg->lang.dstvar);
536 }
537 
538 RZ_API char *rz_egg_mkvar(RzEgg *egg, char *out, const char *_str, int delta) {
539  int i, len, qi;
540  char *oldstr = NULL, *str = NULL, foo[32], *q, *ret = NULL;
541 
542  delta += egg->lang.stackfixed; // XXX can be problematic
543  if (!_str) {
544  return NULL; /* fix segfault, but not badparsing */
545  }
546  /* XXX memory leak */
547  ret = str = oldstr = strdup(skipspaces(_str));
548  // if (num || str[0]=='0') { sprintf(out, "$%d", num); ret = out; }
549  if ((q = strchr(str, ':'))) {
550  *q = '\0';
551  qi = atoi(q + 1);
552  egg->lang.varsize = (qi == 1) ? 'b' : 'l';
553  } else {
554  egg->lang.varsize = 'l';
555  }
556  if (*str == '*' || *str == '&') {
557  egg->lang.varxs = *str;
558  str++;
559  } else {
560  egg->lang.varxs = 0;
561  }
562  if (str[0] == '.') {
563  RzEggEmit *e = egg->remit;
564  if (!strncmp(str + 1, "ret", 3)) {
565  strcpy(out, e->retvar);
566  } else if (!strncmp(str + 1, "fix", 3)) {
567  int idx = (int)rz_num_math(NULL, str + 4) + delta + e->size;
568  e->get_var(egg, 0, out, idx - egg->lang.stackfixed);
569  // sprintf(out, "%d(%%"RZ_BP")", -(atoi(str+4)+delta+RZ_SZ-egg->lang.stackfixed));
570  } else if (!strncmp(str + 1, "var", 3)) {
571  int idx = (int)rz_num_math(NULL, str + 4) + delta + e->size;
572  e->get_var(egg, 0, out, idx);
573  // sprintf(out, "%d(%%"RZ_BP")", -(atoi(str+4)+delta+RZ_SZ));
574  } else if (!strncmp(str + 1, "rarg", 4)) {
575  if (e->get_ar) {
576  int idx = (int)rz_num_math(NULL, str + 5);
577  e->get_ar(egg, out, idx);
578  }
579  } else if (!strncmp(str + 1, "arg", 3)) {
580  if (str[4]) {
581  if (egg->lang.stackframe == 0) {
582  e->get_var(egg, 1, out, 4); // idx-4);
583  } else {
584  int idx = (int)rz_num_math(NULL, str + 4) + delta + e->size;
585  e->get_var(egg, 2, out, idx + 4);
586  }
587  } else {
588  /* TODO: return size of syscall */
589  if (egg->lang.callname) {
590  for (i = 0; i < egg->lang.nsyscalls; i++) {
591  if (!strcmp(egg->lang.syscalls[i].name, egg->lang.callname)) {
592  free(oldstr);
593  return strdup(egg->lang.syscalls[i].arg);
594  }
595  }
596  eprintf("Unknown arg for syscall '%s'\n", egg->lang.callname);
597  } else {
598  eprintf("NO CALLNAME\n");
599  }
600  }
601  } else if (!strncmp(str + 1, "reg", 3)) {
602  // XXX: can overflow if out is small
603  if (egg->lang.attsyntax) {
604  snprintf(out, 32, "%%%s", e->regs(egg, atoi(str + 4)));
605  } else {
606  snprintf(out, 32, "%s", e->regs(egg, atoi(str + 4)));
607  }
608  } else {
609  out = str; /* TODO: show error, invalid var name? */
610  eprintf("Something is really wrong\n");
611  }
612  ret = strdup(out);
613  free(oldstr);
614  } else if (*str == '"' || *str == '\'') {
615  int mustfilter = *str == '"';
616  /* TODO: check for room in egg->lang.stackfixed area */
617  str++;
618  len = strlen(str) - 1;
619  if (!egg->lang.stackfixed || egg->lang.stackfixed < len) {
620  eprintf("WARNING: No room in the static stackframe! (%d must be %d)\n",
621  egg->lang.stackfixed, len);
622  }
623  str[len] = '\0';
624  snprintf(foo, sizeof(foo) - 1, ".fix%d", egg->lang.nargs * 16); /* XXX FIX DELTA !!!1 */
625  free(egg->lang.dstvar);
626  egg->lang.dstvar = strdup(skipspaces(foo));
627  rcc_pushstr(egg, str, mustfilter);
628  ret = rz_egg_mkvar(egg, out, foo, 0);
629  free(oldstr);
630  }
631  return ret;
632 }
633 
634 static void rcc_fun(RzEgg *egg, const char *str) {
635  char *ptr, *ptr2;
636  RzEggEmit *e = egg->remit;
637  str = skipspaces(str);
638  if (CTX) {
639  ptr = strchr(str, '=');
640  if (ptr) {
641  *ptr++ = '\0';
642  free(egg->lang.dstvar);
643  egg->lang.dstvar = strdup(skipspaces(str));
644  ptr2 = (char *)skipspaces(ptr);
645  if (*ptr2) {
646  rcc_set_callname(egg, skipspaces(ptr));
647  }
648  } else {
649  str = skipspaces(str);
651  egg->remit->comment(egg, "rcc_fun %d (%s)",
652  CTX, egg->lang.callname);
653  }
654  } else {
655  ptr = strchr(str, '@');
656  if (ptr) {
657  *ptr++ = '\0';
658  egg->lang.mode = NORMAL;
659  if (strstr(ptr, "env")) {
660  // eprintf ("SETENV (%s)\n", str);
661  free(egg->lang.setenviron);
663  egg->lang.slurp = 0;
664  } else if (strstr(ptr, "fastcall")) {
665  /* TODO : not yet implemented */
666  } else if (strstr(ptr, "syscall")) {
667  if (*str) {
668  egg->lang.mode = SYSCALL;
669  egg->lang.dstvar = strdup(skipspaces(str));
670  } else {
671  egg->lang.mode = INLINE;
672  free(egg->lang.syscallbody);
673  egg->lang.syscallbody = malloc(4096); // XXX hardcoded size
674  egg->lang.dstval = egg->lang.syscallbody;
675  RZ_FREE(egg->lang.dstvar);
676  egg->lang.ndstval = 0;
677  *egg->lang.syscallbody = '\0';
678  }
679  } else if (strstr(ptr, "include")) {
680  egg->lang.mode = INCLUDE;
681  free(egg->lang.includefile);
683  // egg->lang.slurp = 0;
684  // try to deal with alias
685  } else if (strstr(ptr, "alias")) {
686  egg->lang.mode = ALIAS;
687  ptr2 = egg->lang.dstvar = strdup(skipspaces(str));
688  while (*ptr2 && !is_space(*ptr2)) {
689  ptr2++;
690  }
691  *ptr2 = '\x00';
692  // for aliases must be valid and accurate strings
693  } else if (strstr(ptr, "data")) {
694  egg->lang.mode = DATA;
695  egg->lang.ndstval = 0;
696  egg->lang.dstvar = strdup(skipspaces(str));
697  egg->lang.dstval = malloc(4096);
698  } else if (strstr(ptr, "naked")) {
699  egg->lang.mode = NAKED;
700  /*
701  free (egg->lang.dstvar);
702  egg->lang.dstvar = strdup (skipspaces (str));
703  egg->lang.dstval = malloc (4096);
704  egg->lang.ndstval = 0;
705  */
706  rz_egg_printf(egg, "%s:\n", str);
707  } else if (strstr(ptr, "inline")) {
708  egg->lang.mode = INLINE;
709  free(egg->lang.dstvar);
710  egg->lang.dstvar = strdup(skipspaces(str));
711  egg->lang.dstval = malloc(4096);
712  egg->lang.ndstval = 0;
713  } else {
714  // naked label
715  if (*ptr) {
716  rz_egg_printf(egg, "\n.%s %s\n", ptr, str);
717  }
718  rz_egg_printf(egg, "%s:\n", str);
719  }
720  } else {
721  // e->jmp (egg, egg->lang.ctxpush[context], 0);
722  if (CTX > 0) {
723  eprintf("LABEL %d\n", CTX);
724  rz_egg_printf(egg, "\n%s:\n", str);
725  } else {
726  if (!strcmp(str, "goto")) {
727  egg->lang.mode = GOTO;
728  } else {
729  // call() // or maybe jmp?
730  e->call(egg, str, 0);
731  }
732  }
733  }
734  }
735 }
736 
737 #if 0
738 static void shownested(void) {
739  int i;
740  eprintf ("[[[NESTED %d]]] ", context);
741  for (i = 0; egg->lang.nested[i]; i++) {
742  eprintf ("%s ", egg->lang.nested[i]);
743  }
744  eprintf ("\n");
745 }
746 #endif
747 
748 static void set_nested(RzEgg *egg, const char *s) {
749  int i = 0;
750  if (CTX < 1) {
751  return;
752  }
753  free(egg->lang.nested[CTX]);
754  egg->lang.nested[CTX] = strdup(s);
755  // egg->lang.nestedi[c]++;
756  // seems not need to increase egg->lang.nestedi[c]
758  for (i = 1; i < 10; i++) {
759  // egg->lang.nestedi[context+i] = 0;
760  RZ_FREE(egg->lang.nested[CTX + i]);
761  }
762 }
763 
764 static void rcc_context(RzEgg *egg, int delta) {
765  RzEggEmit *emit = egg->remit;
766  char str[64];
767 
768  if (CTX > 31 || CTX < 0) {
769  return;
770  }
771 
772  if (delta > 0) {
773  egg->lang.nestedi[CTX]++;
775  if (egg->lang.callname) {
776  egg->lang.nested_callname[CTX] = strdup(egg->lang.callname);
777  }
778  }
779  if (egg->lang.callname && CTX > 0) { // && delta>0) {
780  // set_nested (callname);
781  // eprintf (" - - - - - - - set nested d=%d c=%d (%s)\n", delta, context-1, callname);
782  // shownested();
783  }
784  CTX += delta;
785  egg->lang.lastctxdelta = delta;
786 
787  if (CTX == 0 && delta < 0) {
788  if (egg->lang.mode != NAKED) {
789  emit->frame_end(egg, egg->lang.stackframe + egg->lang.stackfixed, egg->lang.nbrackets);
790  }
791  if (egg->lang.mode == NORMAL) { /* XXX : commenting this makes hello.r unhappy! TODO: find a cleaner alternative */
792  egg->lang.stackframe = 0;
793  }
794  egg->lang.mode = NORMAL;
795  } else {
796  /* conditional block */
797  // eprintf ("Callname is (%s)\n", callname);
798  const char *elm = skipspaces(egg->lang.elem);
799  // const char *cn = callname;
800  // seems cn is useless in nowadays content
801 // if (egg->lang.nested[context-1])
802 #if 0
803  if (delta < 0 && context > 0) {
804  eprintf ("close bracket foo!!!\n");
805  shownested ();
806  cn = strdup (egg->lang.nested[context - 1]);
807  eprintf ("STATEMENT cn=(%s) idx=%d (%s)\n", cn, context - 1, egg->lang.nested[context - 1]);
808  eprintf ("CNTXXXPUSH (%s)\n", egg->lang.ctxpush[context - 1]);
809 #if 0
810  if (!strcmp (cn, "while")) {
811  emit->while_end (egg, get_frame_label (context - 1));
812  // char *var = get_frame_label (0);
813  // emit->jmp (egg, var, 0);
814  return;
815  }
816 #endif
817  }
818 #endif
819  // eprintf ("ELEM (%s)\n", elm);
820  // eprintf ("END BLOCK %d, (%s)\n", context, egg->lang.nested[context-1]);
821  // eprintf ("CN = (%s) %d (%s) delta=%d\n", cn, context, egg->lang.nested[context-1], delta);
822  if (egg->lang.callname) {
823  /* TODO: this must be an array */
824  char *b, *g, *e, *n;
825  emit->comment(egg, "cond frame %s (%s)", egg->lang.callname, elm);
826  /* TODO: simplify with a single for */
827  if (egg->lang.conditionstr) {
828  b = strchr(egg->lang.conditionstr, '<'); /* below */
829  g = strchr(egg->lang.conditionstr, '>'); /* greater */
830  e = strchr(egg->lang.conditionstr, '='); /* equal */
831  n = strchr(egg->lang.conditionstr, '!'); /* negate */
832  } else {
833  b = g = e = n = NULL;
834  }
835  if (!strcmp(egg->lang.callname, "while")) {
836  char lab[128];
837  sprintf(lab, "__begin_%d_%d_%d", egg->lang.nfunctions,
838  CTX - 1, egg->lang.nestedi[CTX - 1] - 1);
839  // the egg->lang.nestedi[CTX-1] has increased
840  // so we should decrease it in label
841  emit->get_while_end(egg, str, egg->lang.ctxpush[CTX - 1], lab); // get_frame_label (2));
842  // get_frame_label (2));
843  // eprintf ("------ (%s)\n", egg->lang.ctxpush[context-1]);
844  // free (egg->lang.endframe);
845  // XXX: egg->lang.endframe is deprecated, must use set_nested only
846  if (delta > 0) {
847  set_nested(egg, str);
848  }
849  rcc_set_callname(egg, "if"); // append 'if' body
850  }
851  if (!strcmp(egg->lang.callname, "if")) {
852  // emit->branch (egg, b, g, e, n, egg->lang.varsize, get_end_frame_label (egg));
853  // HACK HACK :D
854  // sprintf (str, "__end_%d_%d_%d", egg->lang.nfunctions,
855  // CTX-1, egg->lang.nestedi[CTX-1]);
856  // nestede[CTX-1] = strdup (str);
857  // where give nestede value
858  sprintf(str, "__end_%d_%d_%d", egg->lang.nfunctions, CTX - 1, egg->lang.nestedi[CTX - 1] - 1);
859  emit->branch(egg, b, g, e, n, egg->lang.varsize, str);
860  if (CTX > 0) {
861  /* XXX .. */
862  }
863  rcc_reset_callname(egg);
864  RZ_FREE(egg->lang.conditionstr);
865  } // else eprintf ("Unknown statement (%s)(%s)\n", cn, elem);
866  } // handle '{ ..'
867  }
868 }
869 
870 static int parsedatachar(RzEgg *egg, char c) {
871  char *str;
872  int i, j;
873 
874  if (!egg->lang.dstval) {
875  return 0;
876  }
877  /* skip until '{' */
878  if (c == '{') { /* XXX: repeated code!! */
879  rcc_context(egg, 1);
880  if (++(egg->lang.inlinectr) == 1) {
881  return egg->lang.ndstval = 0;
882  }
883  } else if (egg->lang.inlinectr == 0) {
884  /* capture value between parenthesis foo@data(NNN) { ... } */
885  if (c == ')') {
886  egg->lang.stackframe = atoi(egg->lang.dstval);
887  egg->lang.ndstval = 0;
888  } else {
889  egg->lang.dstval[egg->lang.ndstval++] = c;
890  }
891  return 0;
892  }
893  /* capture body */
894  if (c == '}') { /* XXX: repeated code!! */
895  if (CTX < 2) {
896  egg->lang.inlinectr = 0;
897  rcc_context(egg, -1);
898  egg->lang.slurp = 0;
899  egg->lang.mode = NORMAL;
900  /* register */
901  if (egg->lang.dstval && egg->lang.dstvar) {
902  egg->lang.dstval[egg->lang.ndstval] = '\0';
903  egg->remit->comment(egg, "data (%s)(%s)size=(%d)\n",
904  egg->lang.dstvar, egg->lang.dstval, egg->lang.stackframe);
905  rz_egg_printf(egg, ".data\n");
906  for (str = egg->lang.dstval; is_space(*str); str++) {
907  ;
908  }
909  j = (egg->lang.stackframe) ? egg->lang.stackframe : 1;
910  /* emit label */
911  rz_egg_printf(egg, "%s:\n", egg->lang.dstvar);
912  for (i = 1; i <= j; i++) {
913  if (*str == '"') {
914  rz_egg_printf(egg, ".ascii %s%s\n", egg->lang.dstval, (i == j) ? "\"\\x00\"" : "");
915  } else {
916  rz_egg_printf(egg, ".long %s\n", egg->lang.dstval);
917  }
918  }
919  rz_egg_printf(egg, ".text\n");
920  RZ_FREE(egg->lang.dstvar);
921  RZ_FREE(egg->lang.dstval);
922  egg->lang.ndstval = 0;
923  CTX = 0;
924  return 1;
925  }
926  }
927  }
928  if (egg->lang.dstval) {
929  egg->lang.dstval[egg->lang.ndstval++] = c;
930  }
931  return 0;
932 }
933 
934 static int parseinlinechar(RzEgg *egg, char c) {
935  /* skip until '{' */
936  if (c == '{') { /* XXX: repeated code!! */
937  rcc_context(egg, 1);
938  egg->lang.inlinectr++;
939  if (egg->lang.inlinectr == 1) {
940  return 0;
941  }
942  } else if (egg->lang.inlinectr == 0) {
943  return 0;
944  }
945 
946  /* capture body */
947  if (c == '}') { /* XXX: repeated code!! */
948  if (CTX < 2) {
949  rcc_context(egg, -1);
950  egg->lang.slurp = 0;
951  egg->lang.mode = NORMAL;
952  egg->lang.inlinectr = 0;
953  if (!egg->lang.dstvar && egg->lang.dstval == egg->lang.syscallbody) {
954  egg->lang.dstval = NULL;
955  return 1;
956  } else /* register */
957  if (egg->lang.dstval && egg->lang.dstvar) {
958  egg->lang.dstval[egg->lang.ndstval] = '\0';
959  // printf(" /* END OF INLINE (%s)(%s) */\n", egg->lang.dstvar, egg->lang.dstval);
960  egg->lang.inlines[egg->lang.ninlines].name = strdup(skipspaces(egg->lang.dstvar));
961  egg->lang.inlines[egg->lang.ninlines].body = strdup(skipspaces(egg->lang.dstval));
962  egg->lang.ninlines++;
963  RZ_FREE(egg->lang.dstvar);
964  RZ_FREE(egg->lang.dstval);
965  return 1;
966  }
967  eprintf("Parse error\n");
968  }
969  }
970  if (egg->lang.dstval) {
971  egg->lang.dstval[egg->lang.ndstval++] = c;
972  egg->lang.dstval[egg->lang.ndstval] = 0;
973  }
974  return 0;
975 }
976 
977 /* TODO: split this function into several ones..quite long fun */
978 static void rcc_next(RzEgg *egg) {
979  const char *ocn;
980  RzEggEmit *e = egg->remit;
981  char *str = NULL, *p, *ptr, buf[64];
982  int i;
983 
984  if (egg->lang.setenviron) {
985  egg->lang.elem[egg->lang.elem_n - 1] = 0;
986  rz_sys_setenv(egg->lang.setenviron, egg->lang.elem);
987  RZ_FREE(egg->lang.setenviron);
988  return;
989  }
990  if (egg->lang.includefile) {
991  char *p, *q, *path;
992  egg->lang.elem[egg->lang.elem_n - 1] = 0;
994  if (!path) {
995  eprintf("Cannot find include file '%s'\n", egg->lang.elem);
996  return;
997  }
998  RZ_FREE(egg->lang.includefile);
999  RZ_FREE(egg->lang.includedir);
1000  rcc_reset_callname(egg);
1001  p = q = rz_file_slurp(path, NULL);
1002  if (p) {
1003  int oline = ++(egg->lang.line);
1004  egg->lang.elem[0] = 0; // TODO: this must be a separate function
1005  egg->lang.elem_n = 0;
1006  egg->lang.line = 0;
1007  for (; *p; p++) {
1008  rz_egg_lang_parsechar(egg, *p);
1009  }
1010  free(q);
1011  egg->lang.line = oline;
1012  } else {
1013  eprintf("Cannot find '%s'\n", path);
1014  }
1015  free(path);
1016  return;
1017  }
1018  egg->lang.docall = 1;
1019  if (egg->lang.callname) {
1020  if (!strcmp(egg->lang.callname, "goto")) {
1021  if (egg->lang.nargs != 1) {
1022  eprintf("Invalid number of arguments for goto()\n");
1023  return;
1024  }
1025  e->jmp(egg, egg->lang.ctxpush[CTX], 0);
1026  rcc_reset_callname(egg);
1027  return;
1028  }
1029  if (!strcmp(egg->lang.callname, "break")) {
1030  e->trap(egg);
1031  rcc_reset_callname(egg);
1032  return;
1033  }
1034  ptr = strchr(egg->lang.callname, '=');
1035  if (ptr) {
1036  *ptr = '\0';
1037  // ocn = ptr+1; // what is the point of this?
1038  }
1039  ocn = skipspaces(egg->lang.callname);
1040  if (!ocn) {
1041  return;
1042  }
1043  str = rz_egg_mkvar(egg, buf, ocn, 0);
1044  if (!str) {
1045  eprintf("Cannot mkvar\n");
1046  return;
1047  }
1048  if (*ocn == '.') {
1049  e->call(egg, str, 1);
1050  }
1051  if (!strcmp(str, "while")) {
1052  char var[128];
1053  if (egg->lang.lastctxdelta >= 0) {
1054  eprintf("ERROR: Unsupported while syntax\n");
1055  return;
1056  }
1057  sprintf(var, "__begin_%d_%d_%d\n", egg->lang.nfunctions, CTX, egg->lang.nestedi[CTX - 1]);
1058  e->while_end(egg, var); // get_frame_label (1));
1059 #if 0
1060  eprintf ("------------------------------------------ lastctx: %d\n", egg->lang.lastctxdelta);
1061  // TODO: the pushvar is required for the if(){}while(); constructions
1062  // char *pushvar = egg->lang.ctxpush[context+egg->lang.nbrackets-1];
1063  /* TODO: support to compare more than one expression (LOGICAL OR) */
1064  rcc_printf (" pop %%eax\n");
1065  rcc_printf (" cmp $0, %%eax\n"); // XXX MUST SUPPORT != 0 COMPARE HERE
1066  /* TODO : Simplify!! */
1067  // if (pushvar)
1068  // printf(" push %s /* while push */\n", pushvar);
1069  if (egg->lang.lastctxdelta < 0) {
1070  rcc_printf (" jnz %s\n", get_frame_label (1));
1071  } else {
1072  rcc_printf (" jnz %s\n", get_frame_label (0));
1073  }
1074  // if (pushvar)
1075  // printf(" pop %%"RZ_AX" /* while pop */\n");
1076 #endif
1077  egg->lang.nargs = 0;
1078  } else {
1079  for (i = 0; i < egg->lang.nsyscalls; i++) {
1080  if (!strcmp(str, egg->lang.syscalls[i].name)) {
1081  p = egg->lang.syscallbody;
1082  e->comment(egg, "set syscall args");
1083  e->syscall_args(egg, egg->lang.nargs);
1084  egg->lang.docall = 0;
1085  e->comment(egg, "syscall");
1086  rz_egg_lang_parsechar(egg, '\n'); /* FIX parsing issue */
1087  if (p) {
1088  for (; *p; p++) {
1089  rz_egg_lang_parsechar(egg, *p);
1090  }
1091  } else {
1092  char *q, *s = e->syscall(egg, egg->lang.nargs);
1093  if (s) {
1094  for (q = s; *q; q++) {
1095  rz_egg_lang_parsechar(egg, *q);
1096  }
1097  free(s);
1098  } else {
1099  eprintf("Cannot get @syscall payload\n");
1100  }
1101  }
1102  egg->lang.docall = 0;
1103  break;
1104  }
1105  }
1106  if (egg->lang.docall) {
1107  for (i = 0; i < egg->lang.ninlines; i++) {
1108  if (!strcmp(str, egg->lang.inlines[i].name)) {
1109  p = egg->lang.inlines[i].body;
1110  egg->lang.docall = 0;
1111  e->comment(egg, "inline");
1112  rz_egg_lang_parsechar(egg, '\n'); /* FIX parsing issue */
1113  for (; *p; p++) {
1114  rz_egg_lang_parsechar(egg, *p);
1115  }
1116  egg->lang.docall = 0;
1117  break;
1118  }
1119  }
1120  }
1121  if (egg->lang.docall) {
1122  e->comment(egg, "call in egg->lang.mode %d", egg->lang.mode);
1123  e->call(egg, str, 0);
1124  }
1125  }
1126  if (egg->lang.nargs > 0) {
1127  e->restore_stack(egg, egg->lang.nargs * e->size);
1128  }
1129 
1130  // fixed by izhuer
1131  /*
1132  if (ocn) { // Used to call .var0()
1133  // XXX: ocn mustn't be NULL here
1134  // XXX: Probably buggy and wrong
1135  *buf = 0;
1136  free (str);
1137  str = rz_egg_mkvar (egg, buf, ocn, 0);
1138  if (*buf)
1139  e->get_result (egg, buf); // Why should get_result into ocn?
1140  //else { eprintf("external symbol %s\n", ocn); }
1141  }
1142  */
1143 
1144  /* store result of call */
1145  if (egg->lang.dstvar) {
1146  // if (egg->lang.mode != NAKED) {
1147  *buf = 0;
1148  free(str);
1149  str = rz_egg_mkvar(egg, buf, egg->lang.dstvar, 0);
1150  if (*buf == 0) {
1151  eprintf("Cannot resolve variable '%s'\n", egg->lang.dstvar);
1152  } else {
1153  e->get_result(egg, buf);
1154  }
1155  //}
1156  RZ_FREE(egg->lang.dstvar);
1157  }
1158  rcc_reset_callname(egg);
1159  } else { // handle mathop
1160  int vs = 'l';
1161  char type, *eq, *ptr = egg->lang.elem, *tmp;
1162  egg->lang.elem[egg->lang.elem_n] = '\0';
1163  ptr = (char *)skipspaces(ptr);
1164  if (*ptr) {
1165  eq = strchr(ptr, '=');
1166  if (eq) {
1167  vs = egg->lang.varsize;
1168  *buf = *eq = '\x00';
1169  e->mathop(egg, '=', vs, '$', "0", e->regs(egg, 1));
1170  // avoid situation that egg->lang.mathline starts with a single '-'
1171  egg->lang.mathline = strdup((char *)skipspaces(eq + 1));
1172  tmp = egg->lang.mathline;
1173  rcc_mathop(egg, &tmp, 2);
1174  RZ_FREE(egg->lang.mathline);
1175  tmp = NULL;
1176  // following code block is too ugly, oh noes
1177  char *p = rz_egg_mkvar(egg, buf, ptr, 0);
1178  if (is_var(p)) {
1179  char *q = rz_egg_mkvar(egg, buf, p, 0);
1180  if (q) {
1181  free(p);
1182  p = q;
1183  }
1184  if (egg->lang.varxs == '*' || egg->lang.varxs == '&') {
1185  eprintf("not support for *ptr in egg->lang.dstvar\n");
1186  }
1187  // XXX: Not support for pointer
1188  type = ' ';
1189  } else {
1190  type = '$';
1191  }
1192  e->mathop(egg, '=', vs, type, e->regs(egg, 1), p);
1193  free(p);
1194  /*
1195  char str2[64], *p, ch = *(eq-1);
1196  *eq = '\0';
1197  eq = (char*) skipspaces (eq+1);
1198  p = rz_egg_mkvar (egg, str2, ptr, 0);
1199  vs = egg->lang.varsize;
1200  if (is_var (eq)) {
1201  eq = rz_egg_mkvar (egg, buf, eq, 0);
1202  if (egg->lang.varxs=='*')
1203  e->load (egg, eq, egg->lang.varsize);
1204  else
1205  // XXX this is a hack .. must be integrated with pusharg
1206  if (egg->lang.varxs=='&')
1207  e->load_ptr (egg, eq);
1208  if (eq) {
1209  RZ_FREE (eq);
1210  }
1211  type = ' ';
1212  } else type = '$';
1213  vs = 'l'; // XXX: add support for != 'l' size
1214  eprintf("Getting into e->mathop with ch: %c\n", ch);
1215  eprintf("Getting into e->mathop with vs: %c\n", vs);
1216  eprintf("Getting into e->mathop with type: %c\n", type);
1217  eprintf("Getting into e->mathop with eq: %s\n", eq);
1218  eprintf("Getting into e->mathop with p: %s\n", p);
1219  e->mathop (egg, ch, vs, type, eq, p);
1220  free(p);
1221  */
1222  } else {
1223  if (!strcmp(ptr, "break")) { // handle 'break;'
1224  e->trap(egg);
1225  rcc_reset_callname(egg);
1226  } else {
1227  e->mathop(egg, '=', vs, '$', ptr, NULL);
1228  }
1229  }
1230  }
1231  }
1232  free(str);
1233 }
1234 
1236  RzEggEmit *e = egg->remit;
1237  char *ptr, str[64], *tmp_ptr = NULL;
1238  int i, j;
1239  if (c == '\n') {
1240  egg->lang.line++;
1241  egg->lang.elem_n = 0;
1242  }
1243  /* comments */
1244  if (egg->lang.skipline) {
1245  if (c != '\n') {
1246  egg->lang.oc = c;
1247  return 0;
1248  }
1249  egg->lang.skipline = 0;
1250  }
1251  if (egg->lang.mode == DATA) {
1252  return parsedatachar(egg, c);
1253  }
1254  if (egg->lang.mode == INLINE) {
1255  return parseinlinechar(egg, c);
1256  }
1257  /* quotes */
1258  if (egg->lang.quoteline) {
1259  if (c != egg->lang.quoteline) {
1260  if (egg->lang.quotelinevar == 1) {
1261  if (c == '`') {
1262  egg->lang.elem[egg->lang.elem_n] = 0;
1263  egg->lang.elem_n = 0;
1264  tmp_ptr = rz_egg_mkvar(egg, str, egg->lang.elem, 0);
1265  rz_egg_printf(egg, "%s", tmp_ptr);
1266  free(tmp_ptr);
1267  egg->lang.quotelinevar = 0;
1268  } else {
1269  egg->lang.elem[egg->lang.elem_n++] = c;
1270  }
1271  } else {
1272  if (c == '`') {
1273  egg->lang.elem_n = 0;
1274  egg->lang.quotelinevar = 1;
1275  } else {
1276  rz_egg_printf(egg, "%c", c);
1277  }
1278  }
1279  egg->lang.oc = c;
1280  return 0;
1281  } else {
1282  rz_egg_printf(egg, "\n");
1283  egg->lang.quoteline = 0;
1284  }
1285  }
1286 
1287  if (egg->lang.commentmode) {
1288  if (c == '/' && egg->lang.oc == '*') {
1289  egg->lang.commentmode = 0;
1290  }
1291  egg->lang.oc = c;
1292  return 0;
1293  } else if (c == '*' && egg->lang.oc == '/') {
1294  egg->lang.commentmode = 1;
1295  }
1296  if (egg->lang.slurp) {
1297  if (egg->lang.slurp != '"' && c == egg->lang.slurpin) { // only happend when (...(...)...)
1298  eprintf(
1299  "%s:%d Nesting of expressions not yet supported\n",
1300  egg->lang.file, egg->lang.line);
1301  return -1;
1302  }
1303  if (c == egg->lang.slurp && egg->lang.oc != '\\') { // close egg->lang.slurp
1304  egg->lang.elem[egg->lang.elem_n] = '\0';
1305  if (egg->lang.elem_n > 0) {
1306  rcc_element(egg, egg->lang.elem);
1307  } else {
1308  e->frame(egg, 0);
1309  }
1310  egg->lang.elem_n = 0;
1311  egg->lang.slurp = 0;
1312  } else {
1313  egg->lang.elem[egg->lang.elem_n++] = c;
1314  }
1315  egg->lang.elem[egg->lang.elem_n] = '\0';
1316  } else {
1317  switch (c) {
1318  case ';':
1319  rcc_next(egg);
1320  break;
1321  case '"':
1322  egg->lang.slurp = '"';
1323  break;
1324  case '(':
1325  egg->lang.slurpin = '(';
1326  egg->lang.slurp = ')';
1327  break;
1328  case '{':
1329  if (CTX > 0) {
1330  if (CTX > 31 || CTX < 0) {
1331  eprintf("Sinking before overflow\n");
1332  CTX = 0;
1333  break;
1334  }
1335  // rz_egg_printf (egg, " %s:\n", get_frame_label (0));
1336  if (egg->lang.nested_callname[CTX] && strstr(egg->lang.nested_callname[CTX], "if") &&
1337  strstr(egg->lang.elem, "else")) {
1338  *egg->lang.elem = '\x00';
1339  egg->lang.elem_n = 0;
1340  RZ_FREE(egg->lang.ifelse_table[CTX][egg->lang.nestedi[CTX] - 1])
1341  egg->lang.ifelse_table[CTX][egg->lang.nestedi[CTX] - 1] =
1342  rz_str_newf(" __end_%d_%d_%d",
1343  egg->lang.nfunctions, CTX, egg->lang.nestedi[CTX]);
1344  }
1345  rz_egg_printf(egg, " __begin_%d_%d_%d:\n",
1346  egg->lang.nfunctions, CTX, egg->lang.nestedi[CTX]); // %s:\n", get_frame_label (0));
1347  }
1348  rcc_context(egg, 1);
1349  break;
1350  case '}':
1351  egg->lang.endframe = egg->lang.nested[CTX];
1352  if (egg->lang.endframe) {
1353  // XXX: use egg->lang.endframe[context]
1354  rz_egg_printf(egg, "%s", egg->lang.endframe);
1355  RZ_FREE(egg->lang.nested[CTX]);
1356  // RZ_FREE (egg->lang.endframe);
1357  }
1358  if (CTX > 1) {
1359  if (egg->lang.nested_callname[CTX - 1] && strstr(egg->lang.nested_callname[CTX - 1], "if")) {
1360  tmp_ptr = rz_str_newf("__ifelse_%d_%d", CTX - 1, egg->lang.nestedi[CTX - 1] - 1);
1361  e->jmp(egg, tmp_ptr, 0);
1362  RZ_FREE(tmp_ptr); // mem leak
1363  egg->lang.ifelse_table[CTX - 1][egg->lang.nestedi[CTX - 1] - 1] =
1364  rz_str_newf("__end_%d_%d_%d",
1365  egg->lang.nfunctions, CTX - 1, egg->lang.nestedi[CTX - 1] - 1);
1366  }
1367  // if (nestede[CTX]) {
1368  // rz_egg_printf (egg, "%s:\n", nestede[CTX]);
1370  // } else {
1371  rz_egg_printf(egg, " __end_%d_%d_%d:\n",
1372  egg->lang.nfunctions, CTX - 1, egg->lang.nestedi[CTX - 1] - 1);
1373  // get_end_frame_label (egg));
1374  // }
1375  }
1376  if (CTX > 0) {
1377  egg->lang.nbrackets++;
1378  }
1379  rcc_context(egg, -1);
1380  if (CTX == 0) {
1381  rz_egg_printf(egg, "\n");
1382  // snprintf(str, 64, "__end_%d", egg->lang.nfunctions);
1383  // e->jmp(egg, str, 0);
1384  // edit this unnessary jmp to bypass tests
1385  for (i = 0; i < 32; i++) {
1386  for (j = 0; j < egg->lang.nestedi[i] && j < 32; j++) {
1387  if (egg->lang.ifelse_table[i][j]) {
1388  rz_egg_printf(egg, " __ifelse_%d_%d:\n", i, j);
1389  e->jmp(egg, egg->lang.ifelse_table[i][j], 0);
1390  RZ_FREE(egg->lang.ifelse_table[i][j]);
1391  }
1392  }
1393  }
1394  // rz_egg_printf(egg, " __end_%d:\n\n", egg->lang.nfunctions);
1395  // edit this unnessary jmp to bypass tests
1396  egg->lang.nbrackets = 0;
1397  egg->lang.nfunctions++;
1398  }
1399  break;
1400  case ':':
1401  if (egg->lang.oc == '\n' || egg->lang.oc == '}') {
1402  egg->lang.quoteline = '\n';
1403  } else {
1404  egg->lang.elem[egg->lang.elem_n++] = c;
1405  }
1406  break;
1407  case '#':
1408  if (egg->lang.oc == '\n') {
1409  egg->lang.skipline = 1;
1410  }
1411  break;
1412  case '/':
1413  if (egg->lang.oc == '/') {
1414  egg->lang.skipline = 1;
1415  } else {
1416  egg->lang.elem[egg->lang.elem_n++] = c;
1417  }
1418  break;
1419  default:
1420  egg->lang.elem[egg->lang.elem_n++] = c;
1421  }
1422  if (egg->lang.slurp) {
1423  if (egg->lang.elem_n) {
1424  ptr = egg->lang.elem;
1425  egg->lang.elem[egg->lang.elem_n] = '\0';
1426  while (is_space(*ptr)) {
1427  ptr++;
1428  }
1429  rcc_fun(egg, ptr);
1430  }
1431  egg->lang.elem_n = 0;
1432  }
1433  }
1434  if (c != '\t' && c != ' ') {
1435  egg->lang.oc = c;
1436  }
1437  return 0;
1438 }
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
#define e(frag)
#define emit(frag)
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
RZ_API void rz_egg_printf(RzEgg *egg, const char *fmt,...)
Definition: egg.c:336
static void rcc_next(RzEgg *egg)
Definition: egg_lang.c:978
static void rcc_reset_callname(RzEgg *egg)
Definition: egg_lang.c:179
static int is_op(char x)
Definition: egg_lang.c:23
static const char * find_alias(RzEgg *egg, const char *str)
Definition: egg_lang.c:222
RZ_API void rz_egg_lang_include_path(RzEgg *egg, const char *path)
Definition: egg_lang.c:149
static void rcc_pushstr(RzEgg *egg, char *str, int filter)
Definition: egg_lang.c:485
static int parsedatachar(RzEgg *egg, char c)
Definition: egg_lang.c:870
RZ_API void rz_egg_lang_init(RzEgg *egg)
Definition: egg_lang.c:126
static char * find_include(const char *prefix, const char *file)
Definition: egg_lang.c:75
RZ_API char * rz_egg_mkvar(RzEgg *egg, char *out, const char *_str, int delta)
Definition: egg_lang.c:538
#define CTX
Definition: egg_lang.c:6
static int is_var(char *x)
Definition: egg_lang.c:8
static void rcc_fun(RzEgg *egg, const char *str)
Definition: egg_lang.c:634
RZ_API int rz_egg_lang_parsechar(RzEgg *egg, char c)
Definition: egg_lang.c:1235
static void rcc_context(RzEgg *egg, int delta)
Definition: egg_lang.c:764
static void rcc_internal_mathop(RzEgg *egg, const char *ptr, char *ep, char op)
Definition: egg_lang.c:243
static void rcc_mathop(RzEgg *egg, char **pos, int level)
Definition: egg_lang.c:287
@ INLINE
Definition: egg_lang.c:67
@ ALIAS
Definition: egg_lang.c:64
@ SYSCALL
Definition: egg_lang.c:69
@ INCLUDE
Definition: egg_lang.c:65
@ NORMAL
Definition: egg_lang.c:63
@ NAKED
Definition: egg_lang.c:68
@ LAST
Definition: egg_lang.c:72
@ DATA
Definition: egg_lang.c:66
@ SYSCALLBODY
Definition: egg_lang.c:70
@ GOTO
Definition: egg_lang.c:71
static const char * skipspaces(const char *s)
Definition: egg_lang.c:16
static void rcc_set_callname(RzEgg *egg, const char *s)
Definition: egg_lang.c:172
static void rcc_element(RzEgg *egg, char *str)
Definition: egg_lang.c:345
#define FRAME_FMT
Definition: egg_lang.c:189
RZ_API void rz_egg_lang_include_init(RzEgg *egg)
Definition: egg_lang.c:164
static void rcc_pusharg(RzEgg *egg, char *str)
Definition: egg_lang.c:329
static char * trim(char *s)
Definition: egg_lang.c:49
RZ_API void rz_egg_lang_free(RzEgg *egg)
Definition: egg_lang.c:136
static int get_op(char **pos)
Definition: egg_lang.c:40
static int is_space(char c)
Definition: egg_lang.c:12
#define FRAME_END_FMT
Definition: egg_lang.c:190
static int parseinlinechar(RzEgg *egg, char c)
Definition: egg_lang.c:934
static void set_nested(RzEgg *egg, const char *s)
Definition: egg_lang.c:748
struct @667 g
unsigned short prefix[65536]
Definition: gun.c:163
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
sprintf
Definition: kernel.h:365
void * p
Definition: libc.cpp:67
static RzMain foo[]
Definition: main.c:11
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
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 x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define RZ_EGG_INCDIR_PATH
Definition: rz_egg.h:16
#define RZ_EGG_INCDIR_ENV
Definition: rz_egg.h:15
RZ_API bool rz_file_exists(const char *str)
Definition: file.c:192
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API int rz_hex_pair2bin(const char *arg)
Definition: hex.c:360
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API RZ_OWN char * rz_path_prefix(RZ_NULLABLE const char *path)
Return path prefixed by the Rizin install prefix.
Definition: path.c:121
RZ_API char * rz_str_appendf(char *ptr, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
RZ_API int rz_sys_setenv(const char *key, const char *value)
Set an environment variable in the calling process.
Definition: sys.c:405
#define RZ_FREE(x)
Definition: rz_types.h:369
static int
Definition: sfsocketcall.h:114
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
Definition: gzappend.c:170
Definition: dis.h:35
void(* comment)(RzEgg *egg, const char *fmt,...)
Definition: rz_egg.h:166
int attsyntax
Definition: rz_egg.h:51
int nsyscalls
Definition: rz_egg.h:32
int elem_n
Definition: rz_egg.h:52
char * body
Definition: rz_egg.h:73
char * setenviron
Definition: rz_egg.h:36
int nbrackets
Definition: rz_egg.h:46
char * file
Definition: rz_egg.h:56
int quoteline
Definition: rz_egg.h:64
char * syscallbody
Definition: rz_egg.h:34
int mode
Definition: rz_egg.h:69
int inlinectr
Definition: rz_egg.h:70
char * conditionstr
Definition: rz_egg.h:33
int stackfixed
Definition: rz_egg.h:67
int ninlines
Definition: rz_egg.h:76
int nestedi[32]
Definition: rz_egg.h:90
char * includefile
Definition: rz_egg.h:35
struct rz_egg_lang_t::@276 syscalls[256]
char * mathline
Definition: rz_egg.h:37
int slurpin
Definition: rz_egg.h:47
int stackframe
Definition: rz_egg.h:66
char * arg
Definition: rz_egg.h:79
int ndstval
Definition: rz_egg.h:62
int pushargs
Definition: rz_egg.h:30
int nalias
Definition: rz_egg.h:31
char * content
Definition: rz_egg.h:83
char * ctxpush[32]
Definition: rz_egg.h:55
struct rz_egg_lang_t::@277 aliases[256]
int nargs
Definition: rz_egg.h:43
char elem[1024]
Definition: rz_egg.h:50
char * dstval
Definition: rz_egg.h:58
int nfunctions
Definition: rz_egg.h:45
char * dstvar
Definition: rz_egg.h:57
int varsize
Definition: rz_egg.h:40
int varxs
Definition: rz_egg.h:41
char * nested[32]
Definition: rz_egg.h:85
int slurp
Definition: rz_egg.h:48
char * name
Definition: rz_egg.h:72
struct rz_egg_lang_t::@275 inlines[256]
char * ifelse_table[32][32]
Definition: rz_egg.h:60
char * endframe
Definition: rz_egg.h:54
int docall
Definition: rz_egg.h:44
char * includedir
Definition: rz_egg.h:59
char * nested_callname[32]
Definition: rz_egg.h:86
int quotelinevar
Definition: rz_egg.h:65
int lastctxdelta
Definition: rz_egg.h:42
int commentmode
Definition: rz_egg.h:39
char * callname
Definition: rz_egg.h:53
int skipline
Definition: rz_egg.h:63
int line
Definition: rz_egg.h:49
struct rz_egg_emit_t * remit
Definition: rz_egg.h:105
RzEggLang lang
Definition: rz_egg.h:101
int pos
Definition: main.c:11
static char ** env
Definition: sys.c:32
Definition: dis.c:32
static int level
Definition: vmenus.c:2424
static st64 delta
Definition: vmenus.c:2425