Unified · Split
| @@ -270,6 +270,7 @@ int rsym, anon_sym, · 269 unmodified lines | ||
| 270 | 270 | prog, ind, loc; |
| 271 | 271 | /* expression generation modifiers */ |
| 272 | 272 | int const_wanted; /* true if constant wanted */ |
| 273 | +int nocode_wanted; /* true if no code generation wanted for an expression */ | |
| 273 | 274 | int global_expr; /* true if compound literals must be allocated |
| 274 | 275 | globally (used during initializers parsing */ |
| 275 | 276 | int func_vt, func_vc; /* current function return type (used by |
| @@ -490,83 +491,20 @@ static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224< · 214 unmodified lines | ||
| 490 | 491 | #define TOK_IDENT 256 |
| 491 | 492 | |
| 492 | 493 | enum { |
| 493 | − TOK_INT = TOK_IDENT, | |
| 494 | − TOK_VOID, | |
| 495 | − TOK_CHAR, | |
| 496 | − TOK_IF, | |
| 497 | − TOK_ELSE, | |
| 498 | − TOK_WHILE, | |
| 499 | − TOK_BREAK, | |
| 500 | − TOK_RETURN, | |
| 501 | − TOK_FOR, | |
| 502 | − TOK_EXTERN, | |
| 503 | − TOK_STATIC, | |
| 504 | − TOK_UNSIGNED, | |
| 505 | − TOK_GOTO, | |
| 506 | − TOK_DO, | |
| 507 | − TOK_CONTINUE, | |
| 508 | − TOK_SWITCH, | |
| 509 | − TOK_CASE, | |
| 510 | − | |
| 511 | − /* ignored types Must have contiguous values */ | |
| 512 | − TOK_CONST, | |
| 513 | − TOK_VOLATILE, | |
| 514 | − TOK_LONG, | |
| 515 | − TOK_REGISTER, | |
| 516 | − TOK_SIGNED, | |
| 517 | − TOK___SIGNED__, /* gcc keyword */ | |
| 518 | − TOK_AUTO, | |
| 519 | − TOK_INLINE, | |
| 520 | − TOK___INLINE__, /* gcc keyword */ | |
| 521 | − TOK_RESTRICT, | |
| 522 | − | |
| 523 | − /* unsupported type */ | |
| 524 | − TOK_FLOAT, | |
| 525 | − TOK_DOUBLE, | |
| 526 | − TOK_BOOL, | |
| 527 | − | |
| 528 | − TOK_SHORT, | |
| 529 | − TOK_STRUCT, | |
| 530 | − TOK_UNION, | |
| 531 | − TOK_TYPEDEF, | |
| 532 | − TOK_DEFAULT, | |
| 533 | − TOK_ENUM, | |
| 534 | − TOK_SIZEOF, | |
| 535 | − TOK___ATTRIBUTE__, | |
| 536 | − | |
| 537 | − /* preprocessor only */ | |
| 538 | − TOK_UIDENT, /* first "user" ident (not keyword) */ | |
| 539 | − TOK_DEFINE = TOK_UIDENT, | |
| 540 | − TOK_INCLUDE, | |
| 541 | − TOK_IFDEF, | |
| 542 | − TOK_IFNDEF, | |
| 543 | − TOK_ELIF, | |
| 544 | − TOK_ENDIF, | |
| 545 | − TOK_DEFINED, | |
| 546 | − TOK_UNDEF, | |
| 547 | − TOK_ERROR, | |
| 548 | − TOK_LINE, | |
| 549 | − | |
| 494 | + TOK_LAST = TOK_IDENT - 1, | |
| 550 | 495 | #define DEF(id, str) id, |
| 551 | 496 | #include "tcctok.h" |
| 552 | 497 | #undef DEF |
| 553 | 498 | }; |
| 554 | 499 | |
| 555 | −char *tcc_keywords = | |
| 556 | −"int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0" | |
| 557 | −"unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0" | |
| 558 | −"register\0signed\0__signed__\0auto\0inline\0__inline__\0restrict\0" | |
| 559 | −"float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0" | |
| 560 | −"sizeof\0__attribute__\0" | |
| 561 | −/* the following are not keywords. They are included to ease parsing */ | |
| 562 | −"define\0include\0ifdef\0ifndef\0elif\0endif\0" | |
| 563 | −"defined\0undef\0error\0line\0" | |
| 564 | −/* builtin functions */ | |
| 500 | +static const char *tcc_keywords = | |
| 565 | 501 | #define DEF(id, str) str "\0" |
| 566 | 502 | #include "tcctok.h" |
| 567 | 503 | #undef DEF |
| 568 | 504 | ; |
| 569 | 505 | |
| 506 | +#define TOK_UIDENT TOK_DEFINE | |
| 507 | + | |
| 570 | 508 | #ifdef WIN32 |
| 571 | 509 | #define snprintf _snprintf |
| 572 | 510 | #endif |
| @@ -590,13 +528,16 @@ extern long double strtold (const char *__nptr, char **__endptr); · 17 unmodified lines | ||
| 590 | 528 | static char *pstrcpy(char *buf, int buf_size, const char *s); |
| 591 | 529 | static char *pstrcat(char *buf, int buf_size, const char *s); |
| 592 | 530 | |
| 593 | −void sum(int l); | |
| 594 | −void next(void); | |
| 595 | −void next_nomacro(void); | |
| 531 | +static void sum(int l); | |
| 532 | +static void next(void); | |
| 533 | +static void next_nomacro(void); | |
| 534 | +static int parse_expr_type(void); | |
| 535 | +static int expr_type(void); | |
| 536 | +static int unary_type(void); | |
| 596 | 537 | static int expr_const(void); |
| 597 | −void expr_eq(void); | |
| 598 | −void gexpr(void); | |
| 599 | −void decl(int l); | |
| 538 | +static void expr_eq(void); | |
| 539 | +static void gexpr(void); | |
| 540 | +static void decl(int l); | |
| 600 | 541 | static void decl_initializer(int t, Section *sec, unsigned long c, |
| 601 | 542 | int first, int size_only); |
| 602 | 543 | static void decl_initializer_alloc(int t, AttributeDef *ad, int r, |
| @@ -1301,12 +1242,12 @@ char *get_tok_str(int v, CValue *cv) · 698 unmodified lines | ||
| 1301 | 1242 | switch(v) { |
| 1302 | 1243 | case TOK_CINT: |
| 1303 | 1244 | case TOK_CUINT: |
| 1304 | − /* XXX: not quite exact, but useful for ## in macros */ | |
| 1245 | + /* XXX: not quite exact, but only useful for testing */ | |
| 1305 | 1246 | sprintf(p, "%u", cv->ui); |
| 1306 | 1247 | break; |
| 1307 | 1248 | case TOK_CLLONG: |
| 1308 | 1249 | case TOK_CULLONG: |
| 1309 | − /* XXX: not quite exact, but useful for ## in macros */ | |
| 1250 | + /* XXX: not quite exact, but only useful for testing */ | |
| 1310 | 1251 | sprintf(p, "%Lu", cv->ull); |
| 1311 | 1252 | break; |
| 1312 | 1253 | case TOK_CCHAR: |
| @@ -1321,6 +1262,7 @@ char *get_tok_str(int v, CValue *cv) · 8 unmodified lines | ||
| 1321 | 1262 | len = cstr->size - 1; |
| 1322 | 1263 | for(i=0;i<len;i++) |
| 1323 | 1264 | add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]); |
| 1265 | + cstr_ccat(&cstr_buf, '\0'); | |
| 1324 | 1266 | break; |
| 1325 | 1267 | case TOK_STR: |
| 1326 | 1268 | case TOK_LSTR: |
| @@ -2754,7 +2696,7 @@ static inline void next_nomacro1(void) · 1427 unmodified lines | ||
| 2754 | 2696 | |
| 2755 | 2697 | /* return next token without macro substitution. Can read input from |
| 2756 | 2698 | macro_ptr buffer */ |
| 2757 | −void next_nomacro() | |
| 2699 | +static void next_nomacro(void) | |
| 2758 | 2700 | { |
| 2759 | 2701 | if (macro_ptr) { |
| 2760 | 2702 | redo: |
| @@ -2772,7 +2714,7 @@ void next_nomacro() · 11 unmodified lines | ||
| 2772 | 2714 | } |
| 2773 | 2715 | |
| 2774 | 2716 | /* substitute args in macro_str and return allocated string */ |
| 2775 | −int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) | |
| 2717 | +static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) | |
| 2776 | 2718 | { |
| 2777 | 2719 | int *st, last_tok, t, notfirst; |
| 2778 | 2720 | Sym *s; |
| @@ -2894,7 +2836,7 @@ static int *macro_twosharps(void) · 115 unmodified lines | ||
| 2894 | 2836 | p2 = get_tok_str(t, &cval); |
| 2895 | 2837 | cstr_cat(&cstr, p2); |
| 2896 | 2838 | cstr_ccat(&cstr, '\0'); |
| 2897 | − | |
| 2839 | + | |
| 2898 | 2840 | if ((tok >= TOK_IDENT || tok == TOK_PPNUM) && |
| 2899 | 2841 | (t >= TOK_IDENT || t == TOK_PPNUM)) { |
| 2900 | 2842 | if (tok == TOK_PPNUM) { |
| @@ -3130,7 +3072,7 @@ static void macro_subst(TokenString *tok_str, · 229 unmodified lines | ||
| 3130 | 3072 | } |
| 3131 | 3073 | |
| 3132 | 3074 | /* return next token with macro substitution */ |
| 3133 | −void next(void) | |
| 3075 | +static void next(void) | |
| 3134 | 3076 | { |
| 3135 | 3077 | Sym *nested_list, *s; |
| 3136 | 3078 | TokenString str; |
| @@ -3670,7 +3612,7 @@ void vpop(void) · 533 unmodified lines | ||
| 3670 | 3612 | v = vtop->r & VT_VALMASK; |
| 3671 | 3613 | #ifdef TCC_TARGET_I386 |
| 3672 | 3614 | /* for x86, we need to pop the FP stack */ |
| 3673 | − if (v == REG_ST0) { | |
| 3615 | + if (v == REG_ST0 && !nocode_wanted) { | |
| 3674 | 3616 | o(0xd9dd); /* fstp %st(1) */ |
| 3675 | 3617 | } else |
| 3676 | 3618 | #endif |
| @@ -4045,8 +3987,12 @@ void gen_opic(int op) · 368 unmodified lines | ||
| 4045 | 3987 | vtop->c.i += fc; |
| 4046 | 3988 | } else { |
| 4047 | 3989 | general_case: |
| 4048 | − /* call low level op generator */ | |
| 4049 | − gen_opi(op); | |
| 3990 | + if (!nocode_wanted) { | |
| 3991 | + /* call low level op generator */ | |
| 3992 | + gen_opi(op); | |
| 3993 | + } else { | |
| 3994 | + vtop--; | |
| 3995 | + } | |
| 4050 | 3996 | } |
| 4051 | 3997 | } |
| 4052 | 3998 | } |
| @@ -4107,7 +4053,11 @@ void gen_opif(int op) · 54 unmodified lines | ||
| 4107 | 4053 | vtop--; |
| 4108 | 4054 | } else { |
| 4109 | 4055 | general_case: |
| 4110 | − gen_opf(op); | |
| 4056 | + if (!nocode_wanted) { | |
| 4057 | + gen_opf(op); | |
| 4058 | + } else { | |
| 4059 | + vtop--; | |
| 4060 | + } | |
| 4111 | 4061 | } |
| 4112 | 4062 | } |
| 4113 | 4063 | |
| @@ -4355,7 +4305,7 @@ void gen_cast(int t) · 241 unmodified lines | ||
| 4355 | 4305 | dbt = t & (VT_BTYPE | VT_UNSIGNED); |
| 4356 | 4306 | sbt = vtop->t & (VT_BTYPE | VT_UNSIGNED); |
| 4357 | 4307 | |
| 4358 | − if (sbt != dbt) { | |
| 4308 | + if (sbt != dbt && !nocode_wanted) { | |
| 4359 | 4309 | sf = is_float(sbt); |
| 4360 | 4310 | df = is_float(dbt); |
| 4361 | 4311 | c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
| @@ -4749,25 +4699,30 @@ void vstore(void) · 387 unmodified lines | ||
| 4749 | 4699 | /* if structure, only generate pointer */ |
| 4750 | 4700 | /* structure assignment : generate memcpy */ |
| 4751 | 4701 | /* XXX: optimize if small size */ |
| 4752 | − vdup(); | |
| 4753 | − gfunc_start(&gf, FUNC_CDECL); | |
| 4754 | − /* type size */ | |
| 4755 | − size = type_size(vtop->t, &align); | |
| 4756 | − vpushi(size); | |
| 4757 | − gfunc_param(&gf); | |
| 4758 | − /* source */ | |
| 4759 | − vtop->t = VT_INT; | |
| 4760 | − gaddrof(); | |
| 4761 | − gfunc_param(&gf); | |
| 4762 | − /* destination */ | |
| 4763 | − vswap(); | |
| 4764 | − vtop->t = VT_INT; | |
| 4765 | − gaddrof(); | |
| 4766 | − gfunc_param(&gf); | |
| 4767 | − | |
| 4768 | − save_regs(0); | |
| 4769 | − vpush_global_sym(func_old_type, TOK_memcpy); | |
| 4770 | − gfunc_call(&gf); | |
| 4702 | + if (!nocode_wanted) { | |
| 4703 | + vdup(); | |
| 4704 | + gfunc_start(&gf, FUNC_CDECL); | |
| 4705 | + /* type size */ | |
| 4706 | + size = type_size(vtop->t, &align); | |
| 4707 | + vpushi(size); | |
| 4708 | + gfunc_param(&gf); | |
| 4709 | + /* source */ | |
| 4710 | + vtop->t = VT_INT; | |
| 4711 | + gaddrof(); | |
| 4712 | + gfunc_param(&gf); | |
| 4713 | + /* destination */ | |
| 4714 | + vswap(); | |
| 4715 | + vtop->t = VT_INT; | |
| 4716 | + gaddrof(); | |
| 4717 | + gfunc_param(&gf); | |
| 4718 | + | |
| 4719 | + save_regs(0); | |
| 4720 | + vpush_global_sym(func_old_type, TOK_memcpy); | |
| 4721 | + gfunc_call(&gf); | |
| 4722 | + } else { | |
| 4723 | + vswap(); | |
| 4724 | + vpop(); | |
| 4725 | + } | |
| 4771 | 4726 | /* leave source on stack */ |
| 4772 | 4727 | } else if (ft & VT_BITFIELD) { |
| 4773 | 4728 | /* bitfield store handling */ |
| @@ -4801,33 +4756,35 @@ void vstore(void) · 27 unmodified lines | ||
| 4801 | 4756 | vswap(); |
| 4802 | 4757 | } |
| 4803 | 4758 | #endif |
| 4804 | − rc = RC_INT; | |
| 4805 | − if (is_float(ft)) | |
| 4806 | − rc = RC_FLOAT; | |
| 4807 | − r = gv(rc); /* generate value */ | |
| 4808 | − /* if lvalue was saved on stack, must read it */ | |
| 4809 | − if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { | |
| 4810 | − SValue sv; | |
| 4811 | − t = get_reg(RC_INT); | |
| 4812 | − sv.t = VT_INT; | |
| 4813 | − sv.r = VT_LOCAL | VT_LVAL; | |
| 4814 | − sv.c.ul = vtop[-1].c.ul; | |
| 4815 | − load(t, &sv); | |
| 4816 | − vtop[-1].r = t | VT_LVAL; | |
| 4817 | − } | |
| 4818 | − store(r, vtop - 1); | |
| 4819 | − /* two word case handling : store second register at word + 4 */ | |
| 4820 | − if ((ft & VT_BTYPE) == VT_LLONG) { | |
| 4821 | − vswap(); | |
| 4822 | − /* convert to int to increment easily */ | |
| 4823 | − vtop->t = VT_INT; | |
| 4824 | − gaddrof(); | |
| 4825 | − vpushi(4); | |
| 4826 | − gen_op('+'); | |
| 4827 | − vtop->r |= VT_LVAL; | |
| 4828 | − vswap(); | |
| 4829 | − /* XXX: it works because r2 is spilled last ! */ | |
| 4830 | − store(vtop->r2, vtop - 1); | |
| 4759 | + if (!nocode_wanted) { | |
| 4760 | + rc = RC_INT; | |
| 4761 | + if (is_float(ft)) | |
| 4762 | + rc = RC_FLOAT; | |
| 4763 | + r = gv(rc); /* generate value */ | |
| 4764 | + /* if lvalue was saved on stack, must read it */ | |
| 4765 | + if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { | |
| 4766 | + SValue sv; | |
| 4767 | + t = get_reg(RC_INT); | |
| 4768 | + sv.t = VT_INT; | |
| 4769 | + sv.r = VT_LOCAL | VT_LVAL; | |
| 4770 | + sv.c.ul = vtop[-1].c.ul; | |
| 4771 | + load(t, &sv); | |
| 4772 | + vtop[-1].r = t | VT_LVAL; | |
| 4773 | + } | |
| 4774 | + store(r, vtop - 1); | |
| 4775 | + /* two word case handling : store second register at word + 4 */ | |
| 4776 | + if ((ft & VT_BTYPE) == VT_LLONG) { | |
| 4777 | + vswap(); | |
| 4778 | + /* convert to int to increment easily */ | |
| 4779 | + vtop->t = VT_INT; | |
| 4780 | + gaddrof(); | |
| 4781 | + vpushi(4); | |
| 4782 | + gen_op('+'); | |
| 4783 | + vtop->r |= VT_LVAL; | |
| 4784 | + vswap(); | |
| 4785 | + /* XXX: it works because r2 is spilled last ! */ | |
| 4786 | + store(vtop->r2, vtop - 1); | |
| 4787 | + } | |
| 4831 | 4788 | } |
| 4832 | 4789 | vswap(); |
| 4833 | 4790 | vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ |
| @@ -5188,6 +5145,11 @@ int parse_btype(int *type_ptr, AttributeDef *ad) · 354 unmodified lines | ||
| 5188 | 5145 | case TOK___ATTRIBUTE__: |
| 5189 | 5146 | parse_attribute(ad); |
| 5190 | 5147 | break; |
| 5148 | + /* GNUC typeof */ | |
| 5149 | + case TOK_TYPEOF: | |
| 5150 | + next(); | |
| 5151 | + u = parse_expr_type(); | |
| 5152 | + goto basic_type1; | |
| 5191 | 5153 | default: |
| 5192 | 5154 | s = sym_find(tok); |
| 5193 | 5155 | if (!s || !(s->t & VT_TYPEDEF)) |
| @@ -5367,7 +5329,7 @@ static void indir(void) · 173 unmodified lines | ||
| 5367 | 5329 | { |
| 5368 | 5330 | if ((vtop->t & VT_BTYPE) != VT_PTR) |
| 5369 | 5331 | expect("pointer"); |
| 5370 | − if (vtop->r & VT_LVAL) | |
| 5332 | + if ((vtop->r & VT_LVAL) && !nocode_wanted) | |
| 5371 | 5333 | gv(RC_INT); |
| 5372 | 5334 | vtop->t = pointed_type(vtop->t); |
| 5373 | 5335 | /* an array is never an lvalue */ |
| @@ -5394,10 +5356,31 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg) · 20 unmodified lines | ||
| 5394 | 5356 | } else { |
| 5395 | 5357 | gen_assign_cast(arg->t); |
| 5396 | 5358 | } |
| 5397 | − gfunc_param(gf); | |
| 5359 | + if (!nocode_wanted) { | |
| 5360 | + gfunc_param(gf); | |
| 5361 | + } else { | |
| 5362 | + vpop(); | |
| 5363 | + } | |
| 5364 | +} | |
| 5365 | + | |
| 5366 | +/* parse an expression of the form '(type)' or '(expr)' and return its | |
| 5367 | + type */ | |
| 5368 | +static int parse_expr_type(void) | |
| 5369 | +{ | |
| 5370 | + int ft, n; | |
| 5371 | + AttributeDef ad; | |
| 5372 | + | |
| 5373 | + skip('('); | |
| 5374 | + if (parse_btype(&ft, &ad)) { | |
| 5375 | + ft = type_decl(&ad, &n, ft, TYPE_ABSTRACT); | |
| 5376 | + } else { | |
| 5377 | + ft = expr_type(); | |
| 5378 | + } | |
| 5379 | + skip(')'); | |
| 5380 | + return ft; | |
| 5398 | 5381 | } |
| 5399 | 5382 | |
| 5400 | −void unary(void) | |
| 5383 | +static void unary(void) | |
| 5401 | 5384 | { |
| 5402 | 5385 | int n, t, ft, align, size, r; |
| 5403 | 5386 | Sym *s; |
| @@ -5515,25 +5498,17 @@ void unary(void) · 111 unmodified lines | ||
| 5515 | 5498 | vpushi(0); |
| 5516 | 5499 | gen_op('+'); |
| 5517 | 5500 | } else |
| 5518 | − if (t == TOK_SIZEOF) { | |
| 5501 | + if (t == TOK_SIZEOF || t == TOK_ALIGNOF) { | |
| 5519 | 5502 | if (tok == '(') { |
| 5520 | − next(); | |
| 5521 | − if (parse_btype(&t, &ad)) { | |
| 5522 | − t = type_decl(&ad, &n, t, TYPE_ABSTRACT); | |
| 5523 | − } else { | |
| 5524 | − /* XXX: some code could be generated: add eval | |
| 5525 | − flag */ | |
| 5526 | − gexpr(); | |
| 5527 | − t = vtop->t; | |
| 5528 | − vpop(); | |
| 5529 | − } | |
| 5530 | − skip(')'); | |
| 5503 | + ft = parse_expr_type(); | |
| 5531 | 5504 | } else { |
| 5532 | − unary(); | |
| 5533 | − t = vtop->t; | |
| 5534 | − vpop(); | |
| 5505 | + ft = unary_type(); | |
| 5535 | 5506 | } |
| 5536 | − vpushi(type_size(t, &t)); | |
| 5507 | + size = type_size(ft, &align); | |
| 5508 | + if (t == TOK_SIZEOF) | |
| 5509 | + vpushi(size); | |
| 5510 | + else | |
| 5511 | + vpushi(align); | |
| 5537 | 5512 | } else |
| 5538 | 5513 | if (t == TOK_INC || t == TOK_DEC) { |
| 5539 | 5514 | unary(); |
| @@ -5627,8 +5602,10 @@ void unary(void) · 87 unmodified lines | ||
| 5627 | 5602 | } |
| 5628 | 5603 | /* get return type */ |
| 5629 | 5604 | s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT); |
| 5630 | − save_regs(0); /* save used temporary registers */ | |
| 5631 | − gfunc_start(&gf, s->r); | |
| 5605 | + if (!nocode_wanted) { | |
| 5606 | + save_regs(0); /* save used temporary registers */ | |
| 5607 | + gfunc_start(&gf, s->r); | |
| 5608 | + } | |
| 5632 | 5609 | next(); |
| 5633 | 5610 | sa = s->next; /* first parameter */ |
| 5634 | 5611 | #ifdef INVERT_FUNC_PARAMS |
| @@ -5693,7 +5670,10 @@ void unary(void) · 58 unmodified lines | ||
| 5693 | 5670 | problems */ |
| 5694 | 5671 | vset(VT_INT, VT_LOCAL, loc); |
| 5695 | 5672 | ret.c = vtop->c; |
| 5696 | − gfunc_param(&gf); | |
| 5673 | + if (!nocode_wanted) | |
| 5674 | + gfunc_param(&gf); | |
| 5675 | + else | |
| 5676 | + vtop--; | |
| 5697 | 5677 | } else { |
| 5698 | 5678 | ret.t = s->t; |
| 5699 | 5679 | ret.r2 = VT_CONST; |
| @@ -5723,7 +5703,10 @@ void unary(void) · 23 unmodified lines | ||
| 5723 | 5703 | if (sa) |
| 5724 | 5704 | error("too few arguments to function"); |
| 5725 | 5705 | skip(')'); |
| 5726 | − gfunc_call(&gf); | |
| 5706 | + if (!nocode_wanted) | |
| 5707 | + gfunc_call(&gf); | |
| 5708 | + else | |
| 5709 | + vtop--; | |
| 5727 | 5710 | /* return value */ |
| 5728 | 5711 | vsetc(ret.t, ret.r, &ret.c); |
| 5729 | 5712 | vtop->r2 = ret.r2; |
| @@ -5733,7 +5716,7 @@ void unary(void) · 3 unmodified lines | ||
| 5733 | 5716 | } |
| 5734 | 5717 | } |
| 5735 | 5718 | |
| 5736 | −void uneq(void) | |
| 5719 | +static void uneq(void) | |
| 5737 | 5720 | { |
| 5738 | 5721 | int t; |
| 5739 | 5722 | |
| @@ -5756,7 +5739,7 @@ void uneq(void) · 16 unmodified lines | ||
| 5756 | 5739 | } |
| 5757 | 5740 | } |
| 5758 | 5741 | |
| 5759 | −void sum(int l) | |
| 5742 | +static void sum(int l) | |
| 5760 | 5743 | { |
| 5761 | 5744 | int t; |
| 5762 | 5745 | |
| @@ -5784,7 +5767,7 @@ void sum(int l) · 21 unmodified lines | ||
| 5784 | 5767 | } |
| 5785 | 5768 | |
| 5786 | 5769 | /* only used if non constant */ |
| 5787 | −void eand(void) | |
| 5770 | +static void eand(void) | |
| 5788 | 5771 | { |
| 5789 | 5772 | int t; |
| 5790 | 5773 | |
| @@ -5804,7 +5787,7 @@ void eand(void) · 13 unmodified lines | ||
| 5804 | 5787 | } |
| 5805 | 5788 | } |
| 5806 | 5789 | |
| 5807 | −void eor(void) | |
| 5790 | +static void eor(void) | |
| 5808 | 5791 | { |
| 5809 | 5792 | int t; |
| 5810 | 5793 | |
| @@ -5825,7 +5808,7 @@ void eor(void) · 14 unmodified lines | ||
| 5825 | 5808 | } |
| 5826 | 5809 | |
| 5827 | 5810 | /* XXX: better constant handling */ |
| 5828 | −void expr_eq(void) | |
| 5811 | +static void expr_eq(void) | |
| 5829 | 5812 | { |
| 5830 | 5813 | int tt, u, r1, r2, rc, t1, t2, t, bt1, bt2; |
| 5831 | 5814 | SValue sv; |
| @@ -5925,7 +5908,7 @@ void expr_eq(void) · 93 unmodified lines | ||
| 5925 | 5908 | } |
| 5926 | 5909 | } |
| 5927 | 5910 | |
| 5928 | −void gexpr(void) | |
| 5911 | +static void gexpr(void) | |
| 5929 | 5912 | { |
| 5930 | 5913 | while (1) { |
| 5931 | 5914 | expr_eq(); |
| @@ -5936,6 +5919,35 @@ void gexpr(void) · 4 unmodified lines | ||
| 5936 | 5919 | } |
| 5937 | 5920 | } |
| 5938 | 5921 | |
| 5922 | +/* parse an expression and return its type without any side effect. */ | |
| 5923 | +static int expr_type(void) | |
| 5924 | +{ | |
| 5925 | + int a, t; | |
| 5926 | + | |
| 5927 | + a = nocode_wanted; | |
| 5928 | + nocode_wanted = 1; | |
| 5929 | + gexpr(); | |
| 5930 | + t = vtop->t; | |
| 5931 | + vpop(); | |
| 5932 | + nocode_wanted = a; | |
| 5933 | + return t; | |
| 5934 | +} | |
| 5935 | + | |
| 5936 | +/* parse a unary expression and return its type without any side | |
| 5937 | + effect. */ | |
| 5938 | +static int unary_type(void) | |
| 5939 | +{ | |
| 5940 | + int a, t; | |
| 5941 | + | |
| 5942 | + a = nocode_wanted; | |
| 5943 | + nocode_wanted = 1; | |
| 5944 | + unary(); | |
| 5945 | + t = vtop->t; | |
| 5946 | + vpop(); | |
| 5947 | + nocode_wanted = a; | |
| 5948 | + return t; | |
| 5949 | +} | |
| 5950 | + | |
| 5939 | 5951 | /* parse a constant expression and return value in vtop. */ |
| 5940 | 5952 | static void expr_const1(void) |
| 5941 | 5953 | { |
| @@ -5960,7 +5972,7 @@ static int expr_const(void) · 18 unmodified lines | ||
| 5960 | 5972 | |
| 5961 | 5973 | /* return the label token if current token is a label, otherwise |
| 5962 | 5974 | return zero */ |
| 5963 | −int is_label(void) | |
| 5975 | +static int is_label(void) | |
| 5964 | 5976 | { |
| 5965 | 5977 | int t; |
| 5966 | 5978 | CValue c; |
| @@ -5985,7 +5997,7 @@ int is_label(void) · 18 unmodified lines | ||
| 5985 | 5997 | } |
| 5986 | 5998 | } |
| 5987 | 5999 | |
| 5988 | −void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) | |
| 6000 | +static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) | |
| 5989 | 6001 | { |
| 5990 | 6002 | int a, b, c, d; |
| 5991 | 6003 | Sym *s; |
| @@ -6819,8 +6831,52 @@ void analyse_function(void) · 827 unmodified lines | ||
| 6819 | 6831 | } |
| 6820 | 6832 | #endif |
| 6821 | 6833 | |
| 6834 | +/* parse an old style function declaration list */ | |
| 6835 | +/* XXX: check multiple parameter */ | |
| 6836 | +static void func_decl_list(Sym *func_sym) | |
| 6837 | +{ | |
| 6838 | + AttributeDef ad; | |
| 6839 | + int b, v, t; | |
| 6840 | + Sym *s; | |
| 6841 | + /* parse each declaration */ | |
| 6842 | + while (tok != '{' && tok != ';' && tok != TOK_EOF) { | |
| 6843 | + if (!parse_btype(&b, &ad)) | |
| 6844 | + expect("declaration list"); | |
| 6845 | + if (((b & VT_BTYPE) == VT_ENUM || | |
| 6846 | + (b & VT_BTYPE) == VT_STRUCT) && | |
| 6847 | + tok == ';') { | |
| 6848 | + /* we accept no variable after */ | |
| 6849 | + } else { | |
| 6850 | + for(;;) { | |
| 6851 | + t = type_decl(&ad, &v, b, TYPE_DIRECT); | |
| 6852 | + /* find parameter in function parameter list */ | |
| 6853 | + s = func_sym->next; | |
| 6854 | + while (s != NULL) { | |
| 6855 | + if ((s->v & ~SYM_FIELD) == v) | |
| 6856 | + goto found; | |
| 6857 | + s = s->next; | |
| 6858 | + } | |
| 6859 | + error("declaration for parameter '%s' but no such parameter", | |
| 6860 | + get_tok_str(v, NULL)); | |
| 6861 | + found: | |
| 6862 | + /* check that no storage specifier except 'register' was given */ | |
| 6863 | + if (t & (VT_EXTERN | VT_STATIC | VT_TYPEDEF)) | |
| 6864 | + error("storage class specified for '%s'", get_tok_str(v, NULL)); | |
| 6865 | + /* we can add the type (NOTE: it could be local to the function) */ | |
| 6866 | + s->t = t; | |
| 6867 | + /* accept other parameters */ | |
| 6868 | + if (tok == ',') | |
| 6869 | + next(); | |
| 6870 | + else | |
| 6871 | + break; | |
| 6872 | + } | |
| 6873 | + } | |
| 6874 | + skip(';'); | |
| 6875 | + } | |
| 6876 | +} | |
| 6877 | + | |
| 6822 | 6878 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ |
| 6823 | −void decl(int l) | |
| 6879 | +static void decl(int l) | |
| 6824 | 6880 | { |
| 6825 | 6881 | int t, b, v, has_init, r; |
| 6826 | 6882 | Sym *sym; |
| @@ -6856,6 +6912,14 @@ void decl(int l) · 29 unmodified lines | ||
| 6856 | 6912 | printf("type = '%s'\n", buf); |
| 6857 | 6913 | } |
| 6858 | 6914 | #endif |
| 6915 | + if ((t & VT_BTYPE) == VT_FUNC) { | |
| 6916 | + /* if old style function prototype, we accept a | |
| 6917 | + declaration list */ | |
| 6918 | + sym = sym_find(((unsigned)t >> VT_STRUCT_SHIFT)); | |
| 6919 | + if (sym->c == FUNC_OLD) | |
| 6920 | + func_decl_list(sym); | |
| 6921 | + } | |
| 6922 | + | |
| 6859 | 6923 | if (tok == '{') { |
| 6860 | 6924 | #ifdef CONFIG_REG_VARS |
| 6861 | 6925 | TokenString func_str; |
| @@ -7392,7 +7456,7 @@ int tcc_run(TCCState *s1, int argc, char **argv) · 530 unmodified lines | ||
| 7392 | 7456 | |
| 7393 | 7457 | TCCState *tcc_new(void) |
| 7394 | 7458 | { |
| 7395 | − char *p, *r; | |
| 7459 | + const char *p, *r; | |
| 7396 | 7460 | TCCState *s; |
| 7397 | 7461 | |
| 7398 | 7462 | s = tcc_mallocz(sizeof(TCCState)); |