ADDED Makefile.in Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -0,0 +1,49 @@ +CC = @CC@ +AR = @AR@ +RANLIB = @RANLIB@ +CFLAGS = @CFLAGS@ @SHOBJFLAGS@ +CPPFLAGS = @CPPFLAGS@ -I@srcdir@ @DEFS@ +LDFLAGS = +SHOBJLDFLAGS = @SHOBJLDFLAGS@ +LIBS = @LIBS@ +INSTALL = @INSTALL@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@ +PACKAGE_INSTALL_DIR = $(TCL_PACKAGE_PATH)/$(PACKAGE_NAME)-$(PACKAGE_VERSION) +TARGETS = @TARGETS@ +srcdir = @srcdir@ + +all: $(TARGETS) + +tcltcc.o: $(srcdir)/tcltcc.c + $(CC) $(CPPFLAGS) $(CFLAGS) -o tcltcc.o -c $(srcdir)/tcltcc.c + +tcltcc-shared.@SHOBJEXT@: tcltcc.o + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(SHOBJLDFLAGS) -o tcltcc-shared.@SHOBJEXT@ tcltcc.o $(LIBS) + +tcltcc-static.a: tcltcc.o + $(AR) rcu tcltcc-static.a tcltcc.o + -$(RANLIB) tcltcc-static.a + +install: $(TARGETS) pkgIndex.tcl + $(INSTALL) -d "$(DESTDIR)$(PACKAGE_INSTALL_DIR)" + $(INSTALL) -m 0644 pkgIndex.tcl "$(DESTDIR)$(PACKAGE_INSTALL_DIR)" + $(INSTALL) -m 0755 $(TARGETS) "$(DESTDIR)$(PACKAGE_INSTALL_DIR)" + +clean: + rm -f tcltcc.o + rm -f tcltcc-shared.@SHOBJEXT@ tcltcc-static.a + rm -f tcltcc-shared.@SHOBJEXT@.a tcltcc-shared.@SHOBJEXT@.def + +distclean: clean + rm -rf autom4te.cache + rm -f config.log config.status + rm -f pkgIndex.tcl + rm -f Makefile + +mrproper: distclean + rm -f configure aclocal.m4 + rm -f config.guess config.sub install-sh + +.PHONY: all install clean distclean mrproper ADDED build/autogen.sh Index: build/autogen.sh ================================================================== --- build/autogen.sh +++ build/autogen.sh @@ -0,0 +1,5 @@ +#! /bin/bash + +aclocal -I aclocal +autoconf +rm -rf autom4te.cache ADDED build/pre.sh Index: build/pre.sh ================================================================== --- build/pre.sh +++ build/pre.sh @@ -0,0 +1,19 @@ +#! /bin/bash + +cd "$(dirname "$(which "$0")")/.." || exit 1 + +# Download latest copy of autoconf macros +( + cd aclocal || exit 1 + + for file in shobj.m4 tcl.m4 versionscript.m4; do + rm -f "${file}" + + wget -O "${file}.new" "http://rkeene.org/devel/autoconf/${file}.m4" || continue + + mv "${file}.new" "${file}" + done +) + +# Generate configure script +./build/autogen.sh ADDED build/tcltcc-0.4-versus-tcc-1rsk.diff Index: build/tcltcc-0.4-versus-tcc-1rsk.diff ================================================================== --- build/tcltcc-0.4-versus-tcc-1rsk.diff +++ build/tcltcc-0.4-versus-tcc-1rsk.diff @@ -0,0 +1,18436 @@ +--- tcc-0.9.24/alloca86.S 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/i386/alloca86.S 2007-11-07 10:04:30.000000000 -0500 +@@ -1,33 +1,41 @@ +-/* ---------------------------------------------- */ +-/* alloca86.S */ +- +-#include "config.h" +- +-.globl _alloca ++/* Implementation of alloca() for tinycc (tcc) on x86. ++ * Based on grischka case_8, modified by David A. Wheeler 2007-05-09. ++ * Plays games with stack, so it omits the usual prologue and epilogue. ++ * We use the normal cdecl calling convention to reduce the risk of error. */ ++ ++ ++/* alloca_padding is the minimum number of unused bytes AFTER the allocation. ++ * It must be at LEAST 1 for bound-checking to work, 4 if you want ++ * off-by-one word-writes to not overwrite something important, and 0 ++ * if stack space is an absolute premium */ ++alloca_padding=4 ++ ++/* Alignment: usually 4, 8, or 16. Power of 2. Result % alignment == 0. */ ++alloca_alignment=4 ++ ++.globl _alloca_tcc ++_alloca_tcc: ++ pop %edx /* yank return address from stack */ ++ pop %ecx /* Get parameter (which is size). */ ++ ++ /* See if we got 0, and if so, handle specially. */ ++ or $0,%ecx ++ jz alloc_zero ++ ++ /* Allocate memory on the stack */ ++ mov %ecx,%eax ++ add $(alloca_padding+alloca_alignment-1),%eax ++ and $(-alloca_alignment),%eax ++ sub %eax,%esp /* Allocate! MODIFIES STACK POINTER HERE */ ++ ++ mov %esp,%eax /* Return beginning of allocated area to caller */ ++ push %edx /* Re-allocate param space for the caller to remove */ ++ push %edx /* Restore return address to return to. */ ++ ret + +-_alloca: +- pop %edx +- pop %eax +- add $3,%eax +- and $-4,%eax +- jz p3 +- +-#ifdef TCC_TARGET_PE +-p1: +- cmp $4096,%eax +- jle p2 +- sub $4096,%esp +- sub $4096,%eax +- test %eax,(%esp) +- jmp p1 +-p2: +-#endif +- +- sub %eax,%esp +- mov %esp,%eax +-p3: +- push %edx +- push %edx ++alloc_zero: ++ mov %ecx,%eax /* Return NULL */ ++ push %eax /* Re-allocate param space for the caller to remove */ ++ push %edx /* Restore return address to return to. */ + ret + +-/* ---------------------------------------------- */ +--- tcc-0.9.23/bcheck.c 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/bcheck.c 2007-11-07 10:04:32.000000000 -0500 +@@ -3,25 +3,15 @@ + * + * Copyright (c) 2002 Fabrice Bellard + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * Licensed under LGPL v2.1, see file COPYING in this tarball. + */ + #include + #include + #include + #include +-#ifndef __FreeBSD__ ++#if (!defined(__FreeBSD__) && \ ++ !defined(__DragonFly__) && \ ++ !defined(__OpenBSD__)) + #include + #endif + +@@ -36,8 +26,12 @@ + + #define HAVE_MEMALIGN + +-#if defined(__FreeBSD__) || defined(__dietlibc__) +-#warning Bound checking not fully supported on FreeBSD ++#if (defined(__FreeBSD__) || \ ++ defined(__DragonFly__) || \ ++ defined(__dietlibc__) || \ ++ defined(__UCLIBC__) || \ ++ defined(__OpenBSD__)) ++#warning Bound checking not fully supported in this environment. + #undef CONFIG_TCC_MALLOC_HOOKS + #undef HAVE_MEMALIGN + #endif +--- tcc-0.9.23/Changelog 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/Changelog 2007-11-07 10:04:32.000000000 -0500 +@@ -1,3 +1,15 @@ ++version 0.9.24: ++ ++- ignore AS_NEEDED ld command ++- mark executable sections as executable when running in memory ++- added support for win32 wchar_t (Filip Navara) ++- segment override prefix support (Filip Navara) ++- normalized slashes in paths (Filip Navara) ++- windows style fastcall (Filip Navara) ++- support for empty input register section in asm (Filip Navara) ++- anonymous union/struct support (Filip Navara) ++- fixed parsing of function parameters ++ + version 0.9.23: + + - initial PE executable format for windows version (grischka) +--- tcc-0.9.24/coff.h 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/coff.h 2007-11-07 10:04:32.000000000 -0500 +@@ -37,8 +37,8 @@ + #define F_BYTE_ORDER (F_LITTLE | F_BIG) + #define FILHDR struct filehdr + +-//#define FILHSZ sizeof(FILHDR) +-#define FILHSZ 22 // above rounds to align on 4 bytes which causes problems ++/*#define FILHSZ sizeof(FILHDR) */ ++#define FILHSZ 22 /* above rounds to align on 4 bytes which causes problems */ + + #define COFF_C67_MAGIC 0x00c2 + +@@ -150,7 +150,7 @@ + /*------------------------------------------------------------------------*/ + /* Define constants for names of "special" sections */ + /*------------------------------------------------------------------------*/ +-//#define _TEXT ".text" ++/*#define _TEXT ".text" */ + #define _DATA ".data" + #define _BSS ".bss" + #define _CINIT ".cinit" +--- tcc-0.9.24/elf.h 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/elf.h 2007-11-07 10:04:32.000000000 -0500 +@@ -21,7 +21,7 @@ + #ifndef _ELF_H + #define _ELF_H 1 + +-#ifndef _WIN32 ++#ifndef WIN32 + #include + #else + #ifndef __int8_t_defined +@@ -1627,7 +1627,7 @@ + #define R_C60_GOTOFF 9 /* 32 bit offset to GOT */ + #define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */ + +-#define R_C60HI16 0x55 // high 16 bit MVKH embedded +-#define R_C60LO16 0x54 // low 16 bit MVKL embedded ++#define R_C60HI16 0x55 /* high 16 bit MVKH embedded */ ++#define R_C60LO16 0x54 /* low 16 bit MVKL embedded */ + + #endif /* elf.h */ +--- tcc-0.9.24/float.h 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/include/float.h 2007-11-07 10:04:14.000000000 -0500 +@@ -1,57 +1,224 @@ ++/* ++ * float.h ++ * ++ * Constants related to floating point arithmetic. ++ * ++ * Also included here are some non-ANSI bits for accessing the floating ++ * point controller. ++ * ++ * NOTE: GCC provides float.h, and it is probably more accurate than this, ++ * but it doesn't include the non-standard stuff for accessing the ++ * fp controller. (TODO: Move those bits elsewhere?) Thus it is ++ * probably not a good idea to use the GCC supplied version instead ++ * of this header. ++ * ++ * This file is part of the Mingw32 package. ++ * ++ * Contributors: ++ * Created by Colin Peters ++ * ++ * THIS SOFTWARE IS NOT COPYRIGHTED ++ * ++ * This source code is offered for use in the public domain. You may ++ * use, modify or distribute it freely. ++ * ++ * This code is distributed in the hope that it will be useful but ++ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY ++ * DISCLAIMED. This includes but is not limited to warranties of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ * ++ * $Revision: 1.2 $ ++ * $Author: bellard $ ++ * $Date: 2005/04/17 13:14:29 $ ++ * ++ */ ++ + #ifndef _FLOAT_H_ + #define _FLOAT_H_ + ++/* All the headers include this file. */ ++#include <_mingw.h> ++ ++#define FLT_ROUNDS 1 ++#define FLT_GUARD 1 ++#define FLT_NORMALIZE 1 ++ ++/* ++ * The characteristics of float. ++ */ ++ ++/* The radix for floating point representation. */ + #define FLT_RADIX 2 + +-/* IEEE float */ +-#define FLT_MANT_DIG 24 ++/* Decimal digits of precision. */ + #define FLT_DIG 6 +-#define FLT_ROUNDS 1 ++ ++/* Smallest number such that 1+x != 1 */ + #define FLT_EPSILON 1.19209290e-07F +-#define FLT_MIN_EXP (-125) +-#define FLT_MIN 1.17549435e-38F +-#define FLT_MIN_10_EXP (-37) +-#define FLT_MAX_EXP 128 ++ ++/* The number of base FLT_RADIX digits in the mantissa. */ ++#define FLT_MANT_DIG 24 ++ ++/* The maximum floating point number. */ + #define FLT_MAX 3.40282347e+38F ++ ++/* Maximum n such that FLT_RADIX^n - 1 is representable. */ ++#define FLT_MAX_EXP 128 ++ ++/* Maximum n such that 10^n is representable. */ + #define FLT_MAX_10_EXP 38 + +-/* IEEE double */ +-#define DBL_MANT_DIG 53 ++/* Minimum normalized floating-point number. */ ++#define FLT_MIN 1.17549435e-38F ++ ++/* Minimum n such that FLT_RADIX^n is a normalized number. */ ++#define FLT_MIN_EXP (-125) ++ ++/* Minimum n such that 10^n is a normalized number. */ ++#define FLT_MIN_10_EXP (-37) ++ ++ ++/* ++ * The characteristics of double. ++ */ + #define DBL_DIG 15 +-#define DBL_EPSILON 2.2204460492503131e-16 +-#define DBL_MIN_EXP (-1021) +-#define DBL_MIN 2.2250738585072014e-308 +-#define DBL_MIN_10_EXP (-307) +-#define DBL_MAX_EXP 1024 ++#define DBL_EPSILON 1.1102230246251568e-16 ++#define DBL_MANT_DIG 53 + #define DBL_MAX 1.7976931348623157e+308 ++#define DBL_MAX_EXP 1024 + #define DBL_MAX_10_EXP 308 ++#define DBL_MIN 2.2250738585072014e-308 ++#define DBL_MIN_EXP (-1021) ++#define DBL_MIN_10_EXP (-307) + +-/* horrible intel long double */ +-#ifdef __i386__ +- +-#define LDBL_MANT_DIG 64 +-#define LDBL_DIG 18 +-#define LDBL_EPSILON 1.08420217248550443401e-19L +-#define LDBL_MIN_EXP (-16381) +-#define LDBL_MIN 3.36210314311209350626e-4932L +-#define LDBL_MIN_10_EXP (-4931) +-#define LDBL_MAX_EXP 16384 +-#define LDBL_MAX 1.18973149535723176502e+4932L +-#define LDBL_MAX_10_EXP 4932 +- +-#else + +-/* same as IEEE double */ +-#define LDBL_MANT_DIG 53 ++/* ++ * The characteristics of long double. ++ * NOTE: long double is the same as double. ++ */ + #define LDBL_DIG 15 +-#define LDBL_EPSILON 2.2204460492503131e-16 +-#define LDBL_MIN_EXP (-1021) +-#define LDBL_MIN 2.2250738585072014e-308 +-#define LDBL_MIN_10_EXP (-307) ++#define LDBL_EPSILON 1.1102230246251568e-16L ++#define LDBL_MANT_DIG 53 ++#define LDBL_MAX 1.7976931348623157e+308L + #define LDBL_MAX_EXP 1024 +-#define LDBL_MAX 1.7976931348623157e+308 + #define LDBL_MAX_10_EXP 308 ++#define LDBL_MIN 2.2250738585072014e-308L ++#define LDBL_MIN_EXP (-1021) ++#define LDBL_MIN_10_EXP (-307) ++ ++ ++/* ++ * Functions and definitions for controlling the FPU. ++ */ ++#ifndef __STRICT_ANSI__ ++ ++/* TODO: These constants are only valid for x86 machines */ ++ ++/* Control word masks for unMask */ ++#define _MCW_EM 0x0008001F /* Error masks */ ++#define _MCW_IC 0x00040000 /* Infinity */ ++#define _MCW_RC 0x00000300 /* Rounding */ ++#define _MCW_PC 0x00030000 /* Precision */ ++ ++/* Control word values for unNew (use with related unMask above) */ ++#define _EM_INVALID 0x00000010 ++#define _EM_DENORMAL 0x00080000 ++#define _EM_ZERODIVIDE 0x00000008 ++#define _EM_OVERFLOW 0x00000004 ++#define _EM_UNDERFLOW 0x00000002 ++#define _EM_INEXACT 0x00000001 ++#define _IC_AFFINE 0x00040000 ++#define _IC_PROJECTIVE 0x00000000 ++#define _RC_CHOP 0x00000300 ++#define _RC_UP 0x00000200 ++#define _RC_DOWN 0x00000100 ++#define _RC_NEAR 0x00000000 ++#define _PC_24 0x00020000 ++#define _PC_53 0x00010000 ++#define _PC_64 0x00000000 ++ ++/* These are also defined in Mingw math.h, needed to work around ++ GCC build issues. */ ++/* Return values for fpclass. */ ++#ifndef __MINGW_FPCLASS_DEFINED ++#define __MINGW_FPCLASS_DEFINED 1 ++#define _FPCLASS_SNAN 0x0001 /* Signaling "Not a Number" */ ++#define _FPCLASS_QNAN 0x0002 /* Quiet "Not a Number" */ ++#define _FPCLASS_NINF 0x0004 /* Negative Infinity */ ++#define _FPCLASS_NN 0x0008 /* Negative Normal */ ++#define _FPCLASS_ND 0x0010 /* Negative Denormal */ ++#define _FPCLASS_NZ 0x0020 /* Negative Zero */ ++#define _FPCLASS_PZ 0x0040 /* Positive Zero */ ++#define _FPCLASS_PD 0x0080 /* Positive Denormal */ ++#define _FPCLASS_PN 0x0100 /* Positive Normal */ ++#define _FPCLASS_PINF 0x0200 /* Positive Infinity */ ++#endif /* __MINGW_FPCLASS_DEFINED */ ++ ++/* invalid subconditions (_SW_INVALID also set) */ ++#define _SW_UNEMULATED 0x0040 /* unemulated instruction */ ++#define _SW_SQRTNEG 0x0080 /* square root of a neg number */ ++#define _SW_STACKOVERFLOW 0x0200 /* FP stack overflow */ ++#define _SW_STACKUNDERFLOW 0x0400 /* FP stack underflow */ ++ ++/* Floating point error signals and return codes */ ++#define _FPE_INVALID 0x81 ++#define _FPE_DENORMAL 0x82 ++#define _FPE_ZERODIVIDE 0x83 ++#define _FPE_OVERFLOW 0x84 ++#define _FPE_UNDERFLOW 0x85 ++#define _FPE_INEXACT 0x86 ++#define _FPE_UNEMULATED 0x87 ++#define _FPE_SQRTNEG 0x88 ++#define _FPE_STACKOVERFLOW 0x8a ++#define _FPE_STACKUNDERFLOW 0x8b ++#define _FPE_EXPLICITGEN 0x8c /* raise( SIGFPE ); */ ++ ++#ifndef RC_INVOKED + ++#ifdef __cplusplus ++extern "C" { + #endif + ++/* Set the FPU control word as cw = (cw & ~unMask) | (unNew & unMask), ++ * i.e. change the bits in unMask to have the values they have in unNew, ++ * leaving other bits unchanged. */ ++unsigned int _controlfp (unsigned int unNew, unsigned int unMask); ++unsigned int _control87 (unsigned int unNew, unsigned int unMask); ++ ++ ++unsigned int _clearfp (void); /* Clear the FPU status word */ ++unsigned int _statusfp (void); /* Report the FPU status word */ ++#define _clear87 _clearfp ++#define _status87 _statusfp ++ ++void _fpreset (void); /* Reset the FPU */ ++void fpreset (void); ++ ++/* Global 'variable' for the current floating point error code. */ ++int * __fpecode(void); ++#define _fpecode (*(__fpecode())) ++ ++/* ++ * IEEE recommended functions ++ */ ++ ++double _chgsign (double); ++double _copysign (double, double); ++double _logb (double); ++double _nextafter (double, double); ++double _scalb (double, long); ++ ++int _finite (double); ++int _fpclass (double); ++int _isnan (double); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* Not RC_INVOKED */ ++ ++#endif /* Not __STRICT_ANSI__ */ ++ + #endif /* _FLOAT_H_ */ ++ +--- tcc-0.9.23/i386-asm.c 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/i386/i386-asm.c 2007-11-07 10:04:30.000000000 -0500 +@@ -151,6 +151,15 @@ + 0x0f, /* g */ + }; + ++static const uint8_t segment_prefixes[] = { ++ 0x26, /* es */ ++ 0x2e, /* cs */ ++ 0x36, /* ss */ ++ 0x3e, /* ds */ ++ 0x64, /* fs */ ++ 0x65 /* gs */ ++}; ++ + static const ASMInstr asm_instrs[] = { + #define ALT(x) x + #define DEF_ASM_OP0(name, opcode) +@@ -174,11 +183,11 @@ + #include "i386-asm.h" + }; + +-static inline int get_reg_shift(TCCState *s1) ++static inline int get_reg_shift(TCCState *st) + { + int shift, v; + +- v = asm_int_expr(s1); ++ v = asm_int_expr(st); + switch(v) { + case 1: + shift = 0; +@@ -193,31 +202,31 @@ + shift = 3; + break; + default: +- expect("1, 2, 4 or 8 constant"); ++ expect(st, "1, 2, 4 or 8 constant"); + shift = 0; + break; + } + return shift; + } + +-static int asm_parse_reg(void) ++static int asm_parse_reg(TCCState *st) + { + int reg; + if (tok != '%') + goto error_32; +- next(); ++ next(st); + if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) { + reg = tok - TOK_ASM_eax; +- next(); ++ next(st); + return reg; + } else { + error_32: +- expect("32 bit register"); ++ expect(st, "32 bit register"); + return 0; + } + } + +-static void parse_operand(TCCState *s1, Operand *op) ++static void parse_operand(TCCState *st, Operand *op) + { + ExprValue e; + int reg, indir; +@@ -225,12 +234,12 @@ + + indir = 0; + if (tok == '*') { +- next(); ++ next(st); + indir = OP_INDIR; + } + + if (tok == '%') { +- next(); ++ next(st); + if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) { + reg = tok - TOK_ASM_al; + op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */ +@@ -250,9 +259,9 @@ + } else if (tok == TOK_ASM_st) { + op->type = OP_ST; + op->reg = 0; +- next(); ++ next(st); + if (tok == '(') { +- next(); ++ next(st); + if (tok != TOK_PPNUM) + goto reg_error; + p = tokc.cstr->data; +@@ -260,22 +269,22 @@ + if ((unsigned)reg >= 8 || p[1] != '\0') + goto reg_error; + op->reg = reg; +- next(); +- skip(')'); ++ next(st); ++ skip(st, ')'); + } + if (op->reg == 0) + op->type |= OP_ST0; + goto no_skip; + } else { + reg_error: +- error("unknown register"); ++ tcc_error(st, "unknown register"); + } +- next(); ++ next(st); + no_skip: ; + } else if (tok == '$') { + /* constant value */ +- next(); +- asm_expr(s1, &e); ++ next(st); ++ asm_expr(st, &e); + op->type = OP_IM32; + op->e.v = e.v; + op->e.sym = e.sym; +@@ -294,7 +303,7 @@ + op->reg2 = -1; + op->shift = 0; + if (tok != '(') { +- asm_expr(s1, &e); ++ asm_expr(st, &e); + op->e.v = e.v; + op->e.sym = e.sym; + } else { +@@ -302,19 +311,21 @@ + op->e.sym = NULL; + } + if (tok == '(') { +- next(); ++ next(st); + if (tok != ',') { +- op->reg = asm_parse_reg(); ++ op->reg = asm_parse_reg(st ); + } + if (tok == ',') { +- next(); ++ next(st); + if (tok != ',') { +- op->reg2 = asm_parse_reg(); ++ op->reg2 = asm_parse_reg(st ); ++ } ++ if (tok == ',') { ++ next(st); ++ op->shift = get_reg_shift(st); + } +- skip(','); +- op->shift = get_reg_shift(s1); + } +- skip(')'); ++ skip(st, ')'); + } + if (op->reg == -1 && op->reg2 == -1) + op->type |= OP_ADDR; +@@ -323,15 +334,15 @@ + } + + /* XXX: unify with C code output ? */ +-static void gen_expr32(ExprValue *pe) ++static void gen_expr32(TCCState *st, ExprValue *pe) + { + if (pe->sym) +- greloc(cur_text_section, pe->sym, ind, R_386_32); +- gen_le32(pe->v); ++ greloc(st, cur_text_section, pe->sym, ind, R_386_32); ++ gen_le32(st, pe->v); + } + + /* XXX: unify with C code output ? */ +-static void gen_disp32(ExprValue *pe) ++static void gen_disp32(TCCState * st, ExprValue *pe) + { + Sym *sym; + sym = pe->sym; +@@ -341,37 +352,37 @@ + that the TCC compiler behaves differently here because + it always outputs a relocation to ease (future) code + elimination in the linker */ +- gen_le32(pe->v + (long)sym->next - ind - 4); ++ gen_le32(st, pe->v + (long)sym->next - ind - 4); + } else { +- greloc(cur_text_section, sym, ind, R_386_PC32); +- gen_le32(pe->v - 4); ++ greloc(st, cur_text_section, sym, ind, R_386_PC32); ++ gen_le32(st, pe->v - 4); + } + } else { + /* put an empty PC32 relocation */ +- put_elf_reloc(symtab_section, cur_text_section, ++ put_elf_reloc(st, symtab_section, cur_text_section, + ind, R_386_PC32, 0); +- gen_le32(pe->v - 4); ++ gen_le32(st, pe->v - 4); + } + } + + +-static void gen_le16(int v) ++static void gen_le16(TCCState *st, int v) + { +- g(v); +- g(v >> 8); ++ g(st, v); ++ g(st, v >> 8); + } + + /* generate the modrm operand */ +-static inline void asm_modrm(int reg, Operand *op) ++static inline void asm_modrm(TCCState *st, int reg, Operand *op) + { + int mod, reg1, reg2, sib_reg1; + + if (op->type & (OP_REG | OP_MMX | OP_SSE)) { +- g(0xc0 + (reg << 3) + op->reg); ++ g(st, 0xc0 + (reg << 3) + op->reg); + } else if (op->reg == -1 && op->reg2 == -1) { + /* displacement only */ +- g(0x05 + (reg << 3)); +- gen_expr32(&op->e); ++ g(st, 0x05 + (reg << 3)); ++ gen_expr32(st, &op->e); + } else { + sib_reg1 = op->reg; + /* fist compute displacement encoding */ +@@ -389,47 +400,60 @@ + reg1 = op->reg; + if (op->reg2 != -1) + reg1 = 4; +- g(mod + (reg << 3) + reg1); ++ g(st, mod + (reg << 3) + reg1); + if (reg1 == 4) { + /* add sib byte */ + reg2 = op->reg2; + if (reg2 == -1) + reg2 = 4; /* indicate no index */ +- g((op->shift << 6) + (reg2 << 3) + sib_reg1); ++ g(st, (op->shift << 6) + (reg2 << 3) + sib_reg1); + } + + /* add offset */ + if (mod == 0x40) { +- g(op->e.v); ++ g(st, op->e.v); + } else if (mod == 0x80 || op->reg == -1) { +- gen_expr32(&op->e); ++ gen_expr32(st, &op->e); + } + } + } + +-static void asm_opcode(TCCState *s1, int opcode) ++static void asm_opcode(TCCState *st, int opcode) + { + const ASMInstr *pa; +- int i, modrm_index, reg, v, op1, is_short_jmp; ++ int i, modrm_index, reg, v, op1, is_short_jmp, has_seg_prefix; + int nb_ops, s, ss; +- Operand ops[MAX_OPERANDS], *pop; ++ Operand ops[MAX_OPERANDS], *pop, seg_prefix; + int op_type[3]; /* decoded op type */ + + /* get operands */ + pop = ops; + nb_ops = 0; ++ has_seg_prefix = 0; + for(;;) { + if (tok == ';' || tok == TOK_LINEFEED) + break; + if (nb_ops >= MAX_OPERANDS) { +- error("incorrect number of operands"); ++ tcc_error(st, "incorrect number of operands"); ++ } ++ parse_operand(st, pop); ++ if (tok == ':') { ++ if (pop->type != OP_SEG || has_seg_prefix) { ++ tcc_error(st, "incorrect prefix"); ++ } ++ seg_prefix = *pop; ++ has_seg_prefix = 1; ++ next(st); ++ parse_operand(st, pop); ++ if (!(pop->type & OP_EA)) { ++ tcc_error(st, "segment prefix must be followed by memory reference"); ++ } + } +- parse_operand(s1, pop); + pop++; + nb_ops++; + if (tok != ',') + break; +- next(); ++ next(st); + } + + is_short_jmp = 0; +@@ -506,12 +530,12 @@ + int b; + b = op0_codes[opcode - TOK_ASM_pusha]; + if (b & 0xff00) +- g(b >> 8); +- g(b); ++ g(st, b >> 8); ++ g(st, b); + return; + } else { +- error("unknown opcode '%s'", +- get_tok_str(opcode, NULL)); ++ tcc_error(st, "unknown opcode '%s'", ++ get_tok_str(st, opcode, NULL)); + } + } + /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */ +@@ -525,19 +549,21 @@ + (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32))) + s = 2; + else +- error("cannot infer opcode suffix"); ++ tcc_error(st, "cannot infer opcode suffix"); + } + } + + /* generate data16 prefix if needed */ + ss = s; + if (s == 1 || (pa->instr_type & OPC_D16)) +- g(WORD_PREFIX_OPCODE); ++ g(st, WORD_PREFIX_OPCODE); + else if (s == 2) + s = 1; + /* now generates the operation */ + if (pa->instr_type & OPC_FWAIT) +- g(0x9b); ++ g(st, 0x9b); ++ if (has_seg_prefix) ++ g(st, segment_prefixes[seg_prefix.reg]); + + v = pa->opcode; + if (v == 0x69 || v == 0x69) { +@@ -602,14 +628,14 @@ + else + v += 0x0f10; + } else { +- error("invalid displacement"); ++ tcc_error(st, "invalid displacement"); + } + } + } + op1 = v >> 8; + if (op1) +- g(op1); +- g(v); ++ g(st, op1); ++ g(st, v); + + /* search which operand will used for modrm */ + modrm_index = 0; +@@ -636,7 +662,7 @@ + goto modrm_found; + } + #ifdef ASM_DEBUG +- error("bad op table"); ++ tcc_error(st, "bad op table"); + #endif + modrm_found: + modrm_index = i; +@@ -651,16 +677,16 @@ + } + } + +- asm_modrm(reg, &ops[modrm_index]); ++ asm_modrm(st, reg, &ops[modrm_index]); + } + + /* emit constants */ + if (pa->opcode == 0x9a || pa->opcode == 0xea) { + /* ljmp or lcall kludge */ +- gen_expr32(&ops[1].e); ++ gen_expr32(st, &ops[1].e); + if (ops[0].e.sym) +- error("cannot relocate"); +- gen_le16(ops[0].e.v); ++ tcc_error(st, "cannot relocate"); ++ gen_le16(st, ops[0].e.v); + } else { + for(i = 0;i < nb_ops; i++) { + v = op_type[i]; +@@ -679,21 +705,21 @@ + if (v & (OP_IM8 | OP_IM8S)) { + if (ops[i].e.sym) + goto error_relocate; +- g(ops[i].e.v); ++ g(st, ops[i].e.v); + } else if (v & OP_IM16) { + if (ops[i].e.sym) { + error_relocate: +- error("cannot relocate"); ++ tcc_error(st, "cannot relocate"); + } +- gen_le16(ops[i].e.v); ++ gen_le16(st, ops[i].e.v); + } else { + if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) { + if (is_short_jmp) +- g(ops[i].e.v); ++ g(st, ops[i].e.v); + else +- gen_disp32(&ops[i].e); ++ gen_disp32(st, &ops[i].e); + } else { +- gen_expr32(&ops[i].e); ++ gen_expr32(st, &ops[i].e); + } + } + } +@@ -706,7 +732,7 @@ + + /* return the constraint priority (we allocate first the lowest + numbered constraints) */ +-static inline int constraint_priority(const char *str) ++static inline int constraint_priority(TCCState *st, const char *str) + { + int priority, c, pr; + +@@ -744,7 +770,7 @@ + pr = 4; + break; + default: +- error("unknown constraint '%c'", c); ++ tcc_error(st, "unknown constraint '%c'", c); + pr = 0; + } + if (pr > priority) +@@ -765,7 +791,8 @@ + + #define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask) + +-static void asm_compute_constraints(ASMOperand *operands, ++static void asm_compute_constraints(TCCState *st, ++ ASMOperand *operands, + int nb_operands, int nb_outputs, + const uint8_t *clobber_regs, + int *pout_reg) +@@ -791,19 +818,19 @@ + op = &operands[i]; + str = op->constraint; + str = skip_constraint_modifiers(str); +- if (isnum(*str) || *str == '[') { ++ if (isnum(st, *str) || *str == '[') { + /* this is a reference to another constraint */ +- k = find_constraint(operands, nb_operands, str, NULL); ++ k = find_constraint(st, operands, nb_operands, str, NULL); + if ((unsigned)k >= i || i < nb_outputs) +- error("invalid reference in constraint %d ('%s')", ++ tcc_error(st, "invalid reference in constraint %d ('%s')", + i, str); + op->ref_index = k; + if (operands[k].input_index >= 0) +- error("cannot reference twice the same operand"); ++ tcc_error(st, "cannot reference twice the same operand"); + operands[k].input_index = i; + op->priority = 5; + } else { +- op->priority = constraint_priority(str); ++ op->priority = constraint_priority(st, str); + } + } + +@@ -859,7 +886,7 @@ + /* FALL THRU */ + case '&': + if (j >= nb_outputs) +- error("'%c' modifier can only be applied to outputs", c); ++ tcc_error(st, "'%c' modifier can only be applied to outputs", c); + reg_mask = REG_IN_MASK | REG_OUT_MASK; + goto try_next; + case 'A': +@@ -950,7 +977,7 @@ + } + break; + default: +- error("asm constraint %d ('%s') could not be satisfied", ++ tcc_error(st, "asm constraint %d ('%s') could not be satisfied", + j, op->constraint); + break; + } +@@ -973,7 +1000,7 @@ + if (!(regs_allocated[reg] & REG_OUT_MASK)) + goto reg_found2; + } +- error("could not find free output register for reloading"); ++ tcc_error(st, "could not find free output register for reloading"); + reg_found2: + *pout_reg = reg; + break; +@@ -987,7 +1014,7 @@ + op = &operands[j]; + printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n", + j, +- op->id ? get_tok_str(op->id, NULL) : "", ++ op->id ? get_tok_str(st, op->id, NULL) : "", + op->constraint, + op->vt->r, + op->reg); +@@ -997,7 +1024,7 @@ + #endif + } + +-static void subst_asm_operand(CString *add_str, ++static void subst_asm_operand(TCCState *st, CString *add_str, + SValue *sv, int modifier) + { + int r, reg, size, val; +@@ -1006,11 +1033,11 @@ + r = sv->r; + if ((r & VT_VALMASK) == VT_CONST) { + if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n') +- cstr_ccat(add_str, '$'); ++ cstr_ccat(st, add_str, '$'); + if (r & VT_SYM) { +- cstr_cat(add_str, get_tok_str(sv->sym->v, NULL)); ++ cstr_cat(st, add_str, get_tok_str(st, sv->sym->v, NULL)); + if (sv->c.i != 0) { +- cstr_ccat(add_str, '+'); ++ cstr_ccat(st, add_str, '+'); + } else { + return; + } +@@ -1019,22 +1046,22 @@ + if (modifier == 'n') + val = -val; + snprintf(buf, sizeof(buf), "%d", sv->c.i); +- cstr_cat(add_str, buf); ++ cstr_cat(st, add_str, buf); + } else if ((r & VT_VALMASK) == VT_LOCAL) { + snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i); +- cstr_cat(add_str, buf); ++ cstr_cat(st, add_str, buf); + } else if (r & VT_LVAL) { + reg = r & VT_VALMASK; + if (reg >= VT_CONST) +- error("internal compiler error"); ++ tcc_error(st, "internal compiler error"); + snprintf(buf, sizeof(buf), "(%%%s)", +- get_tok_str(TOK_ASM_eax + reg, NULL)); +- cstr_cat(add_str, buf); ++ get_tok_str(st, TOK_ASM_eax + reg, NULL)); ++ cstr_cat(st, add_str, buf); + } else { + /* register case */ + reg = r & VT_VALMASK; + if (reg >= VT_CONST) +- error("internal compiler error"); ++ tcc_error(st, "internal compiler error"); + + /* choose register operand size */ + if ((sv->type.t & VT_BTYPE) == VT_BYTE) +@@ -1048,11 +1075,11 @@ + + if (modifier == 'b') { + if (reg >= 4) +- error("cannot use byte register"); ++ tcc_error(st, "cannot use byte register"); + size = 1; + } else if (modifier == 'h') { + if (reg >= 4) +- error("cannot use byte register"); ++ tcc_error(st, "cannot use byte register"); + size = -1; + } else if (modifier == 'w') { + size = 2; +@@ -1072,13 +1099,14 @@ + reg = TOK_ASM_eax + reg; + break; + } +- snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL)); +- cstr_cat(add_str, buf); ++ snprintf(buf, sizeof(buf), "%%%s", get_tok_str(st, reg, NULL)); ++ cstr_cat(st, add_str, buf); + } + } + + /* generate prolog and epilog code for asm statment */ +-static void asm_gen_code(ASMOperand *operands, int nb_operands, ++static void asm_gen_code(TCCState *st, ++ ASMOperand *operands, int nb_operands, + int nb_outputs, int is_output, + uint8_t *clobber_regs, + int out_reg) +@@ -1100,7 +1128,7 @@ + for(i = 0; i < NB_SAVED_REGS; i++) { + reg = reg_saved[i]; + if (regs_allocated[reg]) +- g(0x50 + reg); ++ g(st, 0x50 + reg); + } + + /* generate load code */ +@@ -1114,15 +1142,15 @@ + SValue sv; + sv = *op->vt; + sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL; +- load(op->reg, &sv); ++ load(st, op->reg, &sv); + } else if (i >= nb_outputs || op->is_rw) { + /* load value in register */ +- load(op->reg, op->vt); ++ load(st, op->reg, op->vt); + if (op->is_llong) { + SValue sv; + sv = *op->vt; + sv.c.ul += 4; +- load(TREG_EDX, &sv); ++ load(st, TREG_EDX, &sv); + } + } + } +@@ -1137,18 +1165,18 @@ + SValue sv; + sv = *op->vt; + sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL; +- load(out_reg, &sv); ++ load(st, out_reg, &sv); + + sv.r = (sv.r & ~VT_VALMASK) | out_reg; +- store(op->reg, &sv); ++ store(st, op->reg, &sv); + } + } else { +- store(op->reg, op->vt); ++ store(st, op->reg, op->vt); + if (op->is_llong) { + SValue sv; + sv = *op->vt; + sv.c.ul += 4; +- store(TREG_EDX, &sv); ++ store(st, TREG_EDX, &sv); + } + } + } +@@ -1157,12 +1185,12 @@ + for(i = NB_SAVED_REGS - 1; i >= 0; i--) { + reg = reg_saved[i]; + if (regs_allocated[reg]) +- g(0x58 + reg); ++ g(st, 0x58 + reg); + } + } + } + +-static void asm_clobber(uint8_t *clobber_regs, const char *str) ++static void asm_clobber(TCCState *st, uint8_t *clobber_regs, const char *str) + { + int reg; + TokenSym *ts; +@@ -1170,14 +1198,14 @@ + if (!strcmp(str, "memory") || + !strcmp(str, "cc")) + return; +- ts = tok_alloc(str, strlen(str)); ++ ts = tok_alloc(st, str, strlen(str)); + reg = ts->tok; + if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) { + reg -= TOK_ASM_eax; + } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) { + reg -= TOK_ASM_ax; + } else { +- error("invalid clobber register '%s'", str); ++ tcc_error(st, "invalid clobber register '%s'", str); + } + clobber_regs[reg] = 1; + } +--- tcc-0.9.24/i386-asm.h 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/i386/i386-asm.h 2007-11-07 10:04:30.000000000 -0500 +@@ -154,6 +154,7 @@ + /* arith */ + ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ + ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG)) ++ALT(DEF_ASM_OP2(addb, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG)) + ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX)) + ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG)) + ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG)) +--- tcc-0.9.24/i386-gen.c 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/i386/i386-gen.c 2007-11-07 10:04:30.000000000 -0500 +@@ -59,7 +59,7 @@ + + /* defined if structures are passed as pointers. Otherwise structures + are directly pushed on stack. */ +-//#define FUNC_STRUCT_PARAM_AS_PTR ++/*#define FUNC_STRUCT_PARAM_AS_PTR */ + + /* pointer size, in bytes */ + #define PTR_SIZE 4 +@@ -90,36 +90,39 @@ + static int func_ret_sub; + + /* XXX: make it faster ? */ +-void g(int c) ++void g(TCCState *st, int c) + { + int ind1; ++ ++ if (!cur_text_section) return; + ind1 = ind + 1; + if (ind1 > cur_text_section->data_allocated) +- section_realloc(cur_text_section, ind1); ++ section_realloc(st, cur_text_section, ind1); + cur_text_section->data[ind] = c; + ind = ind1; + } + +-void o(unsigned int c) ++void o(TCCState *st, unsigned int c) + { + while (c) { +- g(c); ++ g(st, c); + c = c >> 8; + } + } + +-void gen_le32(int c) ++void gen_le32(TCCState *st, int c) + { +- g(c); +- g(c >> 8); +- g(c >> 16); +- g(c >> 24); ++ g(st,c); ++ g(st,c >> 8); ++ g(st,c >> 16); ++ g(st,c >> 24); + } + + /* output a symbol and patch all calls to it */ + void gsym_addr(int t, int a) + { + int n, *ptr; ++ if (!cur_text_section) return; + while (t) { + ptr = (int *)(cur_text_section->data + t); + n = *ptr; /* next value */ +@@ -138,14 +141,15 @@ + #define psym oad + + /* instruction + 4 bytes data. Return the address of the data */ +-static int oad(int c, int s) ++static int oad(TCCState *st, int c, int s) + { + int ind1; + +- o(c); ++ if (!cur_text_section) return 0; ++ o(st, c); + ind1 = ind + 4; + if (ind1 > cur_text_section->data_allocated) +- section_realloc(cur_text_section, ind1); ++ section_realloc(st, cur_text_section, ind1); + *(int *)(cur_text_section->data + ind) = s; + s = ind; + ind = ind1; +@@ -153,39 +157,39 @@ + } + + /* output constant with relocation if 'r & VT_SYM' is true */ +-static void gen_addr32(int r, Sym *sym, int c) ++static void gen_addr32(TCCState *st, int r, Sym *sym, int c) + { + if (r & VT_SYM) +- greloc(cur_text_section, sym, ind, R_386_32); +- gen_le32(c); ++ greloc(st, cur_text_section, sym, ind, R_386_32); ++ gen_le32(st, c); + } + + /* generate a modrm reference. 'op_reg' contains the addtionnal 3 + opcode bits */ +-static void gen_modrm(int op_reg, int r, Sym *sym, int c) ++static void gen_modrm(TCCState *st, int op_reg, int r, Sym *sym, int c) + { + op_reg = op_reg << 3; + if ((r & VT_VALMASK) == VT_CONST) { + /* constant memory reference */ +- o(0x05 | op_reg); +- gen_addr32(r, sym, c); ++ o(st, 0x05 | op_reg); ++ gen_addr32(st, r, sym, c); + } else if ((r & VT_VALMASK) == VT_LOCAL) { + /* currently, we use only ebp as base */ + if (c == (char)c) { + /* short reference */ +- o(0x45 | op_reg); +- g(c); ++ o(st,0x45 | op_reg); ++ g(st, c); + } else { +- oad(0x85 | op_reg, c); ++ oad(st, 0x85 | op_reg, c); + } + } else { +- g(0x00 | op_reg | (r & VT_VALMASK)); ++ g(st, 0x00 | op_reg | (r & VT_VALMASK)); + } + } + + + /* load 'r' from value 'sv' */ +-void load(int r, SValue *sv) ++void load(TCCState *st, int r, SValue *sv) + { + int v, t, ft, fc, fr; + SValue v1; +@@ -200,57 +204,57 @@ + v1.type.t = VT_INT; + v1.r = VT_LOCAL | VT_LVAL; + v1.c.ul = fc; +- load(r, &v1); ++ load(st, r, &v1); + fr = r; + } + if ((ft & VT_BTYPE) == VT_FLOAT) { +- o(0xd9); /* flds */ ++ o(st, 0xd9); /* flds */ + r = 0; + } else if ((ft & VT_BTYPE) == VT_DOUBLE) { +- o(0xdd); /* fldl */ ++ o(st, 0xdd); /* fldl */ + r = 0; + } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { +- o(0xdb); /* fldt */ ++ o(st, 0xdb); /* fldt */ + r = 5; + } else if ((ft & VT_TYPE) == VT_BYTE) { +- o(0xbe0f); /* movsbl */ ++ o(st, 0xbe0f); /* movsbl */ + } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { +- o(0xb60f); /* movzbl */ ++ o(st, 0xb60f); /* movzbl */ + } else if ((ft & VT_TYPE) == VT_SHORT) { +- o(0xbf0f); /* movswl */ ++ o(st, 0xbf0f); /* movswl */ + } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { +- o(0xb70f); /* movzwl */ ++ o(st, 0xb70f); /* movzwl */ + } else { +- o(0x8b); /* movl */ ++ o(st, 0x8b); /* movl */ + } +- gen_modrm(r, fr, sv->sym, fc); ++ gen_modrm(st, r, fr, sv->sym, fc); + } else { + if (v == VT_CONST) { +- o(0xb8 + r); /* mov $xx, r */ +- gen_addr32(fr, sv->sym, fc); ++ o(st, 0xb8 + r); /* mov $xx, r */ ++ gen_addr32(st, fr, sv->sym, fc); + } else if (v == VT_LOCAL) { +- o(0x8d); /* lea xxx(%ebp), r */ +- gen_modrm(r, VT_LOCAL, sv->sym, fc); ++ o(st, 0x8d); /* lea xxx(%ebp), r */ ++ gen_modrm(st, r, VT_LOCAL, sv->sym, fc); + } else if (v == VT_CMP) { +- oad(0xb8 + r, 0); /* mov $0, r */ +- o(0x0f); /* setxx %br */ +- o(fc); +- o(0xc0 + r); ++ oad(st, 0xb8 + r, 0); /* mov $0, r */ ++ o(st, 0x0f); /* setxx %br */ ++ o(st, fc); ++ o(st, 0xc0 + r); + } else if (v == VT_JMP || v == VT_JMPI) { + t = v & 1; +- oad(0xb8 + r, t); /* mov $1, r */ +- o(0x05eb); /* jmp after */ ++ oad(st, 0xb8 + r, t); /* mov $1, r */ ++ o(st, 0x05eb); /* jmp after */ + gsym(fc); +- oad(0xb8 + r, t ^ 1); /* mov $0, r */ ++ oad(st, 0xb8 + r, t ^ 1); /* mov $0, r */ + } else if (v != r) { +- o(0x89); +- o(0xc0 + r + v * 8); /* mov v, r */ ++ o(st, 0x89); ++ o(st, 0xc0 + r + v * 8); /* mov v, r */ + } + } + } + + /* store register 'r' in lvalue 'v' */ +-void store(int r, SValue *v) ++void store(TCCState *st, int r, SValue *v) + { + int fr, bt, ft, fc; + +@@ -260,63 +264,63 @@ + bt = ft & VT_BTYPE; + /* XXX: incorrect if float reg to reg */ + if (bt == VT_FLOAT) { +- o(0xd9); /* fsts */ ++ o(st, 0xd9); /* fsts */ + r = 2; + } else if (bt == VT_DOUBLE) { +- o(0xdd); /* fstpl */ ++ o(st, 0xdd); /* fstpl */ + r = 2; + } else if (bt == VT_LDOUBLE) { +- o(0xc0d9); /* fld %st(0) */ +- o(0xdb); /* fstpt */ ++ o(st, 0xc0d9); /* fld %st(0) */ ++ o(st, 0xdb); /* fstpt */ + r = 7; + } else { + if (bt == VT_SHORT) +- o(0x66); ++ o(st, 0x66); + if (bt == VT_BYTE || bt == VT_BOOL) +- o(0x88); ++ o(st, 0x88); + else +- o(0x89); ++ o(st, 0x89); + } + if (fr == VT_CONST || + fr == VT_LOCAL || + (v->r & VT_LVAL)) { +- gen_modrm(r, v->r, v->sym, fc); ++ gen_modrm(st, r, v->r, v->sym, fc); + } else if (fr != r) { +- o(0xc0 + fr + r * 8); /* mov r, fr */ ++ o(st, 0xc0 + fr + r * 8); /* mov r, fr */ + } + } + +-static void gadd_sp(int val) ++static void gadd_sp(TCCState *st, int val) + { + if (val == (char)val) { +- o(0xc483); +- g(val); ++ o(st, 0xc483); ++ g(st, val); + } else { +- oad(0xc481, val); /* add $xxx, %esp */ ++ oad(st, 0xc481, val); /* add $xxx, %esp */ + } + } + + /* 'is_jmp' is '1' if it is a jump */ +-static void gcall_or_jmp(int is_jmp) ++static void gcall_or_jmp(TCCState *st, int is_jmp) + { + int r; + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { + /* constant case */ + if (vtop->r & VT_SYM) { + /* relocation case */ +- greloc(cur_text_section, vtop->sym, ++ greloc(st, cur_text_section, vtop->sym, + ind + 1, R_386_PC32); + } else { + /* put an empty PC32 relocation */ +- put_elf_reloc(symtab_section, cur_text_section, ++ put_elf_reloc(st, symtab_section, cur_text_section, + ind + 1, R_386_PC32, 0); + } +- oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */ ++ oad(st, 0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */ + } else { + /* otherwise, indirect call */ +- r = gv(RC_INT); +- o(0xff); /* call/jmp *r */ +- o(0xd0 + r + (is_jmp << 4)); ++ r = gv(st, RC_INT); ++ o(st, 0xff); /* call/jmp *r */ ++ o(st, 0xd0 + r + (is_jmp << 4)); + } + } + +@@ -326,7 +330,7 @@ + /* Generate function call. The function address is pushed first, then + all the parameters in call order. This functions pops all the + parameters and the function address. */ +-void gfunc_call(int nb_args) ++void gfunc_call(TCCState *st, int nb_args) + { + int size, align, r, args_size, i, func_call; + Sym *func_sym; +@@ -334,53 +338,53 @@ + args_size = 0; + for(i = 0;i < nb_args; i++) { + if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { +- size = type_size(&vtop->type, &align); ++ size = type_size(st, &vtop->type, &align); + /* align to stack align size */ + size = (size + 3) & ~3; + /* allocate the necessary size on stack */ +- oad(0xec81, size); /* sub $xxx, %esp */ ++ oad(st, 0xec81, size); /* sub $xxx, %esp */ + /* generate structure store */ +- r = get_reg(RC_INT); +- o(0x89); /* mov %esp, r */ +- o(0xe0 + r); +- vset(&vtop->type, r | VT_LVAL, 0); +- vswap(); +- vstore(); ++ r = get_reg(st, RC_INT); ++ o(st, 0x89); /* mov %esp, r */ ++ o(st, 0xe0 + r); ++ vset(st, &vtop->type, r | VT_LVAL, 0); ++ vswap(st); ++ vstore(st); + args_size += size; +- } else if (is_float(vtop->type.t)) { +- gv(RC_FLOAT); /* only one float register */ ++ } else if (is_float(st, vtop->type.t)) { ++ gv(st, RC_FLOAT); /* only one float register */ + if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) + size = 4; + else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) + size = 8; + else + size = 12; +- oad(0xec81, size); /* sub $xxx, %esp */ ++ oad(st, 0xec81, size); /* sub $xxx, %esp */ + if (size == 12) +- o(0x7cdb); ++ o(st, 0x7cdb); + else +- o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */ +- g(0x24); +- g(0x00); ++ o(st, 0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */ ++ g(st, 0x24); ++ g(st, 0x00); + args_size += size; + } else { + /* simple type (currently always same size) */ + /* XXX: implicit cast ? */ +- r = gv(RC_INT); ++ r = gv(st, RC_INT); + if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { + size = 8; +- o(0x50 + vtop->r2); /* push r */ ++ o(st, 0x50 + vtop->r2); /* push r */ + } else { + size = 4; + } +- o(0x50 + r); /* push r */ ++ o(st, 0x50 + r); /* push r */ + args_size += size; + } + vtop--; + } +- save_regs(0); /* save used temporary registers */ ++ save_regs(st, 0); /* save used temporary registers */ + func_sym = vtop->type.ref; +- func_call = FUNC_CALL(func_sym->r); ++ func_call = func_sym->r; + /* fast call case */ + if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || + func_call == FUNC_FASTCALLW) { +@@ -396,25 +400,21 @@ + for(i = 0;i < fastcall_nb_regs; i++) { + if (args_size <= 0) + break; +- o(0x58 + fastcall_regs_ptr[i]); /* pop r */ ++ o(st, 0x58 + fastcall_regs_ptr[i]); /* pop r */ + /* XXX: incorrect for struct/floats */ + args_size -= 4; + } + } +- gcall_or_jmp(0); +- if (args_size && func_call != FUNC_STDCALL) +- gadd_sp(args_size); ++ gcall_or_jmp(st, 0); ++ if (args_size && func_sym->r != FUNC_STDCALL) ++ gadd_sp(st, args_size); + vtop--; + } + +-#ifdef TCC_TARGET_PE +-#define FUNC_PROLOG_SIZE 10 +-#else + #define FUNC_PROLOG_SIZE 9 +-#endif + + /* generate function prolog of type 't' */ +-void gfunc_prolog(CType *func_type) ++void gfunc_prolog(TCCState *st, CType *func_type) + { + int addr, align, size, func_call, fastcall_nb_regs; + int param_index, param_addr; +@@ -423,7 +423,7 @@ + CType *type; + + sym = func_type->ref; +- func_call = FUNC_CALL(sym->r); ++ func_call = sym->r; + addr = 8; + loc = 0; + if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) { +@@ -452,7 +452,7 @@ + /* define parameters */ + while ((sym = sym->next) != NULL) { + type = &sym->type; +- size = type_size(type, &align); ++ size = type_size(st, type, &align); + size = (size + 3) & ~3; + #ifdef FUNC_STRUCT_PARAM_AS_PTR + /* structs are passed as pointer */ +@@ -463,14 +463,14 @@ + if (param_index < fastcall_nb_regs) { + /* save FASTCALL register */ + loc -= 4; +- o(0x89); /* movl */ +- gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); ++ o(st, 0x89); /* movl */ ++ gen_modrm(st,fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); + param_addr = loc; + } else { + param_addr = addr; + addr += size; + } +- sym_push(sym->v & ~SYM_FIELD, type, ++ sym_push(st, sym->v & ~SYM_FIELD, type, + VT_LOCAL | VT_LVAL, param_addr); + param_index++; + } +@@ -481,57 +481,57 @@ + + /* leave some room for bound checking code */ + if (do_bounds_check) { +- oad(0xb8, 0); /* lbound section pointer */ +- oad(0xb8, 0); /* call to function */ ++ oad(st, 0xb8, 0); /* lbound section pointer */ ++ oad(st, 0xb8, 0); /* call to function */ + func_bound_offset = lbounds_section->data_offset; + } + } + + /* generate function epilog */ +-void gfunc_epilog(void) ++void gfunc_epilog(TCCState *st) + { + int v, saved_ind; + +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + if (do_bounds_check && func_bound_offset != lbounds_section->data_offset) { + int saved_ind; + int *bounds_ptr; + Sym *sym, *sym_data; + /* add end of table info */ +- bounds_ptr = section_ptr_add(lbounds_section, sizeof(int)); ++ bounds_ptr = section_ptr_add(st,lbounds_section, sizeof(int)); + *bounds_ptr = 0; + /* generate bound local allocation */ + saved_ind = ind; + ind = func_sub_sp_offset; +- sym_data = get_sym_ref(&char_pointer_type, lbounds_section, ++ sym_data = get_sym_ref(st,&char_pointer_type, lbounds_section, + func_bound_offset, lbounds_section->data_offset); +- greloc(cur_text_section, sym_data, ++ greloc(st, cur_text_section, sym_data, + ind + 1, R_386_32); +- oad(0xb8, 0); /* mov %eax, xxx */ +- sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0); +- greloc(cur_text_section, sym, ++ oad(st, 0xb8, 0); /* mov %eax, xxx */ ++ sym = external_global_sym(st, TOK___bound_local_new, &func_old_type, 0); ++ greloc(st, cur_text_section, sym, + ind + 1, R_386_PC32); +- oad(0xe8, -4); ++ oad(st, 0xe8, -4); + ind = saved_ind; + /* generate bound check local freeing */ +- o(0x5250); /* save returned value, if any */ +- greloc(cur_text_section, sym_data, ++ o(st, 0x5250); /* save returned value, if any */ ++ greloc(st, cur_text_section, sym_data, + ind + 1, R_386_32); +- oad(0xb8, 0); /* mov %eax, xxx */ +- sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0); +- greloc(cur_text_section, sym, ++ oad(st, 0xb8, 0); /* mov %eax, xxx */ ++ sym = external_global_sym(st, TOK___bound_local_delete, &func_old_type, 0); ++ greloc(st, ur_text_section, sym, + ind + 1, R_386_PC32); +- oad(0xe8, -4); +- o(0x585a); /* restore returned value, if any */ ++ oad(st, 0xe8, -4); ++ o(st, 0x585a); /* restore returned value, if any */ + } + #endif +- o(0xc9); /* leave */ ++ o(st, 0xc9); /* leave */ + if (func_ret_sub == 0) { +- o(0xc3); /* ret */ ++ o(st, 0xc3); /* ret */ + } else { +- o(0xc2); /* ret n */ +- g(func_ret_sub); +- g(func_ret_sub >> 8); ++ o(st, 0xc2); /* ret n */ ++ g(st, func_ret_sub); ++ g(st, func_ret_sub >> 8); + } + /* align local size to word & save local variables */ + +@@ -540,52 +540,48 @@ + ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; + #ifdef TCC_TARGET_PE + if (v >= 4096) { +- Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); +- oad(0xb8, v); /* mov stacksize, %eax */ +- oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ +- greloc(cur_text_section, sym, ind-4, R_386_PC32); ++ Sym *sym = external_global_sym(st, TOK___chkstk, &func_old_type, 0); ++ oad(st, 0xe8, -4); /* call __chkstk, (does the stackframe too) */ ++ greloc(st, cur_text_section, sym, ind-4, R_386_PC32); + } else + #endif + { +- o(0xe58955); /* push %ebp, mov %esp, %ebp */ +- o(0xec81); /* sub esp, stacksize */ +- gen_le32(v); +-#if FUNC_PROLOG_SIZE == 10 +- o(0x90); /* adjust to FUNC_PROLOG_SIZE */ +-#endif ++ o(st, 0xe58955); /* push %ebp, mov %esp, %ebp */ ++ o(st, 0xec81); /* sub esp, stacksize */ + } ++ gen_le32(st, v); + ind = saved_ind; + } + + /* generate a jump to a label */ +-int gjmp(int t) ++int gjmp(TCCState *st, int t) + { +- return psym(0xe9, t); ++ return psym(st, 0xe9, t); + } + + /* generate a jump to a fixed address */ +-void gjmp_addr(int a) ++void gjmp_addr(TCCState *st, int a) + { + int r; + r = a - ind - 2; + if (r == (char)r) { +- g(0xeb); +- g(r); ++ g(st, 0xeb); ++ g(st, r); + } else { +- oad(0xe9, a - ind - 5); ++ oad(st, 0xe9, a - ind - 5); + } + } + + /* generate a test. set 'inv' to invert test. Stack entry is popped */ +-int gtst(int inv, int t) ++int gtst(TCCState *st, int inv, int t) + { + int v, *p; + + v = vtop->r & VT_VALMASK; + if (v == VT_CMP) { + /* fast case : can jump directly since flags are set */ +- g(0x0f); +- t = psym((vtop->c.i - 16) ^ inv, t); ++ g(st, 0x0f); ++ t = psym(st, (vtop->c.i - 16) ^ inv, t); + } else if (v == VT_JMP || v == VT_JMPI) { + /* && or || optimization */ + if ((v & 1) == inv) { +@@ -596,25 +592,25 @@ + *p = t; + t = vtop->c.i; + } else { +- t = gjmp(t); ++ t = gjmp(st, t); + gsym(vtop->c.i); + } + } else { +- if (is_float(vtop->type.t) || +- (vtop->type.t & VT_BTYPE) == VT_LLONG) { +- vpushi(0); +- gen_op(TOK_NE); ++ if (is_float(st, vtop->type.t) || is_llong(st, vtop->type.t)) { ++ /* compare != 0 to get a 32-bit int for testing */ ++ vpushi(st, 0); ++ gen_op(st, TOK_NE); + } + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + /* constant jmp optimization */ + if ((vtop->c.i != 0) != inv) +- t = gjmp(t); ++ t = gjmp(st,t); + } else { +- v = gv(RC_INT); +- o(0x85); +- o(0xc0 + v * 9); +- g(0x0f); +- t = psym(0x85 ^ inv, t); ++ v = gv(st, RC_INT); ++ o(st, 0x85); ++ o(st, 0xc0 + v * 9); ++ g(st, 0x0f); ++ t = psym(st, 0x85 ^ inv, t); + } + } + vtop--; +@@ -622,7 +618,7 @@ + } + + /* generate an integer binary operation */ +-void gen_opi(int op) ++void gen_opi(TCCState *st, int op) + { + int r, fr, opc, c; + +@@ -633,25 +629,25 @@ + gen_op8: + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + /* constant case */ +- vswap(); +- r = gv(RC_INT); +- vswap(); ++ vswap(st); ++ r = gv(st, RC_INT); ++ vswap(st); + c = vtop->c.i; + if (c == (char)c) { + /* XXX: generate inc and dec for smaller code ? */ +- o(0x83); +- o(0xc0 | (opc << 3) | r); +- g(c); ++ o(st, 0x83); ++ o(st, 0xc0 | (opc << 3) | r); ++ g(st, c); + } else { +- o(0x81); +- oad(0xc0 | (opc << 3) | r, c); ++ o(st, 0x81); ++ oad(st, 0xc0 | (opc << 3) | r, c); + } + } else { +- gv2(RC_INT, RC_INT); ++ gv2(st, RC_INT, RC_INT); + r = vtop[-1].r; + fr = vtop[0].r; +- o((opc << 3) | 0x01); +- o(0xc0 + r + fr * 8); ++ o(st, (opc << 3) | 0x01); ++ o(st, 0xc0 + r + fr * 8); + } + vtop--; + if (op >= TOK_ULT && op <= TOK_GT) { +@@ -679,12 +675,12 @@ + opc = 1; + goto gen_op8; + case '*': +- gv2(RC_INT, RC_INT); ++ gv2(st, RC_INT, RC_INT); + r = vtop[-1].r; + fr = vtop[0].r; + vtop--; +- o(0xaf0f); /* imul fr, r */ +- o(0xc0 + fr + r * 8); ++ o(st, 0xaf0f); /* imul fr, r */ ++ o(st, 0xc0 + fr + r * 8); + break; + case TOK_SHL: + opc = 4; +@@ -698,19 +694,19 @@ + opc = 0xc0 | (opc << 3); + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + /* constant case */ +- vswap(); +- r = gv(RC_INT); +- vswap(); ++ vswap(st); ++ r = gv(st, RC_INT); ++ vswap(st); + c = vtop->c.i & 0x1f; +- o(0xc1); /* shl/shr/sar $xxx, r */ +- o(opc | r); +- g(c); ++ o(st, 0xc1); /* shl/shr/sar $xxx, r */ ++ o(st, opc | r); ++ g(st, c); + } else { + /* we generate the shift in ecx */ +- gv2(RC_INT, RC_ECX); ++ gv2(st, RC_INT, RC_ECX); + r = vtop[-1].r; +- o(0xd3); /* shl/shr/sar %cl, r */ +- o(opc | r); ++ o(st, 0xd3); /* shl/shr/sar %cl, r */ ++ o(st, opc | r); + } + vtop--; + break; +@@ -722,23 +718,23 @@ + case TOK_UMULL: + /* first operand must be in eax */ + /* XXX: need better constraint for second operand */ +- gv2(RC_EAX, RC_ECX); ++ gv2(st, RC_EAX, RC_ECX); + r = vtop[-1].r; + fr = vtop[0].r; + vtop--; +- save_reg(TREG_EDX); ++ save_reg(st, TREG_EDX); + if (op == TOK_UMULL) { +- o(0xf7); /* mul fr */ +- o(0xe0 + fr); ++ o(st, 0xf7); /* mul fr */ ++ o(st, 0xe0 + fr); + vtop->r2 = TREG_EDX; + r = TREG_EAX; + } else { + if (op == TOK_UDIV || op == TOK_UMOD) { +- o(0xf7d231); /* xor %edx, %edx, div fr, %eax */ +- o(0xf0 + fr); ++ o(st, 0xf7d231); /* xor %edx, %edx, div fr, %eax */ ++ o(st, 0xf0 + fr); + } else { +- o(0xf799); /* cltd, idiv fr, %eax */ +- o(0xf8 + fr); ++ o(st, 0xf799); /* cltd, idiv fr, %eax */ ++ o(st, 0xf8 + fr); + } + if (op == '%' || op == TOK_UMOD) + r = TREG_EDX; +@@ -756,57 +752,57 @@ + /* generate a floating point operation 'v = t1 op t2' instruction. The + two operands are guaranted to have the same floating point type */ + /* XXX: need to use ST1 too */ +-void gen_opf(int op) ++void gen_opf(TCCState *st, int op) + { + int a, ft, fc, swapped, r; + + /* convert constants to memory references */ + if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { +- vswap(); +- gv(RC_FLOAT); +- vswap(); ++ vswap(st); ++ gv(st, RC_FLOAT); ++ vswap(st); + } + if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) +- gv(RC_FLOAT); ++ gv(st, RC_FLOAT); + + /* must put at least one value in the floating point register */ + if ((vtop[-1].r & VT_LVAL) && + (vtop[0].r & VT_LVAL)) { +- vswap(); +- gv(RC_FLOAT); +- vswap(); ++ vswap(st); ++ gv(st, RC_FLOAT); ++ vswap(st); + } + swapped = 0; + /* swap the stack if needed so that t1 is the register and t2 is + the memory reference */ + if (vtop[-1].r & VT_LVAL) { +- vswap(); ++ vswap(st); + swapped = 1; + } + if (op >= TOK_ULT && op <= TOK_GT) { + /* load on stack second operand */ +- load(TREG_ST0, vtop); +- save_reg(TREG_EAX); /* eax is used by FP comparison code */ ++ load(st, TREG_ST0, vtop); ++ save_reg(st, TREG_EAX); /* eax is used by FP comparison code */ + if (op == TOK_GE || op == TOK_GT) + swapped = !swapped; + else if (op == TOK_EQ || op == TOK_NE) + swapped = 0; + if (swapped) +- o(0xc9d9); /* fxch %st(1) */ +- o(0xe9da); /* fucompp */ +- o(0xe0df); /* fnstsw %ax */ ++ o(st, 0xc9d9); /* fxch %st(1) */ ++ o(st, 0xe9da); /* fucompp */ ++ o(st, 0xe0df); /* fnstsw %ax */ + if (op == TOK_EQ) { +- o(0x45e480); /* and $0x45, %ah */ +- o(0x40fC80); /* cmp $0x40, %ah */ ++ o(st, 0x45e480); /* and $0x45, %ah */ ++ o(st, 0x40fC80); /* cmp $0x40, %ah */ + } else if (op == TOK_NE) { +- o(0x45e480); /* and $0x45, %ah */ +- o(0x40f480); /* xor $0x40, %ah */ ++ o(st, 0x45e480); /* and $0x45, %ah */ ++ o(st, 0x40f480); /* xor $0x40, %ah */ + op = TOK_NE; + } else if (op == TOK_GE || op == TOK_LE) { +- o(0x05c4f6); /* test $0x05, %ah */ ++ o(st, 0x05c4f6); /* test $0x05, %ah */ + op = TOK_EQ; + } else { +- o(0x45c4f6); /* test $0x45, %ah */ ++ o(st, 0x45c4f6); /* test $0x45, %ah */ + op = TOK_EQ; + } + vtop--; +@@ -815,7 +811,7 @@ + } else { + /* no memory reference possible for long double operations */ + if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { +- load(TREG_ST0, vtop); ++ load(st, TREG_ST0, vtop); + swapped = !swapped; + } + +@@ -841,26 +837,26 @@ + ft = vtop->type.t; + fc = vtop->c.ul; + if ((ft & VT_BTYPE) == VT_LDOUBLE) { +- o(0xde); /* fxxxp %st, %st(1) */ +- o(0xc1 + (a << 3)); ++ o(st, 0xde); /* fxxxp %st, %st(1) */ ++ o(st, 0xc1 + (a << 3)); + } else { + /* if saved lvalue, then we must reload it */ + r = vtop->r; + if ((r & VT_VALMASK) == VT_LLOCAL) { + SValue v1; +- r = get_reg(RC_INT); ++ r = get_reg(st, RC_INT); + v1.type.t = VT_INT; + v1.r = VT_LOCAL | VT_LVAL; + v1.c.ul = fc; +- load(r, &v1); ++ load(st, r, &v1); + fc = 0; + } + + if ((ft & VT_BTYPE) == VT_DOUBLE) +- o(0xdc); ++ o(st, 0xdc); + else +- o(0xd8); +- gen_modrm(a, r, vtop->sym, fc); ++ o(st, 0xd8); ++ gen_modrm(st, a, r, vtop->sym, fc); + } + vtop--; + } +@@ -868,37 +864,37 @@ + + /* convert integers to fp 't' type. Must handle 'int', 'unsigned int' + and 'long long' cases. */ +-void gen_cvt_itof(int t) ++void gen_cvt_itof(TCCState *st, int t) + { +- save_reg(TREG_ST0); +- gv(RC_INT); ++ save_reg(st, TREG_ST0); ++ gv(st, RC_INT); + if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { + /* signed long long to float/double/long double (unsigned case + is handled generically) */ +- o(0x50 + vtop->r2); /* push r2 */ +- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ +- o(0x242cdf); /* fildll (%esp) */ +- o(0x08c483); /* add $8, %esp */ ++ o(st, 0x50 + vtop->r2); /* push r2 */ ++ o(st, 0x50 + (vtop->r & VT_VALMASK)); /* push r */ ++ o(st, 0x242cdf); /* fildll (%esp) */ ++ o(st, 0x08c483); /* add $8, %esp */ + } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == + (VT_INT | VT_UNSIGNED)) { + /* unsigned int to float/double/long double */ +- o(0x6a); /* push $0 */ +- g(0x00); +- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ +- o(0x242cdf); /* fildll (%esp) */ +- o(0x08c483); /* add $8, %esp */ ++ o(st, 0x6a); /* push $0 */ ++ g(st, 0x00); ++ o(st, 0x50 + (vtop->r & VT_VALMASK)); /* push r */ ++ o(st, 0x242cdf); /* fildll (%esp) */ ++ o(st, 0x08c483); /* add $8, %esp */ + } else { + /* int to float/double/long double */ +- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ +- o(0x2404db); /* fildl (%esp) */ +- o(0x04c483); /* add $4, %esp */ ++ o(st, 0x50 + (vtop->r & VT_VALMASK)); /* push r */ ++ o(st, 0x2404db); /* fildl (%esp) */ ++ o(st, 0x04c483); /* add $4, %esp */ + } + vtop->r = TREG_ST0; + } + + /* convert fp to int 't' type */ + /* XXX: handle long long case */ +-void gen_cvt_ftoi(int t) ++void gen_cvt_ftoi(TCCState *st, int t) + { + int r, r2, size; + Sym *sym; +@@ -906,76 +902,76 @@ + + ushort_type.t = VT_SHORT | VT_UNSIGNED; + +- gv(RC_FLOAT); ++ gv(st, RC_FLOAT); + if (t != VT_INT) + size = 8; + else + size = 4; + +- o(0x2dd9); /* ldcw xxx */ +- sym = external_global_sym(TOK___tcc_int_fpu_control, ++ o(st, 0x2dd9); /* ldcw xxx */ ++ sym = external_global_sym(st, TOK___tcc_int_fpu_control, + &ushort_type, VT_LVAL); +- greloc(cur_text_section, sym, ++ greloc(st, cur_text_section, sym, + ind, R_386_32); +- gen_le32(0); ++ gen_le32(st, 0); + +- oad(0xec81, size); /* sub $xxx, %esp */ ++ oad(st, 0xec81, size); /* sub $xxx, %esp */ + if (size == 4) +- o(0x1cdb); /* fistpl */ ++ o(st, 0x1cdb); /* fistpl */ + else +- o(0x3cdf); /* fistpll */ +- o(0x24); +- o(0x2dd9); /* ldcw xxx */ +- sym = external_global_sym(TOK___tcc_fpu_control, ++ o(st, 0x3cdf); /* fistpll */ ++ o(st, 0x24); ++ o(st, 0x2dd9); /* ldcw xxx */ ++ sym = external_global_sym(st, TOK___tcc_fpu_control, + &ushort_type, VT_LVAL); +- greloc(cur_text_section, sym, ++ greloc(st, cur_text_section, sym, + ind, R_386_32); +- gen_le32(0); ++ gen_le32(st, 0); + +- r = get_reg(RC_INT); +- o(0x58 + r); /* pop r */ ++ r = get_reg(st, RC_INT); ++ o(st, 0x58 + r); /* pop r */ + if (size == 8) { + if (t == VT_LLONG) { + vtop->r = r; /* mark reg as used */ +- r2 = get_reg(RC_INT); +- o(0x58 + r2); /* pop r2 */ ++ r2 = get_reg(st, RC_INT); ++ o(st, 0x58 + r2); /* pop r2 */ + vtop->r2 = r2; + } else { +- o(0x04c483); /* add $4, %esp */ ++ o(st, 0x04c483); /* add $4, %esp */ + } + } + vtop->r = r; + } + + /* convert from one floating point type to another */ +-void gen_cvt_ftof(int t) ++void gen_cvt_ftof(TCCState *st, int t) + { + /* all we have to do on i386 is to put the float in a register */ +- gv(RC_FLOAT); ++ gv(st, RC_FLOAT); + } + + /* computed goto support */ +-void ggoto(void) ++void ggoto(TCCState *st) + { +- gcall_or_jmp(1); ++ gcall_or_jmp(st, 1); + vtop--; + } + + /* bound check support functions */ +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + + /* generate a bounded pointer addition */ +-void gen_bounded_ptr_add(void) ++void gen_bounded_ptr_add() + { + Sym *sym; + + /* prepare fast i386 function call (args in eax and edx) */ +- gv2(RC_EAX, RC_EDX); ++ gv2(st, RC_EAX, RC_EDX); + /* save all temporary registers */ + vtop -= 2; +- save_regs(0); ++ save_regs(st, 0); + /* do a fast function call */ +- sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0); ++ sym = external_global_sym(st, TOK___bound_ptr_add, &func_old_type, 0); + greloc(cur_text_section, sym, + ind + 1, R_386_PC32); + oad(0xe8, -4); +@@ -997,14 +993,14 @@ + + size = 0; + /* XXX: put that code in generic part of tcc */ +- if (!is_float(vtop->type.t)) { ++ if (!is_float(st, vtop->type.t)) { + if (vtop->r & VT_LVAL_BYTE) + size = 1; + else if (vtop->r & VT_LVAL_SHORT) + size = 2; + } + if (!size) +- size = type_size(&vtop->type, &align); ++ size = type_size(st, &vtop->type, &align); + switch(size) { + case 1: func = TOK___bound_ptr_indir1; break; + case 2: func = TOK___bound_ptr_indir2; break; +@@ -1021,7 +1017,7 @@ + /* patch relocation */ + /* XXX: find a better solution ? */ + rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul); +- sym = external_global_sym(func, &func_old_type, 0); ++ sym = external_global_sym(st, func, &func_old_type, 0); + if (!sym->c) + put_extern_sym(sym, NULL, 0, 0); + rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info)); +--- tcc-0.9.23/il-gen.c 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/il-gen.c 2007-11-07 10:04:32.000000000 -0500 +@@ -3,19 +3,7 @@ + * + * Copyright (c) 2002 Fabrice Bellard + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * Licensed under LGPL v2.1, see file COPYING in this tarball. + */ + + /* number of available registers */ +--- tcc-0.9.24/libtcc1.c 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/c/libtcc1.c 2007-11-07 10:04:02.000000000 -0500 +@@ -107,7 +107,7 @@ + }; + + /* XXX: use gcc/tcc intrinsic ? */ +-#if defined(__i386__) ++#if 1 + #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ + : "=r" ((USItype) (sh)), \ +@@ -399,7 +399,7 @@ + if (vv.s.high < 0) + vv.ll = __negdi2 (vv.ll); + +- __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w); ++ __udivmoddi4 (uu.ll, vv.ll, &w); + if (c) + w = __negdi2 (w); + return w; +@@ -428,7 +428,7 @@ + u.s.low = u.s.high >> (b - 32); + u.s.high = u.s.high >> 31; + } else if (b != 0) { +- u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b)); ++ u.s.low = ((unsigned)u.s.low >> b) | ((unsigned)u.s.high << (32 - b)); + u.s.high = u.s.high >> b; + } + return u.ll; +@@ -447,7 +447,7 @@ + u.s.low = (unsigned)u.s.high >> (b - 32); + u.s.high = 0; + } else if (b != 0) { +- u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b)); ++ u.s.low = ((unsigned)u.s.low >> b) | ((unsigned)u.s.high << (32 - b)); + u.s.high = (unsigned)u.s.high >> b; + } + return u.ll; +@@ -475,7 +475,7 @@ + #endif + } + +-#if defined(__i386__) ++#if 1 + /* FPU control word for rounding to nearest mode */ + unsigned short __tcc_fpu_control = 0x137f; + /* FPU control word for round to zero mode for int conversion */ +--- tcc-0.9.23/Makefile 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/Makefile 2007-11-07 10:04:32.000000000 -0500 +@@ -3,20 +3,21 @@ + # + include config.mak + +-CFLAGS=-O2 -g -Wall ++CFLAGS+=-g -Wall -fsigned-char -Os + ifndef CONFIG_WIN32 +-LIBS=-ldl ++LIBS=-lm ++ifndef CONFIG_NOLDL ++LIBS+=-ldl ++endif + BCHECK_O=bcheck.o + endif + CFLAGS_P=$(CFLAGS) -pg -static -DCONFIG_TCC_STATIC + LIBS_P= + +-CFLAGS+=-mpreferred-stack-boundary=2 +-ifeq ($(GCC_MAJOR),2) +-CFLAGS+=-m386 -malign-functions=0 +-else +-CFLAGS+=-march=i386 -falign-functions=0 -fno-strict-aliasing +-endif ++#CFLAGS+=-mpreferred-stack-boundary=2 -falign-functions=0 ++#ifneq ($(GCC_MAJOR),2) ++CFLAGS+=-fno-strict-aliasing ++#endif + + DISAS=objdump -d + INSTALL=install +@@ -46,11 +47,10 @@ + endif + + # run local version of tcc with local libraries and includes +-TCC=./tcc -B. -I. ++TCC=./tcc -B. -I./include -I. + +-all: $(PROGS) \ +- libtcc1.a $(BCHECK_O) tcc-doc.html tcc.1 libtcc.a \ +- libtcc_test$(EXESUF) ++all: $(PROGS) libtcc1.a $(BCHECK_O) libtcc.a libtcc_test$(EXESUF) \ ++ tcc-doc.html tcc.1 + + Makefile: config.mak + +@@ -59,45 +59,45 @@ + test: test.ref test.out + @if diff -u test.ref test.out ; then echo "Auto Test OK"; fi + +-tcctest.ref: tcctest.c +- $(CC) $(CFLAGS) -I. -o $@ $< ++tcctest.ref: tests/tcctest.c ++ $(CC) $(CFLAGS) -I. -Iinclude -o $@ $< + + test.ref: tcctest.ref + ./tcctest.ref > $@ + +-test.out: tcc tcctest.c +- $(TCC) -run tcctest.c > $@ ++test.out: tcc libtcc1.a tests/tcctest.c ++ $(TCC) -run tests/tcctest.c > $@ + +-run: tcc tcctest.c +- $(TCC) -run tcctest.c ++run: tcc tests/tcctest.c ++ $(TCC) -run tests/tcctest.c + + # iterated test2 (compile tcc then compile tcctest.c !) +-test2: tcc tcc.c tcctest.c test.ref +- $(TCC) -run tcc.c -B. -I. -run tcctest.c > test.out2 ++test2: tcc tcc.c tests/tcctest.c test.ref ++ $(TCC) -run tcc.c -B. -I. -run tests/tcctest.c > test.out2 + @if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi + + # iterated test3 (compile tcc then compile tcc then compile tcctest.c !) +-test3: tcc tcc.c tcctest.c test.ref +- $(TCC) -run tcc.c -B. -I. -run tcc.c -B. -I. -run tcctest.c > test.out3 ++test3: tcc tcc.c tests/tcctest.c test.ref ++ $(TCC) -run tcc.c -B. -I. -run tcc.c -B. -I. -run tests/tcctest.c > test.out3 + @if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi + + # binary output test + test4: tcc test.ref + # dynamic output +- $(TCC) -o tcctest1 tcctest.c ++ $(TCC) -o tcctest1 tests/tcctest.c + ./tcctest1 > test1.out + @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi + # static output +- $(TCC) -static -o tcctest2 tcctest.c ++ $(TCC) -static -o tcctest2 tests/tcctest.c + ./tcctest2 > test2.out + @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi + # object + link output +- $(TCC) -c -o tcctest3.o tcctest.c ++ $(TCC) -c -o tcctest3.o tests/tcctest.c + $(TCC) -o tcctest3 tcctest3.o + ./tcctest3 > test3.out + @if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi + # dynamic output + bound check +- $(TCC) -b -o tcctest4 tcctest.c ++ $(TCC) -b -o tcctest4 tests/tcctest.c + ./tcctest4 > test4.out + @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi + +@@ -137,11 +137,11 @@ + + # Host Tiny C Compiler + ifdef CONFIG_WIN32 +-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h tccpe.c ++tcc$(EXESUF): tcc.c i386/* tccelf.c tccasm.c tcctok.h libtcc.h win32/tccpe.c + $(CC) $(CFLAGS) -DTCC_TARGET_PE -o $@ $< $(LIBS) + else + ifeq ($(ARCH),i386) +-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h ++tcc$(EXESUF): tcc.c i386/* tccelf.c tccasm.c tcctok.h libtcc.h + $(CC) $(CFLAGS) -o $@ $< $(LIBS) + endif + ifeq ($(ARCH),arm) +@@ -151,20 +151,20 @@ + endif + + # Cross Tiny C Compilers +-i386-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h ++i386-tcc$(EXESUF): tcc.c i386/* tccelf.c tccasm.c tcctok.h libtcc.h + $(CC) $(CFLAGS) -o $@ $< $(LIBS) + + c67-tcc$(EXESUF): tcc.c c67-gen.c tccelf.c tccasm.c tcctok.h libtcc.h tcccoff.c + $(CC) $(CFLAGS) -DTCC_TARGET_C67 -o $@ $< $(LIBS) + + arm-tcc$(EXESUF): tcc.c arm-gen.c tccelf.c tccasm.c tcctok.h libtcc.h +- $(CC) $(CFLAGS) -DTCC_TARGET_ARM -o $@ $< $(LIBS) ++ $(CC) $(CFLAGS) -DTCC_TARGET_ARM -DTCC_ARM_EABI -o $@ $< $(LIBS) + +-i386-win32-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h tccpe.c ++i386-win32-tcc$(EXESUF): tcc.c i386/* tccelf.c tccasm.c tcctok.h libtcc.h win32/tccpe.c + $(CC) $(CFLAGS) -DTCC_TARGET_PE -o $@ $< $(LIBS) + + # windows utilities +-tiny_impdef$(EXESUF): tiny_impdef.c ++tiny_impdef$(EXESUF): win32/tiny_impdef.c + $(CC) $(CFLAGS) -o $@ $< -lkernel32 + + # TinyCC runtime libraries +@@ -174,6 +174,9 @@ + LIBTCC1_CC=./tcc.exe -Bwin32 + else + LIBTCC1_OBJS=libtcc1.o ++ifeq ($(ARCH),i386) ++LIBTCC1_OBJS+=i386/alloca86.o i386/bound-alloca86.o ++endif + LIBTCC1_CC=$(CC) + endif + +@@ -191,12 +194,12 @@ + + install: tcc_install libinstall + +-tcc_install: $(PROGS) tcc.1 libtcc1.a $(BCHECK_O) tcc-doc.html tcc.1 ++tcc_install: $(PROGS) libtcc1.a $(BCHECK_O) tcc-doc.html tcc.1 + mkdir -p "$(bindir)" + $(INSTALL) -s -m755 $(PROGS) "$(bindir)" + ifndef CONFIG_WIN32 + mkdir -p "$(mandir)/man1" +- $(INSTALL) tcc.1 "$(mandir)/man1" ++ -$(INSTALL) tcc.1 "$(mandir)/man1" + endif + mkdir -p "$(tccdir)" + mkdir -p "$(tccdir)/include" +@@ -207,19 +210,18 @@ + cp -r win32/examples/. "$(tccdir)/examples" + else + $(INSTALL) -m644 libtcc1.a $(BCHECK_O) "$(tccdir)" +- $(INSTALL) -m644 stdarg.h stddef.h stdbool.h float.h varargs.h \ +- tcclib.h "$(tccdir)/include" ++ $(INSTALL) -m644 include/* "$(tccdir)/include" + endif + mkdir -p "$(docdir)" +- $(INSTALL) -m644 tcc-doc.html "$(docdir)" ++ -$(INSTALL) -m644 tcc-doc.html "$(docdir)" + ifdef CONFIG_WIN32 + $(INSTALL) -m644 win32/readme.txt "$(docdir)" + endif + + clean: +- rm -f *~ *.o *.a tcc tcc1 tcct tcc_g tcctest.ref *.bin *.i ex2 \ ++ rm -f *~ *.o *.a tcc tcc.1 tcct tcc_g tcctest.ref *.bin *.i ex2 \ + core gmon.out test.out test.ref a.out tcc_p \ +- *.exe *.lib tcc.pod libtcc_test \ ++ *.exe *.lib tcc.pod libtcc_test i386/*.o \ + tcctest[1234] test[1234].out $(PROGS) win32/lib/*.o + + distclean: clean +@@ -236,13 +238,13 @@ + mkdir -p "$(includedir)" + $(INSTALL) -m644 libtcc.h "$(includedir)" + +-libtcc.o: tcc.c i386-gen.c Makefile ++libtcc.o: tcc.c i386/i386-gen.c Makefile + $(CC) $(CFLAGS) -DLIBTCC -c -o $@ $< + + libtcc.a: libtcc.o + $(AR) rcs $@ $^ + +-libtcc_test$(EXESUF): libtcc_test.c libtcc.a ++libtcc_test$(EXESUF): tests/libtcc_test.c libtcc.a + $(CC) $(CFLAGS) -o $@ $< libtcc.a $(LIBS) + + libtest: libtcc_test +@@ -282,11 +284,11 @@ + + # documentation and man page + tcc-doc.html: tcc-doc.texi +- texi2html -monolithic -number $< ++ -texi2html -monolithic -number $< + + tcc.1: tcc-doc.texi +- ./texi2pod.pl $< tcc.pod +- pod2man --section=1 --center=" " --release=" " tcc.pod > $@ ++ -./texi2pod.pl $< tcc.pod ++ -pod2man --section=1 --center=" " --release=" " tcc.pod > $@ + + FILE=tcc-$(shell cat VERSION) + +@@ -294,5 +296,5 @@ + tar: + rm -rf /tmp/$(FILE) + cp -r . /tmp/$(FILE) +- ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS ) ++ ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude .hg ) + rm -rf /tmp/$(FILE) +--- tcc-0.9.24/README 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/demo/expat/README 2007-11-07 10:04:16.000000000 -0500 +@@ -1,91 +1,137 @@ +-Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler +------------------------------------------------------------------------ + +-Features: +--------- ++ Expat, Release 2.0.1 + +-- SMALL! You can compile and execute C code everywhere, for example on +- rescue disks. ++This is Expat, a C library for parsing XML, written by James Clark. ++Expat is a stream-oriented XML parser. This means that you register ++handlers with the parser before starting the parse. These handlers ++are called when the parser discovers the associated structures in the ++document being parsed. A start tag is an example of the kind of ++structures for which you may register handlers. ++ ++Windows users should use the expat_win32bin package, which includes ++both precompiled libraries and executables, and source code for ++developers. ++ ++Expat is free software. You may copy, distribute, and modify it under ++the terms of the License contained in the file COPYING distributed ++with this package. This license is the same as the MIT/X Consortium ++license. ++ ++Versions of Expat that have an odd minor version (the middle number in ++the release above), are development releases and should be considered ++as beta software. Releases with even minor version numbers are ++intended to be production grade software. ++ ++If you are building Expat from a check-out from the CVS repository, ++you need to run a script that generates the configure script using the ++GNU autoconf and libtool tools. To do this, you need to have ++autoconf 2.52 or newer and libtool 1.4 or newer (1.5 or newer preferred). ++Run the script like this: + +-- FAST! tcc generates optimized x86 code. No byte code +- overhead. Compile, assemble and link about 7 times faster than 'gcc +- -O0'. ++ ./buildconf.sh + +-- UNLIMITED! Any C dynamic library can be used directly. TCC is +- heading torward full ISOC99 compliance. TCC can of course compile +- itself. ++Once this has been done, follow the same instructions as for building ++from a source distribution. + +-- SAFE! tcc includes an optional memory and bound checker. Bound +- checked code can be mixed freely with standard code. ++To build Expat from a source distribution, you first run the ++configuration shell script in the top level distribution directory: + +-- Compile and execute C source directly. No linking or assembly +- necessary. Full C preprocessor included. ++ ./configure + +-- C script supported : just add '#!/usr/local/bin/tcc -run' at the first +- line of your C source, and execute it directly from the command +- line. ++There are many options which you may provide to configure (which you ++can discover by running configure with the --help option). But the ++one of most interest is the one that sets the installation directory. ++By default, the configure script will set things up to install ++libexpat into /usr/local/lib, expat.h into /usr/local/include, and ++xmlwf into /usr/local/bin. If, for example, you'd prefer to install ++into /home/me/mystuff/lib, /home/me/mystuff/include, and ++/home/me/mystuff/bin, you can tell configure about that with: + +-Documentation: +-------------- ++ ./configure --prefix=/home/me/mystuff + +-1) Installation on a i386 Linux host (for Windows read win32/readme.txt) ++Another interesting option is to enable 64-bit integer support for ++line and column numbers and the over-all byte index: + +- ./configure +- make +- make test +- make install ++ ./configure CPPFLAGS=-DXML_LARGE_SIZE ++ ++However, such a modification would be a breaking change to the ABI ++and is therefore not recommended for general use - e.g. as part of ++a Linux distribution - but rather for builds with special requirements. ++ ++After running the configure script, the "make" command will build ++things and "make install" will install things into their proper ++location. Have a look at the "Makefile" to learn about additional ++"make" options. Note that you need to have write permission into ++the directories into which things will be installed. + +-By default, tcc is installed in /usr/local/bin. +-./configure --help shows configuration options. ++If you are interested in building Expat to provide document ++information in UTF-16 rather than the default UTF-8, follow these ++instructions (after having run "make distclean"): + ++ 1. For UTF-16 output as unsigned short (and version/error ++ strings as char), run: + +-2) Introduction ++ ./configure CPPFLAGS=-DXML_UNICODE + +-We assume here that you know ANSI C. Look at the example ex1.c to know +-what the programs look like. ++ For UTF-16 output as wchar_t (incl. version/error strings), ++ run: + +-The include file can be used if you want a small basic libc +-include support (especially useful for floppy disks). Of course, you +-can also use standard headers, although they are slower to compile. ++ ./configure CFLAGS="-g -O2 -fshort-wchar" \ ++ CPPFLAGS=-DXML_UNICODE_WCHAR_T + +-You can begin your C script with '#!/usr/local/bin/tcc -run' on the first +-line and set its execute bits (chmod a+x your_script). Then, you can +-launch the C code as a shell or perl script :-) The command line +-arguments are put in 'argc' and 'argv' of the main functions, as in +-ANSI C. ++ 2. Edit the MakeFile, changing: + +-3) Examples ++ LIBRARY = libexpat.la + +-ex1.c: simplest example (hello world). Can also be launched directly +-as a script: './ex1.c'. ++ to: + +-ex2.c: more complicated example: find a number with the four +-operations given a list of numbers (benchmark). ++ LIBRARY = libexpatw.la + +-ex3.c: compute fibonacci numbers (benchmark). ++ (Note the additional "w" in the library name.) + +-ex4.c: more complicated: X11 program. Very complicated test in fact +-because standard headers are being used ! ++ 3. Run "make buildlib" (which builds the library only). ++ Or, to save step 2, run "make buildlib LIBRARY=libexpatw.la". + +-ex5.c: 'hello world' with standard glibc headers. ++ 4. Run "make installlib" (which installs the library only). ++ Or, if step 2 was omitted, run "make installlib LIBRARY=libexpatw.la". + +-tcc.c: TCC can of course compile itself. Used to check the code +-generator. ++Using DESTDIR or INSTALL_ROOT is enabled, with INSTALL_ROOT being the default ++value for DESTDIR, and the rest of the make file using only DESTDIR. ++It works as follows: ++ $ make install DESTDIR=/path/to/image ++overrides the in-makefile set DESTDIR, while both ++ $ INSTALL_ROOT=/path/to/image make install ++ $ make install INSTALL_ROOT=/path/to/image ++use DESTDIR=$(INSTALL_ROOT), even if DESTDIR eventually is defined in the ++environment, because variable-setting priority is ++1) commandline ++2) in-makefile ++3) environment + +-tcctest.c: auto test for TCC which tests many subtle possible bugs. Used +-when doing 'make test'. ++Note for Solaris users: The "ar" command is usually located in ++"/usr/ccs/bin", which is not in the default PATH. You will need to ++add this to your path for the "make" command, and probably also switch ++to GNU make (the "make" found in /usr/ccs/bin does not seem to work ++properly -- appearantly it does not understand .PHONY directives). If ++you're using ksh or bash, use this command to build: + +-4) Full Documentation ++ PATH=/usr/ccs/bin:$PATH make + +-Please read tcc-doc.html to have all the features of TCC. ++When using Expat with a project using autoconf for configuration, you ++can use the probing macro in conftools/expat.m4 to determine how to ++include Expat. See the comments at the top of that file for more ++information. + +-Additional information is available for the Windows port in +-win32/readme.txt. ++A reference manual is available in the file doc/reference.html in this ++distribution. + +-License: +-------- ++The homepage for this project is http://www.libexpat.org/. There ++are links there to connect you to the bug reports page. If you need ++to report a bug when you don't have access to a browser, you may also ++send a bug report by email to expat-bugs@mail.libexpat.org. + +-TCC is distributed under the GNU Lesser General Public License (see +-COPYING file). ++Discussion related to the direction of future expat development takes ++place on expat-discuss@mail.libexpat.org. Archives of this list and ++other Expat-related lists may be found at: + +-Fabrice Bellard. ++ http://mail.libexpat.org/mailman/listinfo/ +--- tcc-0.9.23/tcc.1 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/tcc.1 2007-11-07 10:04:32.000000000 -0500 +@@ -1,7 +1,8 @@ +-.\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13 ++.\" Automatically generated by Pod::Man version 1.15 ++.\" Fri Oct 5 16:48:47 2007 + .\" + .\" Standard preamble: +-.\" ======================================================================== ++.\" ====================================================================== + .de Sh \" Subsection heading + .br + .if t .Sp +@@ -14,6 +15,12 @@ + .if t .sp .5v + .if n .sp + .. ++.de Ip \" List item ++.br ++.ie \\n(.$>=3 .ne \\$3 ++.el .ne 3 ++.IP "\\$1" \\$2 ++.. + .de Vb \" Begin verbatim text + .ft CW + .nf +@@ -21,14 +28,15 @@ + .. + .de Ve \" End verbatim text + .ft R ++ + .fi + .. + .\" Set up some character translations and predefined strings. \*(-- will + .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left + .\" double quote, and \*(R" will give a right double quote. | will give a +-.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +-.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +-.\" expand to `' in nroff, nothing in troff, for use with C<>. ++.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used ++.\" to do unbreakable dashes and therefore won't be available. \*(C` and ++.\" \*(C' expand to `' in nroff, nothing in troff, for use with C<> + .tr \(*W-|\(bv\*(Tr + .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' + .ie n \{\ +@@ -48,10 +56,10 @@ + . ds R" '' + 'br\} + .\" +-.\" If the F register is turned on, we'll generate index entries on stderr for +-.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +-.\" entries marked with X<> in POD. Of course, you'll have to process the +-.\" output yourself in some meaningful fashion. ++.\" If the F register is turned on, we'll generate index entries on stderr ++.\" for titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and ++.\" index entries marked with X<> in POD. Of course, you'll have to process ++.\" the output yourself in some meaningful fashion. + .if \nF \{\ + . de IX + . tm Index:\\$1\t\\n%\t"\\$2" +@@ -60,13 +68,14 @@ + . rr F + .\} + .\" +-.\" For nroff, turn off justification. Always turn off hyphenation; it makes +-.\" way too many mistakes in technical documents. ++.\" For nroff, turn off justification. Always turn off hyphenation; it ++.\" makes way too many mistakes in technical documents. + .hy 0 + .if n .na + .\" + .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). + .\" Fear. Run. Save yourself. No user-serviceable parts. ++.bd B 3 + . \" fudge factors for nroff and troff + .if n \{\ + . ds #H 0 +@@ -126,10 +135,11 @@ + . ds Ae AE + .\} + .rm #[ #] #H #V #F C +-.\" ======================================================================== ++.\" ====================================================================== + .\" + .IX Title "TCC 1" +-.TH TCC 1 "2005-06-18" " " " " ++.TH TCC 1 " " "2007-10-05" " " ++.UC + .SH "NAME" + tcc \- Tiny C Compiler + .SH "SYNOPSIS" +@@ -142,59 +152,58 @@ + arguments. + .PP + Here are some examples to understand the logic: +-.ie n .IP """\f(CBtcc \-run a.c\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-run a.c\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-run a.c\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-run a.c\f(CW\fR" 4 + .IX Item "tcc -run a.c" + Compile \fIa.c\fR and execute it directly +-.ie n .IP """\f(CBtcc \-run a.c arg1\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-run a.c arg1\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-run a.c arg1\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-run a.c arg1\f(CW\fR" 4 + .IX Item "tcc -run a.c arg1" + Compile a.c and execute it directly. arg1 is given as first argument to + the \f(CW\*(C`main()\*(C'\fR of a.c. +-.ie n .IP """\f(CBtcc a.c \-run b.c arg1\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc a.c \-run b.c arg1\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc a.c \-run b.c arg1\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc a.c \-run b.c arg1\f(CW\fR" 4 + .IX Item "tcc a.c -run b.c arg1" + Compile \fIa.c\fR and \fIb.c\fR, link them together and execute them. arg1 is given + as first argument to the \f(CW\*(C`main()\*(C'\fR of the resulting program. Because +-multiple C files are specified, \fB\-\-\fR are necessary to clearly separate the ++multiple C files are specified, \fB\--\fR are necessary to clearly separate the + program arguments from the \s-1TCC\s0 options. +-.ie n .IP """\f(CBtcc \-o myprog a.c b.c\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-o myprog a.c b.c\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-o myprog a.c b.c\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-o myprog a.c b.c\f(CW\fR" 4 + .IX Item "tcc -o myprog a.c b.c" + Compile \fIa.c\fR and \fIb.c\fR, link them and generate the executable \fImyprog\fR. +-.ie n .IP """\f(CBtcc \-o myprog a.o b.o\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-o myprog a.o b.o\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-o myprog a.o b.o\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-o myprog a.o b.o\f(CW\fR" 4 + .IX Item "tcc -o myprog a.o b.o" + link \fIa.o\fR and \fIb.o\fR together and generate the executable \fImyprog\fR. +-.ie n .IP """\f(CBtcc \-c a.c\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-c a.c\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-c a.c\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-c a.c\f(CW\fR" 4 + .IX Item "tcc -c a.c" + Compile \fIa.c\fR and generate object file \fIa.o\fR. +-.ie n .IP """\f(CBtcc \-c asmfile.S\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-c asmfile.S\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-c asmfile.S\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-c asmfile.S\f(CW\fR" 4 + .IX Item "tcc -c asmfile.S" + Preprocess with C preprocess and assemble \fIasmfile.S\fR and generate + object file \fIasmfile.o\fR. +-.ie n .IP """\f(CBtcc \-c asmfile.s\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-c asmfile.s\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-c asmfile.s\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-c asmfile.s\f(CW\fR" 4 + .IX Item "tcc -c asmfile.s" + Assemble (but not preprocess) \fIasmfile.s\fR and generate object file + \&\fIasmfile.o\fR. +-.ie n .IP """\f(CBtcc \-r \-o ab.o a.c b.c\f(CW""" 4 +-.el .IP "\f(CW\f(CBtcc \-r \-o ab.o a.c b.c\f(CW\fR" 4 ++.if n .Ip "\f(CW""""\f(CBtcc \-r \-o ab.o a.c b.c\f(CW""""\fR" 4 ++.el .Ip "\f(CW\f(CBtcc \-r \-o ab.o a.c b.c\f(CW\fR" 4 + .IX Item "tcc -r -o ab.o a.c b.c" + Compile \fIa.c\fR and \fIb.c\fR, link them together and generate the object file \fIab.o\fR. + .PP + Scripting: + .PP + \&\s-1TCC\s0 can be invoked from \fIscripts\fR, just as shell scripts. You just +-need to add \f(CW\*(C`#!/usr/local/bin/tcc \-run\*(C'\fR at the start of your C source: ++need to add \f(CW\*(C`#!/usr/bin/tcc \-run\*(C'\fR at the start of your C source: + .PP + .Vb 2 +-\& #!/usr/local/bin/tcc -run ++\& #!/usr/bin/tcc -run + \& #include + .Ve +-.PP + .Vb 5 + \& int main() + \& { +@@ -204,23 +213,23 @@ + .Ve + .SH "OPTIONS" + .IX Header "OPTIONS" +-.IP "\fB\-v\fR" 4 ++.Ip "\fB\-v\fR" 4 + .IX Item "-v" + Display current \s-1TCC\s0 version. +-.IP "\fB\-c\fR" 4 ++.Ip "\fB\-c\fR" 4 + .IX Item "-c" + Generate an object file (\fB\-o\fR option must also be given). +-.IP "\fB\-o outfile\fR" 4 ++.Ip "\fB\-o outfile\fR" 4 + .IX Item "-o outfile" + Put object file, executable, or dll into output file \fIoutfile\fR. +-.IP "\fB\-Bdir\fR" 4 ++.Ip "\fB\-Bdir\fR" 4 + .IX Item "-Bdir" + Set the path where the tcc internal libraries can be found (default is + \&\fIPREFIX/lib/tcc\fR). +-.IP "\fB\-bench\fR" 4 ++.Ip "\fB\-bench\fR" 4 + .IX Item "-bench" + Output compilation statistics. +-.IP "\fB\-run source [args...]\fR" 4 ++.Ip "\fB\-run source [args...]\fR" 4 + .IX Item "-run source [args...]" + Compile file \fIsource\fR and run it with the command line arguments + \&\fIargs\fR. In order to be able to give more than one argument to a +@@ -230,11 +239,10 @@ + .Vb 1 + \& tcc "-run -L/usr/X11R6/lib -lX11" ex4.c + .Ve +-.Sp + In a script, it gives the following header: + .Sp + .Vb 6 +-\& #!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 ++\& #!/usr/bin/tcc -run -L/usr/X11R6/lib -lX11 + \& #include + \& int main(int argc, char **argv) + \& { +@@ -243,7 +251,7 @@ + .Ve + .PP + Preprocessor options: +-.IP "\fB\-Idir\fR" 4 ++.Ip "\fB\-Idir\fR" 4 + .IX Item "-Idir" + Specify an additional include path. Include paths are searched in the + order they are specified. +@@ -252,100 +260,100 @@ + include paths are: \fI/usr/local/include\fR, \fI/usr/include\fR + and \fIPREFIX/lib/tcc/include\fR. (\fI\s-1PREFIX\s0\fR is usually + \&\fI/usr\fR or \fI/usr/local\fR). +-.IP "\fB\-Dsym[=val]\fR" 4 ++.Ip "\fB\-Dsym[=val]\fR" 4 + .IX Item "-Dsym[=val]" + Define preprocessor symbol \fBsym\fR to + val. If val is not present, its value is \fB1\fR. Function-like macros can +-also be defined: \fB\-DF(a)=a+1\fR +-.IP "\fB\-Usym\fR" 4 ++also be defined: \fB\-\f(BIDF\fB\|(a)=a+1\fR ++.Ip "\fB\-Usym\fR" 4 + .IX Item "-Usym" + Undefine preprocessor symbol \fBsym\fR. + .PP + Compilation flags: + .PP + Note: each of the following warning options has a negative form beginning with +-\&\fB\-fno\-\fR. +-.IP "\fB\-funsigned\-char\fR" 4 ++\&\fB\-fno-\fR. ++.Ip "\fB\-funsigned-char\fR" 4 + .IX Item "-funsigned-char" + Let the \f(CW\*(C`char\*(C'\fR type be unsigned. +-.IP "\fB\-fsigned\-char\fR" 4 ++.Ip "\fB\-fsigned-char\fR" 4 + .IX Item "-fsigned-char" + Let the \f(CW\*(C`char\*(C'\fR type be signed. +-.IP "\fB\-fno\-common\fR" 4 ++.Ip "\fB\-fno-common\fR" 4 + .IX Item "-fno-common" + Do not generate common symbols for uninitialized data. +-.IP "\fB\-fleading\-underscore\fR" 4 ++.Ip "\fB\-fleading-underscore\fR" 4 + .IX Item "-fleading-underscore" + Add a leading underscore at the beginning of each C symbol. + .PP + Warning options: +-.IP "\fB\-w\fR" 4 ++.Ip "\fB\-w\fR" 4 + .IX Item "-w" + Disable all warnings. + .PP + Note: each of the following warning options has a negative form beginning with +-\&\fB\-Wno\-\fR. +-.IP "\fB\-Wimplicit\-function\-declaration\fR" 4 ++\&\fB\-Wno-\fR. ++.Ip "\fB\-Wimplicit-function-declaration\fR" 4 + .IX Item "-Wimplicit-function-declaration" + Warn about implicit function declaration. +-.IP "\fB\-Wunsupported\fR" 4 ++.Ip "\fB\-Wunsupported\fR" 4 + .IX Item "-Wunsupported" + Warn about unsupported \s-1GCC\s0 features that are ignored by \s-1TCC\s0. +-.IP "\fB\-Wwrite\-strings\fR" 4 ++.Ip "\fB\-Wwrite-strings\fR" 4 + .IX Item "-Wwrite-strings" + Make string constants be of type \f(CW\*(C`const char *\*(C'\fR instead of \f(CW\*(C`char + *\*(C'\fR. +-.IP "\fB\-Werror\fR" 4 ++.Ip "\fB\-Werror\fR" 4 + .IX Item "-Werror" + Abort compilation if warnings are issued. +-.IP "\fB\-Wall\fR" 4 ++.Ip "\fB\-Wall\fR" 4 + .IX Item "-Wall" + Activate all warnings, except \fB\-Werror\fR, \fB\-Wunusupported\fR and +-\&\fB\-Wwrite\-strings\fR. ++\&\fB\-Wwrite-strings\fR. + .PP + Linker options: +-.IP "\fB\-Ldir\fR" 4 ++.Ip "\fB\-Ldir\fR" 4 + .IX Item "-Ldir" + Specify an additional static library path for the \fB\-l\fR option. The + default library paths are \fI/usr/local/lib\fR, \fI/usr/lib\fR and \fI/lib\fR. +-.IP "\fB\-lxxx\fR" 4 ++.Ip "\fB\-lxxx\fR" 4 + .IX Item "-lxxx" + Link your program with dynamic library libxxx.so or static library + libxxx.a. The library is searched in the paths specified by the + \&\fB\-L\fR option. +-.IP "\fB\-shared\fR" 4 ++.Ip "\fB\-shared\fR" 4 + .IX Item "-shared" + Generate a shared library instead of an executable (\fB\-o\fR option + must also be given). +-.IP "\fB\-static\fR" 4 ++.Ip "\fB\-static\fR" 4 + .IX Item "-static" + Generate a statically linked executable (default is a shared linked + executable) (\fB\-o\fR option must also be given). +-.IP "\fB\-rdynamic\fR" 4 ++.Ip "\fB\-rdynamic\fR" 4 + .IX Item "-rdynamic" + Export global symbols to the dynamic linker. It is useful when a library + opened with \f(CW\*(C`dlopen()\*(C'\fR needs to access executable symbols. +-.IP "\fB\-r\fR" 4 ++.Ip "\fB\-r\fR" 4 + .IX Item "-r" + Generate an object file combining all input files (\fB\-o\fR option must + also be given). +-.IP "\fB\-Wl,\-Ttext,address\fR" 4 ++.Ip "\fB\-Wl,\-Ttext,address\fR" 4 + .IX Item "-Wl,-Ttext,address" + Set the start of the .text section to \fIaddress\fR. +-.IP "\fB\-Wl,\-\-oformat,fmt\fR" 4 ++.Ip "\fB\-Wl,\-\-oformat,fmt\fR" 4 + .IX Item "-Wl,--oformat,fmt" + Use \fIfmt\fR as output format. The supported output formats are: + .RS 4 +-.ie n .IP """elf32\-i386""" 4 +-.el .IP "\f(CWelf32\-i386\fR" 4 ++.if n .Ip "\f(CW""""elf32\-i386""""\fR" 4 ++.el .Ip "\f(CWelf32\-i386\fR" 4 + .IX Item "elf32-i386" + \&\s-1ELF\s0 output format (default) +-.ie n .IP """binary""" 4 +-.el .IP "\f(CWbinary\fR" 4 ++.if n .Ip "\f(CW""""binary""""\fR" 4 ++.el .Ip "\f(CWbinary\fR" 4 + .IX Item "binary" + Binary image (only for executable output) +-.ie n .IP """coff""" 4 +-.el .IP "\f(CWcoff\fR" 4 ++.if n .Ip "\f(CW""""coff""""\fR" 4 ++.el .Ip "\f(CWcoff\fR" 4 + .IX Item "coff" + \&\s-1COFF\s0 output format (only for executable output for TMS320C67xx target) + .RE +@@ -353,18 +361,18 @@ + .RE + .PP + Debugger options: +-.IP "\fB\-g\fR" 4 ++.Ip "\fB\-g\fR" 4 + .IX Item "-g" + Generate run time debug information so that you get clear run time + error messages: \f(CW\*(C` test.c:68: in function 'test5()': dereferencing + invalid pointer\*(C'\fR instead of the laconic \f(CW\*(C`Segmentation + fault\*(C'\fR. +-.IP "\fB\-b\fR" 4 ++.Ip "\fB\-b\fR" 4 + .IX Item "-b" + Generate additional support code to check + memory allocations and array/pointer bounds. \fB\-g\fR is implied. Note + that the generated code is slower and bigger in this case. +-.IP "\fB\-bt N\fR" 4 ++.Ip "\fB\-bt N\fR" 4 + .IX Item "-bt N" + Display N callers in stack traces. This is useful with \fB\-g\fR or + \&\fB\-b\fR. +--- tcc-0.9.24/tccasm.c 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/tccasm.c 2007-11-07 10:04:32.000000000 -0500 +@@ -24,7 +24,7 @@ + TokenSym *ts; + + snprintf(buf, sizeof(buf), "L..%u", n); +- ts = tok_alloc(buf, strlen(buf)); ++ ts = tok_alloc(s1, buf, strlen(buf)); + return ts->tok; + } + +@@ -46,18 +46,18 @@ + if (*p == 'b' || *p == 'f') { + /* backward or forward label */ + label = asm_get_local_label_name(s1, n); +- sym = label_find(label); ++ sym = label_find(s1, label); + if (*p == 'b') { + /* backward : find the last corresponding defined label */ + if (sym && sym->r == 0) + sym = sym->prev_tok; + if (!sym) +- error("local label '%d' not found backward", n); ++ tcc_error(s1, "local label '%d' not found backward", n); + } else { + /* forward */ + if (!sym || sym->r) { + /* if the last label is defined, then define a new one */ +- sym = label_push(&s1->asm_labels, label, 0); ++ sym = label_push(s1, &s1->asm_labels, label, 0); + sym->type.t = VT_STATIC | VT_VOID; + } + } +@@ -67,21 +67,21 @@ + pe->v = n; + pe->sym = NULL; + } else { +- error("invalid number syntax"); ++ tcc_error(s1, "invalid number syntax"); + } +- next(); ++ next(s1); + break; + case '+': +- next(); ++ next(s1); + asm_expr_unary(s1, pe); + break; + case '-': + case '~': + op = tok; +- next(); ++ next(s1); + asm_expr_unary(s1, pe); + if (pe->sym) +- error("invalid operation with label"); ++ tcc_error(s1, "invalid operation with label"); + if (op == '-') + pe->v = -pe->v; + else +@@ -91,19 +91,19 @@ + case TOK_LCHAR: + pe->v = tokc.i; + pe->sym = NULL; +- next(); ++ next(s1); + break; + case '(': +- next(); ++ next(s1); + asm_expr(s1, pe); +- skip(')'); ++ skip(s1, ')'); + break; + default: + if (tok >= TOK_IDENT) { + /* label case : if the label was not found, add one */ +- sym = label_find(tok); ++ sym = label_find(s1, tok); + if (!sym) { +- sym = label_push(&s1->asm_labels, tok, 0); ++ sym = label_push(s1, &s1->asm_labels, tok, 0); + /* NOTE: by default, the symbol is global */ + sym->type.t = VT_VOID; + } +@@ -115,9 +115,9 @@ + pe->v = 0; + pe->sym = sym; + } +- next(); ++ next(s1); + } else { +- error("bad expression syntax [%s]", get_tok_str(tok, &tokc)); ++ tcc_error(s1, "bad expression syntax [%s]", get_tok_str(s1, tok, &tokc)); + } + break; + } +@@ -134,10 +134,10 @@ + if (op != '*' && op != '/' && op != '%' && + op != TOK_SHL && op != TOK_SAR) + break; +- next(); ++ next(s1); + asm_expr_unary(s1, &e2); + if (pe->sym || e2.sym) +- error("invalid operation with label"); ++ tcc_error(s1, "invalid operation with label"); + switch(op) { + case '*': + pe->v *= e2.v; +@@ -145,7 +145,7 @@ + case '/': + if (e2.v == 0) { + div_error: +- error("division by zero"); ++ tcc_error(s1, "division by zero"); + } + pe->v /= e2.v; + break; +@@ -175,10 +175,10 @@ + op = tok; + if (op != '&' && op != '|' && op != '^') + break; +- next(); ++ next(s1); + asm_expr_prod(s1, &e2); + if (pe->sym || e2.sym) +- error("invalid operation with label"); ++ tcc_error(s1, "invalid operation with label"); + switch(op) { + case '&': + pe->v &= e2.v; +@@ -204,7 +204,7 @@ + op = tok; + if (op != '+' && op != '-') + break; +- next(); ++ next(s1); + asm_expr_logic(s1, &e2); + if (op == '+') { + if (pe->sym != NULL && e2.sym != NULL) +@@ -232,7 +232,7 @@ + pe->sym = NULL; /* same symbols can be substracted to NULL */ + } else { + cannot_relocate: +- error("invalid operation with label"); ++ tcc_error(s1, "invalid operation with label"); + } + } + } +@@ -248,7 +248,7 @@ + ExprValue e; + asm_expr(s1, &e); + if (e.sym) +- expect("constant"); ++ expect(s1, "constant"); + return e.v; + } + +@@ -259,13 +259,13 @@ + { + Sym *sym; + +- sym = label_find(label); ++ sym = label_find(s1, label); + if (sym) { + if (sym->r) { + /* the label is already defined */ + if (!is_local) { +- error("assembler label '%s' already defined", +- get_tok_str(label, NULL)); ++ tcc_error(s1, "assembler label '%s' already defined", ++ get_tok_str(s1, label, NULL)); + } else { + /* redefinition of local labels is possible */ + goto new_label; +@@ -273,7 +273,7 @@ + } + } else { + new_label: +- sym = label_push(&s1->asm_labels, label, 0); ++ sym = label_push(s1, &s1->asm_labels, label, 0); + sym->type.t = VT_STATIC | VT_VOID; + } + sym->r = sh_num; +@@ -298,11 +298,11 @@ + sec = SECTION_ABS; + else + sec = st->sections[s->r]; +- put_extern_sym2(s, sec, (long)s->next, 0, 0); ++ put_extern_sym2(st, s, sec, (long)s->next, 0, 0); + } + /* remove label */ + table_ident[s->v - TOK_IDENT]->sym_label = NULL; +- sym_free(s); ++ sym_free(st,s); + } + st->asm_labels = NULL; + } +@@ -328,18 +328,18 @@ + uint8_t *ptr; + + /* assembler directive */ +- next(); ++ next(s1); + sec = cur_text_section; + switch(tok) { + case TOK_ASM_align: + case TOK_ASM_skip: + case TOK_ASM_space: + tok1 = tok; +- next(); ++ next(s1); + n = asm_int_expr(s1); + if (tok1 == TOK_ASM_align) { + if (n < 0 || (n & (n-1)) != 0) +- error("alignment must be a positive power of two"); ++ tcc_error(s1, "alignment must be a positive power of two"); + offset = (ind + n - 1) & -n; + size = offset - ind; + /* the section must have a compatible alignment */ +@@ -350,19 +350,19 @@ + } + v = 0; + if (tok == ',') { +- next(); ++ next(s1); + v = asm_int_expr(s1); + } + zero_pad: + if (sec->sh_type != SHT_NOBITS) { + sec->data_offset = ind; +- ptr = section_ptr_add(sec, size); ++ ptr = section_ptr_add(s1, sec, size); + memset(ptr, v, size); + } + ind += size; + break; + case TOK_ASM_quad: +- next(); ++ next(s1); + for(;;) { + uint64_t vl; + const char *p; +@@ -370,22 +370,22 @@ + p = tokc.cstr->data; + if (tok != TOK_PPNUM) { + error_constant: +- error("64 bit constant"); ++ tcc_error(s1, "64 bit constant"); + } + vl = strtoll(p, (char **)&p, 0); + if (*p != '\0') + goto error_constant; +- next(); ++ next(s1); + if (sec->sh_type != SHT_NOBITS) { + /* XXX: endianness */ +- gen_le32(vl); +- gen_le32(vl >> 32); ++ gen_le32(s1, vl); ++ gen_le32(s1, vl >> 32); + } else { + ind += 8; + } + if (tok != ',') + break; +- next(); ++ next(s1); + } + break; + case TOK_ASM_byte: +@@ -399,52 +399,52 @@ + case TOK_INT: + size = 4; + asm_data: +- next(); ++ next(s1); + for(;;) { + ExprValue e; + asm_expr(s1, &e); + if (sec->sh_type != SHT_NOBITS) { + if (size == 4) { +- gen_expr32(&e); ++ gen_expr32(s1, &e); + } else { + if (e.sym) +- expect("constant"); ++ expect(s1, "constant"); + if (size == 1) +- g(e.v); ++ g(s1, e.v); + else +- gen_le16(e.v); ++ gen_le16(s1, e.v); + } + } else { + ind += size; + } + if (tok != ',') + break; +- next(); ++ next(s1); + } + break; + case TOK_ASM_fill: + { + int repeat, size, val, i, j; + uint8_t repeat_buf[8]; +- next(); ++ next(s1); + repeat = asm_int_expr(s1); + if (repeat < 0) { +- error("repeat < 0; .fill ignored"); ++ tcc_error(s1, "repeat < 0; .fill ignored"); + break; + } + size = 1; + val = 0; + if (tok == ',') { +- next(); ++ next(s1); + size = asm_int_expr(s1); + if (size < 0) { +- error("size < 0; .fill ignored"); ++ tcc_error(s1, "size < 0; .fill ignored"); + break; + } + if (size > 8) + size = 8; + if (tok == ',') { +- next(); ++ next(s1); + val = asm_int_expr(s1); + } + } +@@ -459,7 +459,7 @@ + repeat_buf[7] = 0; + for(i = 0; i < repeat; i++) { + for(j = 0; j < size; j++) { +- g(repeat_buf[j]); ++ g(s1, repeat_buf[j]); + } + } + } +@@ -467,11 +467,11 @@ + case TOK_ASM_org: + { + unsigned long n; +- next(); ++ next(s1); + /* XXX: handle section symbols too */ + n = asm_int_expr(s1); + if (n < ind) +- error("attempt to .org backwards"); ++ tcc_error(s1, "attempt to .org backwards"); + v = 0; + size = n - ind; + goto zero_pad; +@@ -482,14 +482,14 @@ + { + Sym *sym; + +- next(); +- sym = label_find(tok); ++ next(s1); ++ sym = label_find(s1, tok); + if (!sym) { +- sym = label_push(&s1->asm_labels, tok, 0); ++ sym = label_push(s1, &s1->asm_labels, tok, 0); + sym->type.t = VT_VOID; + } + sym->type.t &= ~VT_STATIC; +- next(); ++ next(s1); + } + break; + case TOK_ASM_string: +@@ -500,19 +500,19 @@ + int i, size, t; + + t = tok; +- next(); ++ next(s1); + for(;;) { + if (tok != TOK_STR) +- expect("string constant"); ++ expect(s1, "string constant"); + p = tokc.cstr->data; + size = tokc.cstr->size; + if (t == TOK_ASM_ascii && size > 0) + size--; + for(i = 0; i < size; i++) +- g(p[i]); +- next(); ++ g(s1, p[i]); ++ next(s1); + if (tok == ',') { +- next(); ++ next(s1); + } else if (tok != TOK_STR) { + break; + } +@@ -526,12 +526,12 @@ + char sname[64]; + tok1 = tok; + n = 0; +- next(); ++ next(s1); + if (tok != ';' && tok != TOK_LINEFEED) { + n = asm_int_expr(s1); +- next(); ++ next(s1); + } +- sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n); ++ sprintf(sname, (n?".%s%d":".%s"), get_tok_str(s1, tok1, NULL), n); + use_section(s1, sname); + } + break; +@@ -540,21 +540,21 @@ + char sname[256]; + + /* XXX: support more options */ +- next(); ++ next(s1); + sname[0] = '\0'; + while (tok != ';' && tok != TOK_LINEFEED && tok != ',') { + if (tok == TOK_STR) +- pstrcat(sname, sizeof(sname), tokc.cstr->data); ++ pstrcat(s1, sname, sizeof(sname), tokc.cstr->data); + else +- pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL)); +- next(); ++ pstrcat(s1, sname, sizeof(sname), get_tok_str(s1, tok, NULL)); ++ next(s1); + } + if (tok == ',') { + /* skip section options */ +- next(); ++ next(s1); + if (tok != TOK_STR) +- expect("string constant"); +- next(); ++ expect(s1, "string constant"); ++ next(s1); + } + last_text_section = cur_text_section; + use_section(s1, sname); +@@ -563,16 +563,16 @@ + case TOK_ASM_previous: + { + Section *sec; +- next(); ++ next(s1); + if (!last_text_section) +- error("no previous section referenced"); ++ tcc_error(s1, "no previous section referenced"); + sec = cur_text_section; + use_section1(s1, last_text_section); + last_text_section = sec; + } + break; + default: +- error("unknown assembler directive '.%s'", get_tok_str(tok, NULL)); ++ tcc_error(s1, "unknown assembler directive '.%s'", get_tok_str(s1, tok, NULL)); + break; + } + } +@@ -617,12 +617,12 @@ + + /* XXX: undefine C labels */ + +- ch = file->buf_ptr[0]; +- tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; ++ fch = file->buf_ptr[0]; ++ next_tok_flags = TOK_FLAG_BOW | TOK_FLAG_BOL | TOK_FLAG_BOF; + parse_flags = PARSE_FLAG_ASM_COMMENTS; + if (do_preprocess) + parse_flags |= PARSE_FLAG_PREPROCESS; +- next(); ++ next(s1); + for(;;) { + if (tok == TOK_EOF) + break; +@@ -631,7 +631,7 @@ + if (tok == '#') { + /* horrible gas comment */ + while (tok != TOK_LINEFEED) +- next(); ++ next(s1); + } else if (tok == '.') { + asm_parse_directive(s1); + } else if (tok == TOK_PPNUM) { +@@ -640,24 +640,24 @@ + p = tokc.cstr->data; + n = strtoul(p, (char **)&p, 10); + if (*p != '\0') +- expect("':'"); ++ expect(s1, "':'"); + /* new local label */ + asm_new_label(s1, asm_get_local_label_name(s1, n), 1); +- next(); +- skip(':'); ++ next(s1); ++ skip(s1, ':'); + goto redo; + } else if (tok >= TOK_IDENT) { + /* instruction or label */ + opcode = tok; +- next(); ++ next(s1); + if (tok == ':') { + /* new label */ + asm_new_label(s1, opcode, 0); +- next(); ++ next(s1); + goto redo; + } else if (tok == '=') { + int n; +- next(); ++ next(s1); + n = asm_int_expr(s1); + asm_new_label1(s1, opcode, 0, SHN_ABS, n); + goto redo; +@@ -667,10 +667,10 @@ + } + /* end of line */ + if (tok != ';' && tok != TOK_LINEFEED){ +- expect("end of line"); ++ expect(s1, "end of line"); + } + parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ +- next(); ++ next(s1); + } + + asm_free_labels(s1); +@@ -696,7 +696,7 @@ + + cur_text_section->data_offset = ind; + +- free_defines(define_start); ++ free_defines(s1, define_start); + + return ret; + } +@@ -712,15 +712,15 @@ + BufferedFile *bf, *saved_file; + int saved_parse_flags, *saved_macro_ptr; + +- bf = tcc_malloc(sizeof(BufferedFile)); ++ bf = tcc_malloc(s1, sizeof(BufferedFile)); + memset(bf, 0, sizeof(BufferedFile)); +- bf->fd = -1; ++ bf->fd = NULL; + bf->buf_ptr = str; + bf->buf_end = str + len; + str[len] = CH_EOB; + /* same name as current file so that errors are correctly + reported */ +- pstrcpy(bf->filename, sizeof(bf->filename), file->filename); ++ pstrcpy(s1, bf->filename, sizeof(bf->filename), file->filename); + bf->line_num = file->line_num; + saved_file = file; + file = bf; +@@ -733,22 +733,23 @@ + parse_flags = saved_parse_flags; + macro_ptr = saved_macro_ptr; + file = saved_file; +- tcc_free(bf); ++ ckfree((char *)bf); + } + + /* find a constraint by its number or id (gcc 3 extended + syntax). return -1 if not found. Return in *pp in char after the + constraint */ +-static int find_constraint(ASMOperand *operands, int nb_operands, ++static int find_constraint(TCCState *s1, ++ ASMOperand *operands, int nb_operands, + const char *name, const char **pp) + { + int index; + TokenSym *ts; + const char *p; + +- if (isnum(*name)) { ++ if (isnum(s1, *name)) { + index = 0; +- while (isnum(*name)) { ++ while (isnum(s1, *name)) { + index = (index * 10) + (*name) - '0'; + name++; + } +@@ -758,7 +759,7 @@ + name++; + p = strchr(name, ']'); + if (p) { +- ts = tok_alloc(name, p - name); ++ ts = tok_alloc(s1, name, p - name); + for(index = 0; index < nb_operands; index++) { + if (operands[index].id == ts->tok) + goto found; +@@ -777,7 +778,8 @@ + return index; + } + +-static void subst_asm_operands(ASMOperand *operands, int nb_operands, ++static void subst_asm_operands(TCCState *s1, ++ ASMOperand *operands, int nb_operands, + int nb_outputs, + CString *out_str, CString *in_str) + { +@@ -786,7 +788,7 @@ + ASMOperand *op; + SValue sv; + +- cstr_new(out_str); ++ cstr_new(s1, out_str); + str = in_str->data; + for(;;) { + c = *str++; +@@ -799,9 +801,9 @@ + if (*str == 'c' || *str == 'n' || + *str == 'b' || *str == 'w' || *str == 'h') + modifier = *str++; +- index = find_constraint(operands, nb_operands, str, &str); ++ index = find_constraint(s1, operands, nb_operands, str, &str); + if (index < 0) +- error("invalid operand reference after %%"); ++ tcc_error(s1, "invalid operand reference after %%"); + op = &operands[index]; + sv = *op->vt; + if (op->reg >= 0) { +@@ -809,10 +811,10 @@ + if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory) + sv.r |= VT_LVAL; + } +- subst_asm_operand(out_str, &sv, modifier); ++ subst_asm_operand(s1, out_str, &sv, modifier); + } else { + add_char: +- cstr_ccat(out_str, c); ++ cstr_ccat(s1, out_str, c); + if (c == '\0') + break; + } +@@ -820,7 +822,8 @@ + } + + +-static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr, ++static void parse_asm_operands(TCCState *s1, ++ ASMOperand *operands, int *nb_operands_ptr, + int is_output) + { + ASMOperand *op; +@@ -830,26 +833,26 @@ + nb_operands = *nb_operands_ptr; + for(;;) { + if (nb_operands >= MAX_ASM_OPERANDS) +- error("too many asm operands"); ++ tcc_error(s1, "too many asm operands"); + op = &operands[nb_operands++]; + op->id = 0; + if (tok == '[') { +- next(); ++ next(s1); + if (tok < TOK_IDENT) +- expect("identifier"); ++ expect(s1, "identifier"); + op->id = tok; +- next(); +- skip(']'); ++ next(s1); ++ skip(s1, ']'); + } + if (tok != TOK_STR) +- expect("string constant"); +- op->constraint = tcc_malloc(tokc.cstr->size); ++ expect(s1, "string constant"); ++ op->constraint = tcc_malloc(s1, tokc.cstr->size); + strcpy(op->constraint, tokc.cstr->data); +- next(); +- skip('('); +- gexpr(); ++ next(s1); ++ skip(s1, '('); ++ gexpr(s1); + if (is_output) { +- test_lvalue(); ++ test_lvalue(s1); + } else { + /* we want to avoid LLOCAL case, except when the 'm' + constraint is used. Note that it may come from +@@ -859,13 +862,13 @@ + ((vtop->r & VT_VALMASK) == VT_LLOCAL || + (vtop->r & VT_VALMASK) < VT_CONST) && + !strchr(op->constraint, 'm')) { +- gv(RC_INT); ++ gv(s1, RC_INT); + } + } + op->vt = vtop; +- skip(')'); ++ skip(s1, ')'); + if (tok == ',') { +- next(); ++ next(s1); + } else { + break; + } +@@ -874,62 +877,63 @@ + } + } + +-static void parse_asm_str(CString *astr) ++static void parse_asm_str(TCCState *s1, ++ CString *astr) + { +- skip('('); ++ skip(s1, '('); + /* read the string */ + if (tok != TOK_STR) +- expect("string constant"); +- cstr_new(astr); ++ expect(s1, "string constant"); ++ cstr_new(s1, astr); + while (tok == TOK_STR) { + /* XXX: add \0 handling too ? */ +- cstr_cat(astr, tokc.cstr->data); +- next(); ++ cstr_cat(s1, astr, tokc.cstr->data); ++ next(s1); + } +- cstr_ccat(astr, '\0'); ++ cstr_ccat(s1, astr, '\0'); + } + + /* parse the GCC asm() instruction */ +-static void asm_instr(void) ++static void asm_instr(TCCState *s1) + { + CString astr, astr1; + ASMOperand operands[MAX_ASM_OPERANDS]; + int nb_inputs, nb_outputs, nb_operands, i, must_subst, out_reg; + uint8_t clobber_regs[NB_ASM_REGS]; + +- next(); ++ next(s1); + /* since we always generate the asm() instruction, we can ignore + volatile */ + if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) { +- next(); ++ next(s1); + } +- parse_asm_str(&astr); ++ parse_asm_str(s1, &astr); + nb_operands = 0; + nb_outputs = 0; + must_subst = 0; + memset(clobber_regs, 0, sizeof(clobber_regs)); + if (tok == ':') { +- next(); ++ next(s1); + must_subst = 1; + /* output args */ +- parse_asm_operands(operands, &nb_operands, 1); ++ parse_asm_operands(s1, operands, &nb_operands, 1); + nb_outputs = nb_operands; + if (tok == ':') { +- next(); ++ next(s1); + if (tok != ')') { + /* input args */ +- parse_asm_operands(operands, &nb_operands, 0); ++ parse_asm_operands(s1, operands, &nb_operands, 0); + if (tok == ':') { + /* clobber list */ + /* XXX: handle registers */ +- next(); ++ next(s1); + for(;;) { + if (tok != TOK_STR) +- expect("string constant"); +- asm_clobber(clobber_regs, tokc.cstr->data); +- next(); ++ expect(s1, "string constant"); ++ asm_clobber(s1, clobber_regs, tokc.cstr->data); ++ next(s1); + if (tok == ',') { +- next(); ++ next(s1); + } else { + break; + } +@@ -938,18 +942,18 @@ + } + } + } +- skip(')'); ++ skip(s1, ')'); + /* NOTE: we do not eat the ';' so that we can restore the current + token after the assembler parsing */ + if (tok != ';') +- expect("';'"); ++ expect(s1, "';'"); + nb_inputs = nb_operands - nb_outputs; + + /* save all values in the memory */ +- save_regs(0); ++ save_regs(s1, 0); + + /* compute constraints */ +- asm_compute_constraints(operands, nb_operands, nb_outputs, ++ asm_compute_constraints(s1, operands, nb_operands, nb_outputs, + clobber_regs, &out_reg); + + /* substitute the operands in the asm string. No substitution is +@@ -958,8 +962,8 @@ + printf("asm: \"%s\"\n", (char *)astr.data); + #endif + if (must_subst) { +- subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr); +- cstr_free(&astr); ++ subst_asm_operands(s1, operands, nb_operands, nb_outputs, &astr1, &astr); ++ cstr_free(s1, &astr); + } else { + astr1 = astr; + } +@@ -968,40 +972,40 @@ + #endif + + /* generate loads */ +- asm_gen_code(operands, nb_operands, nb_outputs, 0, ++ asm_gen_code(s1, operands, nb_operands, nb_outputs, 0, + clobber_regs, out_reg); + + /* assemble the string with tcc internal assembler */ +- tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1); ++ tcc_assemble_inline(s1, astr1.data, astr1.size - 1); + + /* restore the current C token */ +- next(); ++ next(s1); + + /* store the output values if needed */ +- asm_gen_code(operands, nb_operands, nb_outputs, 1, ++ asm_gen_code(s1, operands, nb_operands, nb_outputs, 1, + clobber_regs, out_reg); + + /* free everything */ + for(i=0;iconstraint); +- vpop(); ++ ckfree(op->constraint); ++ vpop(s1 ); + } +- cstr_free(&astr1); ++ cstr_free(s1, &astr1); + } + +-static void asm_global_instr(void) ++static void asm_global_instr(TCCState *s1) + { + CString astr; + +- next(); +- parse_asm_str(&astr); +- skip(')'); ++ next(s1); ++ parse_asm_str(s1, &astr); ++ skip(s1, ')'); + /* NOTE: we do not eat the ';' so that we can restore the current + token after the assembler parsing */ + if (tok != ';') +- expect("';'"); ++ expect(s1, "';'"); + + #ifdef ASM_DEBUG + printf("asm_global: \"%s\"\n", (char *)astr.data); +@@ -1010,12 +1014,12 @@ + ind = cur_text_section->data_offset; + + /* assemble the string with tcc internal assembler */ +- tcc_assemble_inline(tcc_state, astr.data, astr.size - 1); ++ tcc_assemble_inline(s1, astr.data, astr.size - 1); + + cur_text_section->data_offset = ind; + + /* restore the current C token */ +- next(); ++ next(s1); + +- cstr_free(&astr); ++ cstr_free(s1, &astr); + } +--- tcc-0.9.23/tcc.c 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/tcc.c 2007-11-07 10:04:32.000000000 -0500 +@@ -17,339 +17,73 @@ + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +-#define _GNU_SOURCE +-#include "config.h" + +-#ifdef CONFIG_TCCBOOT ++#include "tcc.h" + +-#include "tccboot.h" +-#define CONFIG_TCC_STATIC ++/* This stuff is used by the code generation backend. */ + +-#else +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef WIN32 +-#include +-#endif +-#ifndef WIN32 +-#include +-#include +-#endif +- +-#endif /* !CONFIG_TCCBOOT */ +- +-#include "elf.h" +-#include "stab.h" +- +-#ifndef O_BINARY +-#define O_BINARY 0 +-#endif +- +-#include "libtcc.h" +- +-/* parser debug */ +-//#define PARSE_DEBUG +-/* preprocessor debug */ +-//#define PP_DEBUG +-/* include file debug */ +-//#define INC_DEBUG +- +-//#define MEM_DEBUG +- +-/* assembler debug */ +-//#define ASM_DEBUG +- +-/* target selection */ +-//#define TCC_TARGET_I386 /* i386 code generator */ +-//#define TCC_TARGET_ARM /* ARMv4 code generator */ +-//#define TCC_TARGET_C67 /* TMS320C67xx code generator */ +- +-/* default target is I386 */ +-#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \ +- !defined(TCC_TARGET_C67) +-#define TCC_TARGET_I386 +-#endif ++static int ind; /* output code index */ ++static int loc; /* local variable index */ ++static Section *cur_text_section; /* current section where function code is generated */ ++static SValue *vtop; ++static Section *symtab_section; ++static CType func_vt; /* current function return type (used by return instruction) */ ++static int func_vc; ++static Section *lbounds_section; /* contains local data bound description */ ++/* Predefined types */ ++static CType char_pointer_type; ++static CType func_old_type; + +-#if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ +- !defined(TCC_TARGET_C67) +-#define CONFIG_TCC_BCHECK /* enable bound checking code */ +-#endif ++/* compile with built-in memory and bounds checker */ ++static int do_bounds_check = 0; + +-#if defined(WIN32) && !defined(TCC_TARGET_PE) +-#define CONFIG_TCC_STATIC ++#ifdef TCC_TARGET_I386 ++#include "i386/i386-gen.c" + #endif + +-/* define it to include assembler support */ +-#if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67) +-#define CONFIG_TCC_ASM ++#ifdef TCC_TARGET_ARM ++#include "arm-gen.c" + #endif + +-/* object format selection */ +-#if defined(TCC_TARGET_C67) +-#define TCC_TARGET_COFF ++#ifdef TCC_TARGET_C67 ++#include "c67-gen.c" + #endif + +-#define FALSE 0 +-#define false 0 +-#define TRUE 1 +-#define true 1 +-typedef int BOOL; +- +-/* path to find crt1.o, crti.o and crtn.o. Only needed when generating +- executables or dlls */ +-#define CONFIG_TCC_CRT_PREFIX "/usr/lib" +- +-#define INCLUDE_STACK_SIZE 32 +-#define IFDEF_STACK_SIZE 64 +-#define VSTACK_SIZE 256 +-#define STRING_MAX_SIZE 1024 +-#define PACK_STACK_SIZE 8 +- +-#define TOK_HASH_SIZE 8192 /* must be a power of two */ +-#define TOK_ALLOC_INCR 512 /* must be a power of two */ +-#define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */ +- +-/* token symbol management */ +-typedef struct TokenSym { +- struct TokenSym *hash_next; +- struct Sym *sym_define; /* direct pointer to define */ +- struct Sym *sym_label; /* direct pointer to label */ +- struct Sym *sym_struct; /* direct pointer to structure */ +- struct Sym *sym_identifier; /* direct pointer to identifier */ +- int tok; /* token number */ +- int len; +- char str[1]; +-} TokenSym; +- +-typedef struct CString { +- int size; /* size in bytes */ +- void *data; /* either 'char *' or 'int *' */ +- int size_allocated; +- void *data_allocated; /* if non NULL, data has been malloced */ +-} CString; +- +-/* type definition */ +-typedef struct CType { +- int t; +- struct Sym *ref; +-} CType; +- +-/* constant value */ +-typedef union CValue { +- long double ld; +- double d; +- float f; +- int i; +- unsigned int ui; +- unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */ +- long long ll; +- unsigned long long ull; +- struct CString *cstr; +- void *ptr; +- int tab[1]; +-} CValue; +- +-/* value on stack */ +-typedef struct SValue { +- CType type; /* type */ +- unsigned short r; /* register + flags */ +- unsigned short r2; /* second register, used for 'long long' +- type. If not used, set to VT_CONST */ +- CValue c; /* constant, if VT_CONST */ +- struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */ +-} SValue; +- +-/* symbol management */ +-typedef struct Sym { +- int v; /* symbol token */ +- int r; /* associated register */ +- int c; /* associated number */ +- CType type; /* associated type */ +- struct Sym *next; /* next related symbol */ +- struct Sym *prev; /* prev symbol in stack */ +- struct Sym *prev_tok; /* previous symbol for this token */ +-} Sym; +- +-/* section definition */ +-/* XXX: use directly ELF structure for parameters ? */ +-/* special flag to indicate that the section should not be linked to +- the other ones */ +-#define SHF_PRIVATE 0x80000000 +- +-typedef struct Section { +- unsigned long data_offset; /* current data offset */ +- unsigned char *data; /* section data */ +- unsigned long data_allocated; /* used for realloc() handling */ +- int sh_name; /* elf section name (only used during output) */ +- int sh_num; /* elf section number */ +- int sh_type; /* elf section type */ +- int sh_flags; /* elf section flags */ +- int sh_info; /* elf section info */ +- int sh_addralign; /* elf section alignment */ +- int sh_entsize; /* elf entry size */ +- unsigned long sh_size; /* section size (only used during output) */ +- unsigned long sh_addr; /* address at which the section is relocated */ +- unsigned long sh_offset; /* address at which the section is relocated */ +- int nb_hashed_syms; /* used to resize the hash table */ +- struct Section *link; /* link to another section */ +- struct Section *reloc; /* corresponding section for relocation, if any */ +- struct Section *hash; /* hash table for symbols */ +- struct Section *next; +- char name[1]; /* section name */ +-} Section; +- +-typedef struct DLLReference { +- int level; +- char name[1]; +-} DLLReference; +- +-/* GNUC attribute definition */ +-typedef struct AttributeDef { +- int aligned; +- int packed; +- Section *section; +- unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */ +- unsigned char dllexport; +-} AttributeDef; +- +-#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */ +-#define SYM_FIELD 0x20000000 /* struct/union field symbol space */ +-#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */ +- +-/* stored in 'Sym.c' field */ +-#define FUNC_NEW 1 /* ansi function prototype */ +-#define FUNC_OLD 2 /* old function prototype */ +-#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */ +- +-/* stored in 'Sym.r' field */ +-#define FUNC_CDECL 0 /* standard c call */ +-#define FUNC_STDCALL 1 /* pascal c call */ +-#define FUNC_FASTCALL1 2 /* first param in %eax */ +-#define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */ +-#define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */ +- +-/* field 'Sym.t' for macros */ +-#define MACRO_OBJ 0 /* object like macro */ +-#define MACRO_FUNC 1 /* function like macro */ +- +-/* field 'Sym.r' for C labels */ +-#define LABEL_DEFINED 0 /* label is defined */ +-#define LABEL_FORWARD 1 /* label is forward defined */ +-#define LABEL_DECLARED 2 /* label is declared but never used */ +- +-/* type_decl() types */ +-#define TYPE_ABSTRACT 1 /* type without variable */ +-#define TYPE_DIRECT 2 /* type with variable */ +- +-#define IO_BUF_SIZE 8192 +- +-typedef struct BufferedFile { +- uint8_t *buf_ptr; +- uint8_t *buf_end; +- int fd; +- int line_num; /* current line number - here to simplify code */ +- int ifndef_macro; /* #ifndef macro / #endif search */ +- int ifndef_macro_saved; /* saved ifndef_macro */ +- int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ +- char inc_type; /* type of include */ +- char inc_filename[512]; /* filename specified by the user */ +- char filename[1024]; /* current filename - here to simplify code */ +- unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */ +-} BufferedFile; +- +-#define CH_EOB '\\' /* end of buffer or '\0' char in file */ +-#define CH_EOF (-1) /* end of file */ +- +-/* parsing state (used to save parser state to reparse part of the +- source several times) */ +-typedef struct ParseState { +- int *macro_ptr; +- int line_num; +- int tok; +- CValue tokc; +-} ParseState; +- +-/* used to record tokens */ +-typedef struct TokenString { +- int *str; +- int len; +- int allocated_len; +- int last_line_num; +-} TokenString; +- +-/* include file cache, used to find files faster and also to eliminate +- inclusion if the include file is protected by #ifndef ... #endif */ +-typedef struct CachedInclude { +- int ifndef_macro; +- int hash_next; /* -1 if none */ +- char type; /* '"' or '>' to give include type */ +- char filename[1]; /* path specified in #include */ +-} CachedInclude; +- +-#define CACHED_INCLUDES_HASH_SIZE 512 +- + /* parser */ + static struct BufferedFile *file; +-static int ch, tok; ++static int fch, tok; + static CValue tokc; + static CString tokcstr; /* current parsed string, if any */ + /* additional informations about token */ +-static int tok_flags; +-#define TOK_FLAG_BOL 0x0001 /* beginning of line before */ +-#define TOK_FLAG_BOF 0x0002 /* beginning of file before */ +-#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */ ++static int tok_flags, next_tok_flags; + + static int *macro_ptr, *macro_ptr_allocated; + static int *unget_saved_macro_ptr; + static int unget_saved_buffer[TOK_MAX_SIZE + 1]; + static int unget_buffer_enabled; + static int parse_flags; +-#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */ +-#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */ +-#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a +- token. line feed is also +- returned at eof */ +-#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ +- + static Section *text_section, *data_section, *bss_section; /* predefined sections */ +-static Section *cur_text_section; /* current section where function code is +- generated */ + #ifdef CONFIG_TCC_ASM + static Section *last_text_section; /* to handle .previous asm directive */ + #endif ++ + /* bound check related sections */ + static Section *bounds_section; /* contains global data bound description */ +-static Section *lbounds_section; /* contains local data bound description */ + /* symbol sections */ +-static Section *symtab_section, *strtab_section; ++static Section *strtab_section; + + /* debug sections */ + static Section *stab_section, *stabstr_section; + +-/* loc : local variable index +- ind : output code index ++/* + rsym: return symbol + anon_sym: anonymous symbol index + */ +-static int rsym, anon_sym, ind, loc; ++static int rsym, anon_sym; + /* expression generation modifiers */ + static int const_wanted; /* true if constant wanted */ +-static int nocode_wanted; /* true if no code generation wanted for an expression */ + static int global_expr; /* true if compound literals must be allocated + globally (used during initializers parsing */ +-static CType func_vt; /* current function return type (used by return +- instruction) */ +-static int func_vc; + static int last_line_num, last_ind, func_ind; /* debug last line number and pc */ + static int tok_ident; + static TokenSym **table_ident; +@@ -360,21 +94,17 @@ + static Sym *define_stack; + static Sym *global_label_stack, *local_label_stack; + /* symbol allocator */ +-#define SYM_POOL_NB (8192 / sizeof(Sym)) + static Sym *sym_free_first; + +-static SValue vstack[VSTACK_SIZE], *vtop; ++static SValue vstack[VSTACK_SIZE]; + /* some predefined types */ +-static CType char_pointer_type, func_old_type, int_type; +-/* true if isid(c) || isnum(c) */ ++static CType int_type; ++/* true if isid(c) || isnum(st, c) */ + static unsigned char isidnum_table[256]; + + /* compile with debug symbol (and use them if error during execution) */ + static int do_debug = 0; + +-/* compile with built-in memory and bounds checker */ +-static int do_bounds_check = 0; +- + /* display benchmark infos */ + #if !defined(LIBTCC) + static int do_bench = 0; +@@ -392,581 +122,19 @@ + static int num_callers = 6; + static const char **rt_bound_error_msg; + +-/* XXX: get rid of this ASAP */ +-static struct TCCState *tcc_state; +- +-/* give the path of the tcc libraries */ +-static const char *tcc_lib_path = CONFIG_TCCDIR; +- +-struct TCCState { +- int output_type; +- +- BufferedFile **include_stack_ptr; +- int *ifdef_stack_ptr; +- +- /* include file handling */ +- char **include_paths; +- int nb_include_paths; +- char **sysinclude_paths; +- int nb_sysinclude_paths; +- CachedInclude **cached_includes; +- int nb_cached_includes; +- +- char **library_paths; +- int nb_library_paths; +- +- /* array of all loaded dlls (including those referenced by loaded +- dlls) */ +- DLLReference **loaded_dlls; +- int nb_loaded_dlls; +- +- /* sections */ +- Section **sections; +- int nb_sections; /* number of sections, including first dummy section */ +- +- /* got handling */ +- Section *got; +- Section *plt; +- unsigned long *got_offsets; +- int nb_got_offsets; +- /* give the correspondance from symtab indexes to dynsym indexes */ +- int *symtab_to_dynsym; +- +- /* temporary dynamic symbol sections (for dll loading) */ +- Section *dynsymtab_section; +- /* exported dynamic symbol section */ +- Section *dynsym; +- +- int nostdinc; /* if true, no standard headers are added */ +- int nostdlib; /* if true, no standard libraries are added */ +- +- int nocommon; /* if true, do not use common symbols for .bss data */ +- +- /* if true, static linking is performed */ +- int static_link; +- +- /* if true, all symbols are exported */ +- int rdynamic; +- +- /* if true, only link in referenced objects from archive */ +- int alacarte_link; +- +- /* address of text section */ +- unsigned long text_addr; +- int has_text_addr; +- +- /* output format, see TCC_OUTPUT_FORMAT_xxx */ +- int output_format; +- +- /* C language options */ +- int char_is_unsigned; +- int leading_underscore; +- +- /* warning switches */ +- int warn_write_strings; +- int warn_unsupported; +- int warn_error; +- int warn_none; +- int warn_implicit_function_declaration; +- +- /* error handling */ +- void *error_opaque; +- void (*error_func)(void *opaque, const char *msg); +- int error_set_jmp_enabled; +- jmp_buf error_jmp_buf; +- int nb_errors; +- +- /* tiny assembler state */ +- Sym *asm_labels; +- +- /* see include_stack_ptr */ +- BufferedFile *include_stack[INCLUDE_STACK_SIZE]; +- +- /* see ifdef_stack_ptr */ +- int ifdef_stack[IFDEF_STACK_SIZE]; +- +- /* see cached_includes */ +- int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE]; +- +- /* pack stack */ +- int pack_stack[PACK_STACK_SIZE]; +- int *pack_stack_ptr; +-}; +- +-/* The current value can be: */ +-#define VT_VALMASK 0x00ff +-#define VT_CONST 0x00f0 /* constant in vc +- (must be first non register value) */ +-#define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */ +-#define VT_LOCAL 0x00f2 /* offset on stack */ +-#define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */ +-#define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */ +-#define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */ +-#define VT_LVAL 0x0100 /* var is an lvalue */ +-#define VT_SYM 0x0200 /* a symbol value is added */ +-#define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for +- char/short stored in integer registers) */ +-#define VT_MUSTBOUND 0x0800 /* bound checking must be done before +- dereferencing value */ +-#define VT_BOUNDED 0x8000 /* value is bounded. The address of the +- bounding function call point is in vc */ +-#define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */ +-#define VT_LVAL_SHORT 0x2000 /* lvalue is a short */ +-#define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */ +-#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED) +- +-/* types */ +-#define VT_INT 0 /* integer type */ +-#define VT_BYTE 1 /* signed byte type */ +-#define VT_SHORT 2 /* short type */ +-#define VT_VOID 3 /* void type */ +-#define VT_PTR 4 /* pointer */ +-#define VT_ENUM 5 /* enum definition */ +-#define VT_FUNC 6 /* function type */ +-#define VT_STRUCT 7 /* struct/union definition */ +-#define VT_FLOAT 8 /* IEEE float */ +-#define VT_DOUBLE 9 /* IEEE double */ +-#define VT_LDOUBLE 10 /* IEEE long double */ +-#define VT_BOOL 11 /* ISOC99 boolean type */ +-#define VT_LLONG 12 /* 64 bit integer */ +-#define VT_LONG 13 /* long integer (NEVER USED as type, only +- during parsing) */ +-#define VT_BTYPE 0x000f /* mask for basic type */ +-#define VT_UNSIGNED 0x0010 /* unsigned type */ +-#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ +-#define VT_BITFIELD 0x0040 /* bitfield modifier */ +-#define VT_CONSTANT 0x0800 /* const modifier */ +-#define VT_VOLATILE 0x1000 /* volatile modifier */ +-#define VT_SIGNED 0x2000 /* signed type */ +- +-/* storage */ +-#define VT_EXTERN 0x00000080 /* extern definition */ +-#define VT_STATIC 0x00000100 /* static variable */ +-#define VT_TYPEDEF 0x00000200 /* typedef definition */ +-#define VT_INLINE 0x00000400 /* inline definition */ +- +-#define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */ +- +-/* type mask (except storage) */ +-#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE) +-#define VT_TYPE (~(VT_STORAGE)) +- +-/* token values */ +- +-/* warning: the following compare tokens depend on i386 asm code */ +-#define TOK_ULT 0x92 +-#define TOK_UGE 0x93 +-#define TOK_EQ 0x94 +-#define TOK_NE 0x95 +-#define TOK_ULE 0x96 +-#define TOK_UGT 0x97 +-#define TOK_LT 0x9c +-#define TOK_GE 0x9d +-#define TOK_LE 0x9e +-#define TOK_GT 0x9f +- +-#define TOK_LAND 0xa0 +-#define TOK_LOR 0xa1 +- +-#define TOK_DEC 0xa2 +-#define TOK_MID 0xa3 /* inc/dec, to void constant */ +-#define TOK_INC 0xa4 +-#define TOK_UDIV 0xb0 /* unsigned division */ +-#define TOK_UMOD 0xb1 /* unsigned modulo */ +-#define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */ +-#define TOK_CINT 0xb3 /* number in tokc */ +-#define TOK_CCHAR 0xb4 /* char constant in tokc */ +-#define TOK_STR 0xb5 /* pointer to string in tokc */ +-#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */ +-#define TOK_LCHAR 0xb7 +-#define TOK_LSTR 0xb8 +-#define TOK_CFLOAT 0xb9 /* float constant */ +-#define TOK_LINENUM 0xba /* line number info */ +-#define TOK_CDOUBLE 0xc0 /* double constant */ +-#define TOK_CLDOUBLE 0xc1 /* long double constant */ +-#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ +-#define TOK_ADDC1 0xc3 /* add with carry generation */ +-#define TOK_ADDC2 0xc4 /* add with carry use */ +-#define TOK_SUBC1 0xc5 /* add with carry generation */ +-#define TOK_SUBC2 0xc6 /* add with carry use */ +-#define TOK_CUINT 0xc8 /* unsigned int constant */ +-#define TOK_CLLONG 0xc9 /* long long constant */ +-#define TOK_CULLONG 0xca /* unsigned long long constant */ +-#define TOK_ARROW 0xcb +-#define TOK_DOTS 0xcc /* three dots */ +-#define TOK_SHR 0xcd /* unsigned shift right */ +-#define TOK_PPNUM 0xce /* preprocessor number */ +- +-#define TOK_SHL 0x01 /* shift left */ +-#define TOK_SAR 0x02 /* signed shift right */ +- +-/* assignement operators : normal operator or 0x80 */ +-#define TOK_A_MOD 0xa5 +-#define TOK_A_AND 0xa6 +-#define TOK_A_MUL 0xaa +-#define TOK_A_ADD 0xab +-#define TOK_A_SUB 0xad +-#define TOK_A_DIV 0xaf +-#define TOK_A_XOR 0xde +-#define TOK_A_OR 0xfc +-#define TOK_A_SHL 0x81 +-#define TOK_A_SAR 0x82 +- +-#ifndef offsetof +-#define offsetof(type, field) ((size_t) &((type *)0)->field) +-#endif +- +-#ifndef countof +-#define countof(tab) (sizeof(tab) / sizeof((tab)[0])) +-#endif +- +-/* WARNING: the content of this string encodes token numbers */ +-static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; +- +-#define TOK_EOF (-1) /* end of file */ +-#define TOK_LINEFEED 10 /* line feed */ +- +-/* all identificators and strings have token above that */ +-#define TOK_IDENT 256 +- +-/* only used for i386 asm opcodes definitions */ +-#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x) +- +-#define DEF_BWL(x) \ +- DEF(TOK_ASM_ ## x ## b, #x "b") \ +- DEF(TOK_ASM_ ## x ## w, #x "w") \ +- DEF(TOK_ASM_ ## x ## l, #x "l") \ +- DEF(TOK_ASM_ ## x, #x) +- +-#define DEF_WL(x) \ +- DEF(TOK_ASM_ ## x ## w, #x "w") \ +- DEF(TOK_ASM_ ## x ## l, #x "l") \ +- DEF(TOK_ASM_ ## x, #x) +- +-#define DEF_FP1(x) \ +- DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \ +- DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \ +- DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \ +- DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s") +- +-#define DEF_FP(x) \ +- DEF(TOK_ASM_ ## f ## x, "f" #x ) \ +- DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \ +- DEF_FP1(x) +- +-#define DEF_ASMTEST(x) \ +- DEF_ASM(x ## o) \ +- DEF_ASM(x ## no) \ +- DEF_ASM(x ## b) \ +- DEF_ASM(x ## c) \ +- DEF_ASM(x ## nae) \ +- DEF_ASM(x ## nb) \ +- DEF_ASM(x ## nc) \ +- DEF_ASM(x ## ae) \ +- DEF_ASM(x ## e) \ +- DEF_ASM(x ## z) \ +- DEF_ASM(x ## ne) \ +- DEF_ASM(x ## nz) \ +- DEF_ASM(x ## be) \ +- DEF_ASM(x ## na) \ +- DEF_ASM(x ## nbe) \ +- DEF_ASM(x ## a) \ +- DEF_ASM(x ## s) \ +- DEF_ASM(x ## ns) \ +- DEF_ASM(x ## p) \ +- DEF_ASM(x ## pe) \ +- DEF_ASM(x ## np) \ +- DEF_ASM(x ## po) \ +- DEF_ASM(x ## l) \ +- DEF_ASM(x ## nge) \ +- DEF_ASM(x ## nl) \ +- DEF_ASM(x ## ge) \ +- DEF_ASM(x ## le) \ +- DEF_ASM(x ## ng) \ +- DEF_ASM(x ## nle) \ +- DEF_ASM(x ## g) +- +-#define TOK_ASM_int TOK_INT +- +-enum tcc_token { +- TOK_LAST = TOK_IDENT - 1, +-#define DEF(id, str) id, +-#include "tcctok.h" +-#undef DEF +-}; +- +-static const char tcc_keywords[] = +-#define DEF(id, str) str "\0" +-#include "tcctok.h" +-#undef DEF +-; +- +-#define TOK_UIDENT TOK_DEFINE +- +-#ifdef WIN32 +-int __stdcall GetModuleFileNameA(void *, char *, int); +-void *__stdcall GetProcAddress(void *, const char *); +-void *__stdcall GetModuleHandleA(const char *); +-void *__stdcall LoadLibraryA(const char *); +-int __stdcall FreeConsole(void); +- +-#define snprintf _snprintf +-#define vsnprintf _vsnprintf +-#ifndef __GNUC__ +- #define strtold (long double)strtod +- #define strtof (float)strtod +- #define strtoll (long long)strtol +-#endif +-#elif defined(TCC_UCLIBC) || defined(__FreeBSD__) +-/* currently incorrect */ +-long double strtold(const char *nptr, char **endptr) +-{ +- return (long double)strtod(nptr, endptr); +-} +-float strtof(const char *nptr, char **endptr) +-{ +- return (float)strtod(nptr, endptr); +-} +-#else +-/* XXX: need to define this to use them in non ISOC99 context */ +-extern float strtof (const char *__nptr, char **__endptr); +-extern long double strtold (const char *__nptr, char **__endptr); +-#endif +- +-static char *pstrcpy(char *buf, int buf_size, const char *s); +-static char *pstrcat(char *buf, int buf_size, const char *s); +-static const char *tcc_basename(const char *name); +- +-static void next(void); +-static void next_nomacro(void); +-static void parse_expr_type(CType *type); +-static void expr_type(CType *type); +-static void unary_type(CType *type); +-static void block(int *bsym, int *csym, int *case_sym, int *def_sym, +- int case_reg, int is_expr); +-static int expr_const(void); +-static void expr_eq(void); +-static void gexpr(void); +-static void gen_inline_functions(void); +-static void decl(int l); +-static void decl_initializer(CType *type, Section *sec, unsigned long c, +- int first, int size_only); +-static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, +- int has_init, int v, int scope); +-int gv(int rc); +-void gv2(int rc1, int rc2); +-void move_reg(int r, int s); +-void save_regs(int n); +-void save_reg(int r); +-void vpop(void); +-void vswap(void); +-void vdup(void); +-int get_reg(int rc); +-int get_reg_ex(int rc,int rc2); +- +-struct macro_level { +- struct macro_level *prev; +- int *p; +-}; +- +-static void macro_subst(TokenString *tok_str, Sym **nested_list, +- const int *macro_str, struct macro_level **can_read_stream); +-void gen_op(int op); +-void force_charshort_cast(int t); +-static void gen_cast(CType *type); +-void vstore(void); +-static Sym *sym_find(int v); +-static Sym *sym_push(int v, CType *type, int r, int c); +- +-/* type handling */ +-static int type_size(CType *type, int *a); +-static inline CType *pointed_type(CType *type); +-static int pointed_size(CType *type); +-static int lvalue_type(int t); +-static int parse_btype(CType *type, AttributeDef *ad); +-static void type_decl(CType *type, AttributeDef *ad, int *v, int td); +-static int is_compatible_types(CType *type1, CType *type2); +- +-int ieee_finite(double d); +-void error(const char *fmt, ...); +-void vpushi(int v); +-void vrott(int n); +-void vnrott(int n); +-void lexpand_nr(void); +-static void vpush_global_sym(CType *type, int v); +-void vset(CType *type, int r, int v); +-void type_to_str(char *buf, int buf_size, +- CType *type, const char *varstr); +-char *get_tok_str(int v, CValue *cv); +-static Sym *get_sym_ref(CType *type, Section *sec, +- unsigned long offset, unsigned long size); +-static Sym *external_global_sym(int v, CType *type, int r); +- +-/* section generation */ +-static void section_realloc(Section *sec, unsigned long new_size); +-static void *section_ptr_add(Section *sec, unsigned long size); +-static void put_extern_sym(Sym *sym, Section *section, +- unsigned long value, unsigned long size); +-static void greloc(Section *s, Sym *sym, unsigned long addr, int type); +-static int put_elf_str(Section *s, const char *sym); +-static int put_elf_sym(Section *s, +- unsigned long value, unsigned long size, +- int info, int other, int shndx, const char *name); +-static int add_elf_sym(Section *s, unsigned long value, unsigned long size, +- int info, int other, int sh_num, const char *name); +-static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, +- int type, int symbol); +-static void put_stabs(const char *str, int type, int other, int desc, +- unsigned long value); +-static void put_stabs_r(const char *str, int type, int other, int desc, +- unsigned long value, Section *sec, int sym_index); +-static void put_stabn(int type, int other, int desc, int value); +-static void put_stabd(int type, int other, int desc); +-static int tcc_add_dll(TCCState *s, const char *filename, int flags); +- +-#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */ +-#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */ +-static int tcc_add_file_internal(TCCState *s, const char *filename, int flags); +- +-/* tcccoff.c */ +-int tcc_output_coff(TCCState *s1, FILE *f); +- +-/* tccpe.c */ +-void *resolve_sym(TCCState *s1, const char *sym, int type); +-int pe_load_def_file(struct TCCState *s1, FILE *fp); +-void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file); +-unsigned long pe_add_runtime(struct TCCState *s1); +-int tcc_output_pe(struct TCCState *s1, const char *filename); +- +-/* tccasm.c */ +- +-#ifdef CONFIG_TCC_ASM +- +-typedef struct ExprValue { +- uint32_t v; +- Sym *sym; +-} ExprValue; +- +-#define MAX_ASM_OPERANDS 30 +- +-typedef struct ASMOperand { +- int id; /* GCC 3 optionnal identifier (0 if number only supported */ +- char *constraint; +- char asm_str[16]; /* computed asm string for operand */ +- SValue *vt; /* C value of the expression */ +- int ref_index; /* if >= 0, gives reference to a output constraint */ +- int input_index; /* if >= 0, gives reference to an input constraint */ +- int priority; /* priority, used to assign registers */ +- int reg; /* if >= 0, register number used for this operand */ +- int is_llong; /* true if double register value */ +- int is_memory; /* true if memory operand */ +- int is_rw; /* for '+' modifier */ +-} ASMOperand; +- +-static void asm_expr(TCCState *s1, ExprValue *pe); +-static int asm_int_expr(TCCState *s1); +-static int find_constraint(ASMOperand *operands, int nb_operands, +- const char *name, const char **pp); +- +-static int tcc_assemble(TCCState *s1, int do_preprocess); +- +-#endif +- +-static void asm_instr(void); +-static void asm_global_instr(void); +- +-/* true if float/double/long double type */ +-static inline int is_float(int t) +-{ +- int bt; +- bt = t & VT_BTYPE; +- return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT; +-} +- +-#ifdef TCC_TARGET_I386 +-#include "i386-gen.c" +-#endif +- +-#ifdef TCC_TARGET_ARM +-#include "arm-gen.c" +-#endif +- +-#ifdef TCC_TARGET_C67 +-#include "c67-gen.c" +-#endif +- +-#ifdef CONFIG_TCC_STATIC +- +-#define RTLD_LAZY 0x001 +-#define RTLD_NOW 0x002 +-#define RTLD_GLOBAL 0x100 +-#define RTLD_DEFAULT NULL +- +-/* dummy function for profiling */ +-void *dlopen(const char *filename, int flag) +-{ +- return NULL; +-} +- +-const char *dlerror(void) +-{ +- return "error"; +-} +- +-typedef struct TCCSyms { +- char *str; +- void *ptr; +-} TCCSyms; +- +-#define TCCSYM(a) { #a, &a, }, +- +-/* add the symbol you want here if no dynamic linking is done */ +-static TCCSyms tcc_syms[] = { +-#if !defined(CONFIG_TCCBOOT) +- TCCSYM(printf) +- TCCSYM(fprintf) +- TCCSYM(fopen) +- TCCSYM(fclose) +-#endif +- { NULL, NULL }, +-}; +- +-void *resolve_sym(TCCState *s1, const char *symbol, int type) +-{ +- TCCSyms *p; +- p = tcc_syms; +- while (p->str != NULL) { +- if (!strcmp(p->str, symbol)) +- return p->ptr; +- p++; +- } +- return NULL; +-} +- +-#elif !defined(WIN32) +- +-#include +- +-void *resolve_sym(TCCState *s1, const char *sym, int type) +-{ +- return dlsym(RTLD_DEFAULT, sym); +-} +- +-#endif +- + /********************************************************/ + + /* we use our own 'finite' function to avoid potential problems with + non standard math libs */ + /* XXX: endianness dependent */ +-int ieee_finite(double d) ++int ieee_finite(TCCState *st, double d) + { + int *p = (int *)&d; + return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; + } + + /* copy a string and truncate it. */ +-static char *pstrcpy(char *buf, int buf_size, const char *s) ++static char *pstrcpy(TCCState *st, char *buf, int buf_size, const char *s) + { + char *q, *q_end; + int c; +@@ -976,9 +144,8 @@ + q_end = buf + buf_size - 1; + while (q < q_end) { + c = *s++; +- if (c == '\0') +- break; + *q++ = c; ++ if (!c) break; + } + *q = '\0'; + } +@@ -986,16 +153,16 @@ + } + + /* strcat and truncate. */ +-static char *pstrcat(char *buf, int buf_size, const char *s) ++static char *pstrcat(TCCState *st, char *buf, int buf_size, const char *s) + { + int len; + len = strlen(buf); + if (len < buf_size) +- pstrcpy(buf + len, buf_size - len, s); ++ pstrcpy(st, buf + len, buf_size - len, s); + return buf; + } + +-static int strstart(const char *str, const char *val, const char **ptr) ++static int strstart(TCCState *st, const char *str, const char *val, const char **ptr) + { + const char *p, *q; + p = str; +@@ -1011,71 +178,39 @@ + return 1; + } + +-/* memory management */ +-#ifdef MEM_DEBUG +-int mem_cur_size; +-int mem_max_size; +-#endif +- +-static inline void tcc_free(void *ptr) +-{ +-#ifdef MEM_DEBUG +- mem_cur_size -= malloc_usable_size(ptr); +-#endif +- free(ptr); +-} +- +-static void *tcc_malloc(unsigned long size) ++static void *tcc_malloc(TCCState *st, unsigned long size) + { +- void *ptr; +- ptr = malloc(size); +- if (!ptr && size) +- error("memory full"); +-#ifdef MEM_DEBUG +- mem_cur_size += malloc_usable_size(ptr); +- if (mem_cur_size > mem_max_size) +- mem_max_size = mem_cur_size; +-#endif ++ void *ptr = attemptckalloc(size); ++ if (!ptr && size)tcc_error(st, "memory full"); + return ptr; + } + +-static void *tcc_mallocz(unsigned long size) ++static void *tcc_mallocz(TCCState *st, unsigned long size) + { + void *ptr; +- ptr = tcc_malloc(size); ++ ptr = tcc_malloc(st, size); + memset(ptr, 0, size); + return ptr; + } + +-static inline void *tcc_realloc(void *ptr, unsigned long size) ++static inline void *tcc_realloc(TCCState *st, void *ptr, unsigned long size) + { +- void *ptr1; +-#ifdef MEM_DEBUG +- mem_cur_size -= malloc_usable_size(ptr); +-#endif +- ptr1 = realloc(ptr, size); +-#ifdef MEM_DEBUG +- /* NOTE: count not correct if alloc error, but not critical */ +- mem_cur_size += malloc_usable_size(ptr1); +- if (mem_cur_size > mem_max_size) +- mem_max_size = mem_cur_size; +-#endif ++ void *ptr1 = attemptckrealloc(ptr, size); ++ if (!ptr1 && size)tcc_error(st, "memory full"); + return ptr1; + } + +-static char *tcc_strdup(const char *str) ++static char *tcc_strdup(TCCState *st, const char *str) + { + char *ptr; +- ptr = tcc_malloc(strlen(str) + 1); ++ ptr = tcc_malloc(st, strlen(str) + 1); + strcpy(ptr, str); + return ptr; + } + +-#define free(p) use_tcc_free(p) +-#define malloc(s) use_tcc_malloc(s) +-#define realloc(p, s) use_tcc_realloc(p, s) ++#define malloc(s) ckalloc(s) + +-static void dynarray_add(void ***ptab, int *nb_ptr, void *data) ++static void dynarray_add(TCCState *st, void ***ptab, int *nb_ptr, void *data) + { + int nb, nb_alloc; + void **pp; +@@ -1088,9 +223,9 @@ + nb_alloc = 1; + else + nb_alloc = nb * 2; +- pp = tcc_realloc(pp, nb_alloc * sizeof(void *)); ++ pp = tcc_realloc(st, pp, nb_alloc * sizeof(void *)); + if (!pp) +- error("memory full"); ++ tcc_error(st, "memory full"); + *ptab = pp; + } + pp[nb++] = data; +@@ -1098,12 +233,12 @@ + } + + /* symbol allocator */ +-static Sym *__sym_malloc(void) ++static Sym *__sym_malloc(TCCState *st) + { + Sym *sym_pool, *sym, *last_sym; + int i; + +- sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym)); ++ sym_pool = tcc_malloc(st, SYM_POOL_NB * sizeof(Sym)); + + last_sym = sym_free_first; + sym = sym_pool; +@@ -1116,27 +251,27 @@ + return last_sym; + } + +-static inline Sym *sym_malloc(void) ++static inline Sym *sym_malloc(TCCState * st) + { + Sym *sym; + sym = sym_free_first; + if (!sym) +- sym = __sym_malloc(); ++ sym = __sym_malloc(st); + sym_free_first = sym->next; + return sym; + } + +-static inline void sym_free(Sym *sym) ++static inline void sym_free(TCCState *st, Sym *sym) + { + sym->next = sym_free_first; + sym_free_first = sym; + } + +-Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) ++Section *new_section(TCCState *st, const char *name, int sh_type, int sh_flags) + { + Section *sec; + +- sec = tcc_mallocz(sizeof(Section) + strlen(name)); ++ sec = tcc_mallocz(st,sizeof(Section) + strlen(name)); + strcpy(sec->name, name); + sec->sh_type = sh_type; + sec->sh_flags = sh_flags; +@@ -1158,20 +293,20 @@ + + /* only add section if not private */ + if (!(sh_flags & SHF_PRIVATE)) { +- sec->sh_num = s1->nb_sections; +- dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec); ++ sec->sh_num = st->nb_sections; ++ dynarray_add(st, (void ***)&st->sections, &st->nb_sections, sec); + } + return sec; + } + +-static void free_section(Section *s) ++static void free_section(TCCState *st, Section *s) + { +- tcc_free(s->data); +- tcc_free(s); ++ ckfree((char *)(s->data)); ++ ckfree((char *)s); + } + + /* realloc section and set its content to zero */ +-static void section_realloc(Section *sec, unsigned long new_size) ++static void section_realloc(TCCState * st, Section *sec, unsigned long new_size) + { + unsigned long size; + unsigned char *data; +@@ -1181,9 +316,9 @@ + size = 1; + while (size < new_size) + size = size * 2; +- data = tcc_realloc(sec->data, size); ++ data = tcc_realloc(st, sec->data, size); + if (!data) +- error("memory full"); ++ tcc_error(st, "memory full"); + memset(data + sec->data_allocated, 0, size - sec->data_allocated); + sec->data = data; + sec->data_allocated = size; +@@ -1191,38 +326,38 @@ + + /* reserve at least 'size' bytes in section 'sec' from + sec->data_offset. */ +-static void *section_ptr_add(Section *sec, unsigned long size) ++static void *section_ptr_add(TCCState *st, Section *sec, unsigned long size) + { + unsigned long offset, offset1; + + offset = sec->data_offset; + offset1 = offset + size; + if (offset1 > sec->data_allocated) +- section_realloc(sec, offset1); ++ section_realloc(st, sec, offset1); + sec->data_offset = offset1; + return sec->data + offset; + } + + /* return a reference to a section, and create it if it does not + exists */ +-Section *find_section(TCCState *s1, const char *name) ++Section *find_section(TCCState *st, const char *name) + { + Section *sec; + int i; +- for(i = 1; i < s1->nb_sections; i++) { +- sec = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ sec = st->sections[i]; + if (!strcmp(name, sec->name)) + return sec; + } + /* sections are created as PROGBITS */ +- return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC); ++ return new_section(st, name, SHT_PROGBITS, SHF_ALLOC); + } + + #define SECTION_ABS ((void *)1) + + /* update sym->c so that it points to an external symbol in section + 'section' with value 'value' */ +-static void put_extern_sym2(Sym *sym, Section *section, ++static void put_extern_sym2(TCCState * st, Sym *sym, Section *section, + unsigned long value, unsigned long size, + int can_add_underscore) + { +@@ -1247,8 +382,8 @@ + else + sym_bind = STB_GLOBAL; + +- name = get_tok_str(sym->v, NULL); +-#ifdef CONFIG_TCC_BCHECK ++ name = get_tok_str(st, sym->v, NULL); ++#if 0 + if (do_bounds_check) { + char buf[32]; + +@@ -1269,6 +404,7 @@ + case TOK_memset: + case TOK_strlen: + case TOK_strcpy: ++ case TOK_alloca: + strcpy(buf, "__bound_"); + strcat(buf, name); + name = buf; +@@ -1276,13 +412,13 @@ + } + } + #endif +- if (tcc_state->leading_underscore && can_add_underscore) { ++ if (st->leading_underscore && can_add_underscore) { + buf1[0] = '_'; +- pstrcpy(buf1 + 1, sizeof(buf1) - 1, name); ++ pstrcpy(st, buf1 + 1, sizeof(buf1) - 1, name); + name = buf1; + } + info = ELF32_ST_INFO(sym_bind, sym_type); +- sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name); ++ sym->c = add_elf_sym(st, symtab_section, value, size, info, 0, sh_num, name); + } else { + esym = &((Elf32_Sym *)symtab_section->data)[sym->c]; + esym->st_value = value; +@@ -1291,39 +427,39 @@ + } + } + +-static void put_extern_sym(Sym *sym, Section *section, ++static void put_extern_sym(TCCState * st, Sym *sym, Section *section, + unsigned long value, unsigned long size) + { +- put_extern_sym2(sym, section, value, size, 1); ++ put_extern_sym2(st, sym, section, value, size, 1); + } + + /* add a new relocation entry to symbol 'sym' in section 's' */ +-static void greloc(Section *s, Sym *sym, unsigned long offset, int type) ++static void greloc(TCCState * st, Section *s, Sym *sym, unsigned long offset, int type) + { + if (!sym->c) +- put_extern_sym(sym, NULL, 0, 0); ++ put_extern_sym(st, sym, NULL, 0, 0); + /* now we can add ELF relocation info */ +- put_elf_reloc(symtab_section, s, offset, type, sym->c); ++ put_elf_reloc(st, symtab_section, s, offset, type, sym->c); + } + +-static inline int isid(int c) ++static inline int isid(TCCState *st, int c) + { + return (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_'; + } + +-static inline int isnum(int c) ++static inline int isnum(TCCState *st, int c) + { + return c >= '0' && c <= '9'; + } + +-static inline int isoct(int c) ++static inline int isoct(TCCState *st, int c) + { + return c >= '0' && c <= '7'; + } + +-static inline int toup(int c) ++static inline int toup(TCCState *st, int c) + { + if (c >= 'a' && c <= 'z') + return c - 'a' + 'A'; +@@ -1331,54 +467,54 @@ + return c; + } + +-static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) ++static void strcat_vprintf(TCCState *st, char *buf, int buf_size, const char *fmt, va_list ap) + { + int len; + len = strlen(buf); + vsnprintf(buf + len, buf_size - len, fmt, ap); + } + +-static void strcat_printf(char *buf, int buf_size, const char *fmt, ...) ++static void strcat_printf(TCCState *st, char *buf, int buf_size, const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); +- strcat_vprintf(buf, buf_size, fmt, ap); ++ strcat_vprintf(st, buf, buf_size, fmt, ap); + va_end(ap); + } + +-void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) ++void error1(TCCState *st, int is_warning, const char *fmt, va_list ap) + { + char buf[2048]; + BufferedFile **f; + + buf[0] = '\0'; + if (file) { +- for(f = s1->include_stack; f < s1->include_stack_ptr; f++) +- strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n", ++ for(f = st->include_stack; f < st->include_stack_ptr; f++) ++ strcat_printf(st, buf, sizeof(buf), "In file included from %s:%d:\n", + (*f)->filename, (*f)->line_num); + if (file->line_num > 0) { +- strcat_printf(buf, sizeof(buf), ++ strcat_printf(st, buf, sizeof(buf), + "%s:%d: ", file->filename, file->line_num); + } else { +- strcat_printf(buf, sizeof(buf), ++ strcat_printf(st, buf, sizeof(buf), + "%s: ", file->filename); + } + } else { +- strcat_printf(buf, sizeof(buf), ++ strcat_printf(st, buf, sizeof(buf), + "tcc: "); + } + if (is_warning) +- strcat_printf(buf, sizeof(buf), "warning: "); +- strcat_vprintf(buf, sizeof(buf), fmt, ap); ++ strcat_printf(st, buf, sizeof(buf), "warning: "); ++ strcat_vprintf(st, buf, sizeof(buf), fmt, ap); + +- if (!s1->error_func) { ++ if (!st->error_func) { + /* default case: stderr */ + fprintf(stderr, "%s\n", buf); + } else { +- s1->error_func(s1->error_opaque, buf); ++ st->error_func(st->error_opaque, buf); + } +- if (!is_warning || s1->warn_error) +- s1->nb_errors++; ++ if (!is_warning || st->warn_error) ++ st->nb_errors++; + } + + #ifdef LIBTCC +@@ -1391,83 +527,80 @@ + #endif + + /* error without aborting current compilation */ +-void error_noabort(const char *fmt, ...) ++void error_noabort(TCCState * st, const char *fmt, ...) + { +- TCCState *s1 = tcc_state; + va_list ap; + + va_start(ap, fmt); +- error1(s1, 0, fmt, ap); ++ error1(st, 0, fmt, ap); + va_end(ap); + } + +-void error(const char *fmt, ...) ++void tcc_error(TCCState * st, const char *fmt, ...) + { +- TCCState *s1 = tcc_state; + va_list ap; + + va_start(ap, fmt); +- error1(s1, 0, fmt, ap); ++ error1(st, 0, fmt, ap); + va_end(ap); + /* better than nothing: in some cases, we accept to handle errors */ +- if (s1->error_set_jmp_enabled) { +- longjmp(s1->error_jmp_buf, 1); ++ if (st->error_set_jmp_enabled) { ++ longjmp(st->error_jmp_buf, 1); + } else { + /* XXX: eliminate this someday */ + exit(1); + } + } + +-void expect(const char *msg) ++void expect(TCCState * st, const char *msg) + { +- error("%s expected", msg); ++ tcc_error(st, "%s expected", msg); + } + +-void warning(const char *fmt, ...) ++void warning(TCCState * st, const char *fmt, ...) + { +- TCCState *s1 = tcc_state; + va_list ap; + +- if (s1->warn_none) ++ if (st->warn_none) + return; + + va_start(ap, fmt); +- error1(s1, 1, fmt, ap); ++ error1(st, 1, fmt, ap); + va_end(ap); + } + +-void skip(int c) ++void skip(TCCState *st, int c) + { + if (tok != c) +- error("'%c' expected", c); +- next(); ++ tcc_error(st,"'%c' expected", c); ++ next(st); + } + +-static void test_lvalue(void) ++static void test_lvalue(TCCState *st) + { + if (!(vtop->r & VT_LVAL)) +- expect("lvalue"); ++ expect(st, "lvalue"); + } + + /* allocate a new token */ +-static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) ++static TokenSym *tok_alloc_new(TCCState *st, TokenSym **pts, const char *str, int len) + { + TokenSym *ts, **ptable; + int i; + + if (tok_ident >= SYM_FIRST_ANOM) +- error("memory full"); ++ tcc_error(st, "memory full"); + + /* expand token table if needed */ + i = tok_ident - TOK_IDENT; + if ((i % TOK_ALLOC_INCR) == 0) { +- ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *)); ++ ptable = tcc_realloc(st, table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *)); + if (!ptable) +- error("memory full"); ++ tcc_error(st, "memory full"); + table_ident = ptable; + } + +- ts = tcc_malloc(sizeof(TokenSym) + len); ++ ts = tcc_malloc(st, sizeof(TokenSym) + len); + table_ident[i] = ts; + ts->tok = tok_ident++; + ts->sym_define = NULL; +@@ -1486,7 +619,7 @@ + #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c)) + + /* find a token and add it if not found */ +-static TokenSym *tok_alloc(const char *str, int len) ++static TokenSym *tok_alloc(TCCState *st, const char *str, int len) + { + TokenSym *ts, **pts; + int i; +@@ -1506,12 +639,12 @@ + return ts; + pts = &(ts->hash_next); + } +- return tok_alloc_new(pts, str, len); ++ return tok_alloc_new(st, pts, str, len); + } + + /* CString handling */ + +-static void cstr_realloc(CString *cstr, int new_size) ++static void cstr_realloc(TCCState *st, CString *cstr, int new_size) + { + int size; + void *data; +@@ -1521,86 +654,86 @@ + size = 8; /* no need to allocate a too small first string */ + while (size < new_size) + size = size * 2; +- data = tcc_realloc(cstr->data_allocated, size); ++ data = tcc_realloc(st, cstr->data_allocated, size); + if (!data) +- error("memory full"); ++ tcc_error(st, "memory full"); + cstr->data_allocated = data; + cstr->size_allocated = size; + cstr->data = data; + } + + /* add a byte */ +-static inline void cstr_ccat(CString *cstr, int ch) ++static inline void cstr_ccat(TCCState *st,CString *cstr, int ch) + { + int size; + size = cstr->size + 1; + if (size > cstr->size_allocated) +- cstr_realloc(cstr, size); ++ cstr_realloc(st, cstr, size); + ((unsigned char *)cstr->data)[size - 1] = ch; + cstr->size = size; + } + +-static void cstr_cat(CString *cstr, const char *str) ++static void cstr_cat(TCCState *st, CString *cstr, const char *str) + { + int c; + for(;;) { + c = *str; + if (c == '\0') + break; +- cstr_ccat(cstr, c); ++ cstr_ccat(st, cstr, c); + str++; + } + } + + /* add a wide char */ +-static void cstr_wccat(CString *cstr, int ch) ++static void cstr_wccat(TCCState *st, CString *cstr, int ch) + { + int size; +- size = cstr->size + sizeof(int); ++ size = cstr->size + sizeof(nwchar_t); + if (size > cstr->size_allocated) +- cstr_realloc(cstr, size); +- *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch; ++ cstr_realloc(st, cstr, size); ++ *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch; + cstr->size = size; + } + +-static void cstr_new(CString *cstr) ++static void cstr_new(TCCState *st, CString *cstr) + { + memset(cstr, 0, sizeof(CString)); + } + + /* free string and reset it to NULL */ +-static void cstr_free(CString *cstr) ++static void cstr_free(TCCState *st, CString *cstr) + { +- tcc_free(cstr->data_allocated); +- cstr_new(cstr); ++ ckfree((char *)(cstr->data_allocated)); ++ cstr_new(st, cstr); + } + +-#define cstr_reset(cstr) cstr_free(cstr) ++#define cstr_reset(ts, cstr) cstr_free(ts, cstr) + + /* XXX: unicode ? */ +-static void add_char(CString *cstr, int c) ++static void add_char(TCCState *st, CString *cstr, int c) + { + if (c == '\'' || c == '\"' || c == '\\') { + /* XXX: could be more precise if char or string */ +- cstr_ccat(cstr, '\\'); ++ cstr_ccat(st, cstr, '\\'); + } + if (c >= 32 && c <= 126) { +- cstr_ccat(cstr, c); ++ cstr_ccat(st, cstr, c); + } else { +- cstr_ccat(cstr, '\\'); ++ cstr_ccat(st, cstr, '\\'); + if (c == '\n') { +- cstr_ccat(cstr, 'n'); ++ cstr_ccat(st, cstr, 'n'); + } else { +- cstr_ccat(cstr, '0' + ((c >> 6) & 7)); +- cstr_ccat(cstr, '0' + ((c >> 3) & 7)); +- cstr_ccat(cstr, '0' + (c & 7)); ++ cstr_ccat(st, cstr, '0' + ((c >> 6) & 7)); ++ cstr_ccat(st, cstr, '0' + ((c >> 3) & 7)); ++ cstr_ccat(st, cstr, '0' + (c & 7)); + } + } + } + + /* XXX: buffer overflow */ + /* XXX: float tokens */ +-char *get_tok_str(int v, CValue *cv) ++char *get_tok_str(TCCState *st, int v, CValue *cv) + { + static char buf[STRING_MAX_SIZE + 1]; + static CString cstr_buf; +@@ -1610,7 +743,7 @@ + int i, len; + + /* NOTE: to go faster, we give a fixed buffer for small strings */ +- cstr_reset(&cstr_buf); ++ cstr_reset(st, &cstr_buf); + cstr_buf.data = buf; + cstr_buf.size_allocated = sizeof(buf); + p = buf; +@@ -1628,33 +761,33 @@ + break; + case TOK_CCHAR: + case TOK_LCHAR: +- cstr_ccat(&cstr_buf, '\''); +- add_char(&cstr_buf, cv->i); +- cstr_ccat(&cstr_buf, '\''); +- cstr_ccat(&cstr_buf, '\0'); ++ cstr_ccat(st, &cstr_buf, '\''); ++ add_char(st, &cstr_buf, cv->i); ++ cstr_ccat(st, &cstr_buf, '\''); ++ cstr_ccat(st, &cstr_buf, '\0'); + break; + case TOK_PPNUM: + cstr = cv->cstr; + len = cstr->size - 1; + for(i=0;idata)[i]); +- cstr_ccat(&cstr_buf, '\0'); ++ add_char(st, &cstr_buf, ((unsigned char *)cstr->data)[i]); ++ cstr_ccat(st, &cstr_buf, '\0'); + break; + case TOK_STR: + case TOK_LSTR: + cstr = cv->cstr; +- cstr_ccat(&cstr_buf, '\"'); ++ cstr_ccat(st, &cstr_buf, '\"'); + if (v == TOK_STR) { + len = cstr->size - 1; + for(i=0;idata)[i]); ++ add_char(st, &cstr_buf, ((unsigned char *)cstr->data)[i]); + } else { +- len = (cstr->size / sizeof(int)) - 1; ++ len = (cstr->size / sizeof(nwchar_t)) - 1; + for(i=0;idata)[i]); ++ add_char(st, &cstr_buf, ((nwchar_t *)cstr->data)[i]); + } +- cstr_ccat(&cstr_buf, '\"'); +- cstr_ccat(&cstr_buf, '\0'); ++ cstr_ccat(st, &cstr_buf, '\"'); ++ cstr_ccat(st, &cstr_buf, '\0'); + break; + case TOK_LT: + v = '<'; +@@ -1662,6 +795,8 @@ + case TOK_GT: + v = '>'; + goto addv; ++ case TOK_DOTS: ++ return strcpy(p, "..."); + case TOK_A_SHL: + return strcpy(p, "<<="); + case TOK_A_SAR: +@@ -1697,10 +832,10 @@ + } + + /* push, without hashing */ +-static Sym *sym_push2(Sym **ps, int v, int t, int c) ++static Sym *sym_push2(TCCState *st, Sym **ps, int v, int t, int c) + { + Sym *s; +- s = sym_malloc(); ++ s = sym_malloc(st); + s->v = v; + s->type.t = t; + s->c = c; +@@ -1713,7 +848,7 @@ + + /* find a symbol and return its associated structure. 's' is the top + of the symbol stack */ +-static Sym *sym_find2(Sym *s, int v) ++static Sym *sym_find2(TCCState *st, Sym *s, int v) + { + while (s) { + if (s->v == v) +@@ -1724,7 +859,7 @@ + } + + /* structure lookup */ +-static inline Sym *struct_find(int v) ++static inline Sym *struct_find(TCCState *st, int v) + { + v -= TOK_IDENT; + if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) +@@ -1733,7 +868,7 @@ + } + + /* find an identifier */ +-static inline Sym *sym_find(int v) ++static inline Sym *sym_find(TCCState *st, int v) + { + v -= TOK_IDENT; + if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) +@@ -1742,7 +877,7 @@ + } + + /* push a given symbol on the symbol stack */ +-static Sym *sym_push(int v, CType *type, int r, int c) ++static Sym *sym_push(TCCState *st, int v, CType *type, int r, int c) + { + Sym *s, **ps; + TokenSym *ts; +@@ -1751,7 +886,7 @@ + ps = &local_stack; + else + ps = &global_stack; +- s = sym_push2(ps, v, type->t, c); ++ s = sym_push2(st, ps, v, type->t, c); + s->type.ref = type->ref; + s->r = r; + /* don't record fields or anonymous symbols */ +@@ -1770,10 +905,10 @@ + } + + /* push a global identifier */ +-static Sym *global_identifier_push(int v, int t, int c) ++static Sym *global_identifier_push(TCCState *st, int v, int t, int c) + { + Sym *s, **ps; +- s = sym_push2(&global_stack, v, t, c); ++ s = sym_push2(st, &global_stack, v, t, c); + /* don't record anonymous symbol */ + if (v < SYM_FIRST_ANOM) { + ps = &table_ident[v - TOK_IDENT]->sym_identifier; +@@ -1788,7 +923,7 @@ + } + + /* pop symbols until top reaches 'b' */ +-static void sym_pop(Sym **ptop, Sym *b) ++static void sym_pop(TCCState *st, Sym **ptop, Sym *b) + { + Sym *s, *ss, **ps; + TokenSym *ts; +@@ -1808,7 +943,7 @@ + ps = &ts->sym_identifier; + *ps = s->prev_tok; + } +- sym_free(s); ++ sym_free(st, s); + s = ss; + } + *ptop = b; +@@ -1816,51 +951,62 @@ + + /* I/O layer */ + +-BufferedFile *tcc_open(TCCState *s1, const char *filename) ++BufferedFile *tcc_open(TCCState *st, const char *filename) + { +- int fd; ++ Tcl_Channel fd; + BufferedFile *bf; +- +- fd = open(filename, O_RDONLY | O_BINARY); +- if (fd < 0) ++ int i, len; ++ /*printf("opening '%s'\n", filename); */ ++ Tcl_Obj * path ; ++ path = Tcl_NewStringObj(filename,-1); ++ Tcl_IncrRefCount(path); ++ fd = Tcl_FSOpenFileChannel(NULL,path, "r", 0); ++ Tcl_DecrRefCount(path); ++ if (fd==NULL) { ++ /*printf("T_FOFC, returned NULL\n"); */ + return NULL; +- bf = tcc_malloc(sizeof(BufferedFile)); ++ } ++ /*printf("T_FOFC, returned SUCCESS\n"); */ ++ bf = tcc_malloc(st, sizeof(BufferedFile)); + if (!bf) { +- close(fd); ++ Tcl_Close(NULL,fd); + return NULL; + } + bf->fd = fd; + bf->buf_ptr = bf->buffer; + bf->buf_end = bf->buffer; + bf->buffer[0] = CH_EOB; /* put eob symbol */ +- pstrcpy(bf->filename, sizeof(bf->filename), filename); ++ pstrcpy(st, bf->filename, sizeof(bf->filename), filename); ++ len = strlen(bf->filename); ++ for (i = 0; i < len; i++) ++ if (bf->filename[i] == '\\') ++ bf->filename[i] = '/'; + bf->line_num = 1; + bf->ifndef_macro = 0; +- bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; +- // printf("opening '%s'\n", filename); ++ bf->ifdef_stack_ptr = st->ifdef_stack_ptr; + return bf; + } + + void tcc_close(BufferedFile *bf) + { + total_lines += bf->line_num; +- close(bf->fd); +- tcc_free(bf); ++ Tcl_Close(NULL,bf->fd); ++ ckfree((char *)bf); + } + + /* fill input buffer and peek next char */ +-static int tcc_peekc_slow(BufferedFile *bf) ++static int tcc_peekc_slow(TCCState *st, BufferedFile *bf) + { + int len; + /* only tries to read if really end of buffer */ + if (bf->buf_ptr >= bf->buf_end) { +- if (bf->fd != -1) { ++ if (bf->fd != NULL) { + #if defined(PARSE_DEBUG) + len = 8; + #else + len = IO_BUF_SIZE; + #endif +- len = read(bf->fd, bf->buffer, len); ++ len = Tcl_Read(bf->fd, bf->buffer, len); + if (len < 0) + len = 0; + } else { +@@ -1881,58 +1027,63 @@ + + /* return the current character, handling end of block if necessary + (but not stray) */ +-static int handle_eob(void) ++static int handle_eob(TCCState *st) + { +- return tcc_peekc_slow(file); ++ return tcc_peekc_slow(st, file); + } + + /* read next char from current input file and handle end of input buffer */ +-static inline void inp(void) ++static inline void inp(TCCState *st) + { +- ch = *(++(file->buf_ptr)); ++ fch = *(++(file->buf_ptr)); + /* end of buffer/file handling */ +- if (ch == CH_EOB) +- ch = handle_eob(); ++ if (fch == CH_EOB) ++ fch = handle_eob(st); ++} ++ ++/* space excluding newline */ ++static inline int is_space(TCCState *st, int ch) ++{ ++ return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r'; + } + + /* handle '\[\r]\n' */ +-static void handle_stray(void) ++static int handle_stray_noerror(TCCState *st) + { +- while (ch == '\\') { +- inp(); +- if (ch == '\n') { +- file->line_num++; +- inp(); +- } else if (ch == '\r') { +- inp(); +- if (ch != '\n') +- goto fail; ++ while (fch == '\\') { ++ inp(st); ++ while (is_space(st, fch)) inp(st); ++ if (fch == '\n') { + file->line_num++; +- inp(); +- } else { +- fail: +- error("stray '\\' in program"); ++ inp(st); ++ } else return 1; + } ++ return 0; + } ++ ++static void handle_stray(TCCState *st) ++{ ++ if(handle_stray_noerror(st)) ++ tcc_error(st, "stray '\\' in program"); + } + + /* skip the stray and handle the \\n case. Output an error if + incorrect char after the stray */ +-static int handle_stray1(uint8_t *p) ++static int handle_stray1(TCCState *st, uint8_t *p) + { + int c; + + if (p >= file->buf_end) { + file->buf_ptr = p; +- c = handle_eob(); ++ c = handle_eob(st); + p = file->buf_ptr; + if (c == '\\') + goto parse_stray; + } else { + parse_stray: + file->buf_ptr = p; +- ch = *p; +- handle_stray(); ++ fch = *p; ++ handle_stray(st); + p = file->buf_ptr; + c = *p; + } +@@ -1940,24 +1091,24 @@ + } + + /* handle just the EOB case, but not stray */ +-#define PEEKC_EOB(c, p)\ ++#define PEEKC_EOB(st, c, p)\ + {\ + p++;\ + c = *p;\ + if (c == '\\') {\ + file->buf_ptr = p;\ +- c = handle_eob();\ ++ c = handle_eob(st);\ + p = file->buf_ptr;\ + }\ + } + + /* handle the complicated stray case */ +-#define PEEKC(c, p)\ ++#define PEEKC(st, c, p)\ + {\ + p++;\ + c = *p;\ + if (c == '\\') {\ +- c = handle_stray1(p);\ ++ c = handle_stray1(st, p);\ + p = file->buf_ptr;\ + }\ + } +@@ -1965,16 +1116,16 @@ + /* input with '\[\r]\n' handling. Note that this function cannot + handle other characters after '\', so you cannot call it inside + strings or comments */ +-static void minp(void) ++static void minp(TCCState *st) + { +- inp(); +- if (ch == '\\') +- handle_stray(); ++ inp(st); ++ if (fch == '\\') ++ handle_stray(st); + } + + + /* single line C++ comments */ +-static uint8_t *parse_line_comment(uint8_t *p) ++static uint8_t *parse_line_comment(TCCState *st, uint8_t *p) + { + int c; + +@@ -1986,18 +1137,18 @@ + break; + } else if (c == '\\') { + file->buf_ptr = p; +- c = handle_eob(); ++ c = handle_eob(st); + p = file->buf_ptr; + if (c == '\\') { +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + if (c == '\n') { + file->line_num++; +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + } else if (c == '\r') { +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + if (c == '\n') { + file->line_num++; +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + } + } + } else { +@@ -2011,7 +1162,7 @@ + } + + /* C comments */ +-static uint8_t *parse_comment(uint8_t *p) ++static uint8_t *parse_comment(TCCState *st, uint8_t *p) + { + int c; + +@@ -2042,20 +1193,20 @@ + goto end_of_comment; + } else if (c == '\\') { + file->buf_ptr = p; +- c = handle_eob(); ++ c = handle_eob(st); + p = file->buf_ptr; + if (c == '\\') { + /* skip '\[\r]\n', otherwise just skip the stray */ + while (c == '\\') { +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + if (c == '\n') { + file->line_num++; +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + } else if (c == '\r') { +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + if (c == '\n') { + file->line_num++; +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + } + } else { + goto after_star; +@@ -2070,10 +1221,10 @@ + } else { + /* stray, eob or eof */ + file->buf_ptr = p; +- c = handle_eob(); ++ c = handle_eob(st); + p = file->buf_ptr; + if (c == CH_EOF) { +- error("unexpected end of file in comment"); ++ tcc_error(st, "unexpected end of file in comment"); + } else if (c == '\\') { + p++; + } +@@ -2086,20 +1237,14 @@ + + #define cinp minp + +-/* space exlcuding newline */ +-static inline int is_space(int ch) +-{ +- return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r'; +-} +- +-static inline void skip_spaces(void) ++static inline void skip_spaces(TCCState *st) + { +- while (is_space(ch)) +- cinp(); ++ while (is_space(st, fch)) ++ cinp(st); + } + + /* parse a string without interpreting escapes */ +-static uint8_t *parse_pp_string(uint8_t *p, ++static uint8_t *parse_pp_string(TCCState *st, uint8_t *p, + int sep, CString *str) + { + int c; +@@ -2110,30 +1255,30 @@ + break; + } else if (c == '\\') { + file->buf_ptr = p; +- c = handle_eob(); ++ c = handle_eob(st); + p = file->buf_ptr; + if (c == CH_EOF) { + unterminated_string: + /* XXX: indicate line number of start of string */ +- error("missing terminating %c character", sep); ++ tcc_error(st, "missing terminating %c character", sep); + } else if (c == '\\') { + /* escape : just skip \[\r]\n */ +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + if (c == '\n') { + file->line_num++; + p++; + } else if (c == '\r') { +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + if (c != '\n') +- expect("'\n' after '\r'"); ++ expect(st, "'\n' after '\r'"); + file->line_num++; + p++; + } else if (c == CH_EOF) { + goto unterminated_string; + } else { + if (str) { +- cstr_ccat(str, '\\'); +- cstr_ccat(str, c); ++ cstr_ccat(st, str, '\\'); ++ cstr_ccat(st, str, c); + } + p++; + } +@@ -2142,10 +1287,10 @@ + file->line_num++; + goto add_char; + } else if (c == '\r') { +- PEEKC_EOB(c, p); ++ PEEKC_EOB(st, c, p); + if (c != '\n') { + if (str) +- cstr_ccat(str, '\r'); ++ cstr_ccat(st, str, '\r'); + } else { + file->line_num++; + goto add_char; +@@ -2153,7 +1298,7 @@ + } else { + add_char: + if (str) +- cstr_ccat(str, c); ++ cstr_ccat(st, str, c); + p++; + } + } +@@ -2163,7 +1308,7 @@ + + /* skip block of text until #else, #elif or #endif. skip also pairs of + #if/#endif */ +-void preprocess_skip(void) ++void preprocess_skip(TCCState *st) + { + int a, start_of_line, c; + uint8_t *p; +@@ -2189,31 +1334,30 @@ + goto redo_no_start; + case '\\': + file->buf_ptr = p; +- c = handle_eob(); ++ c = handle_eob(st); + if (c == CH_EOF) { +- expect("#endif"); ++ expect(st, "#endif"); + } else if (c == '\\') { +- /* XXX: incorrect: should not give an error */ +- ch = file->buf_ptr[0]; +- handle_stray(); ++ fch = file->buf_ptr[0]; ++ handle_stray_noerror(st); + } + p = file->buf_ptr; + goto redo_no_start; + /* skip strings */ + case '\"': + case '\'': +- p = parse_pp_string(p, c, NULL); ++ p = parse_pp_string(st, p, c, NULL); + break; + /* skip comments */ + case '/': + file->buf_ptr = p; +- ch = *p; +- minp(); ++ fch = *p; ++ minp(st); + p = file->buf_ptr; +- if (ch == '*') { +- p = parse_comment(p); +- } else if (ch == '/') { +- p = parse_line_comment(p); ++ if (fch == '*') { ++ p = parse_comment(st, p); ++ } else if (fch == '/') { ++ p = parse_line_comment(st, p); + } + break; + +@@ -2221,7 +1365,7 @@ + p++; + if (start_of_line) { + file->buf_ptr = p; +- next_nomacro(); ++ next_nomacro(st); + p = file->buf_ptr; + if (a == 0 && + (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF)) +@@ -2249,7 +1393,7 @@ + files */ + + /* save current parse state in 's' */ +-void save_parse_state(ParseState *s) ++void save_parse_state(TCCState *st, ParseState *s) + { + s->line_num = file->line_num; + s->macro_ptr = macro_ptr; +@@ -2258,7 +1402,7 @@ + } + + /* restore parse state from 's' */ +-void restore_parse_state(ParseState *s) ++void restore_parse_state(TCCState *st, ParseState *s) + { + file->line_num = s->line_num; + macro_ptr = s->macro_ptr; +@@ -2268,7 +1412,7 @@ + + /* return the number of additional 'ints' necessary to store the + token */ +-static inline int tok_ext_size(int t) ++static inline int tok_ext_size(TCCState *st, int t) + { + switch(t) { + /* 4 bytes */ +@@ -2282,7 +1426,7 @@ + case TOK_STR: + case TOK_LSTR: + case TOK_PPNUM: +- error("unsupported token"); ++ tcc_error(st,"unsupported token"); + return 1; + case TOK_CDOUBLE: + case TOK_CLLONG: +@@ -2297,7 +1441,7 @@ + + /* token string handling */ + +-static inline void tok_str_new(TokenString *s) ++static inline void tok_str_new(TCCState *st, TokenString *s) + { + s->str = NULL; + s->len = 0; +@@ -2305,12 +1449,12 @@ + s->last_line_num = -1; + } + +-static void tok_str_free(int *str) ++static void tok_str_free(TCCState *st, int *str) + { +- tcc_free(str); ++ ckfree((char *)str); + } + +-static int *tok_str_realloc(TokenString *s) ++static int *tok_str_realloc(TCCState *st, TokenString *s) + { + int *str, len; + +@@ -2319,27 +1463,28 @@ + } else { + len = s->allocated_len * 2; + } +- str = tcc_realloc(s->str, len * sizeof(int)); ++ str = tcc_realloc(st, s->str, len * sizeof(int)); + if (!str) +- error("memory full"); ++ tcc_error(st, "memory full"); + s->allocated_len = len; + s->str = str; + return str; + } + +-static void tok_str_add(TokenString *s, int t) ++static void tok_str_add(TCCState *st, TokenString *s, int t, int tf) + { + int len, *str; + + len = s->len; + str = s->str; +- if (len >= s->allocated_len) +- str = tok_str_realloc(s); ++ if (len+1 >= s->allocated_len) ++ str = tok_str_realloc(st, s); + str[len++] = t; ++ str[len++] = tf; + s->len = len; + } + +-static void tok_str_add2(TokenString *s, int t, CValue *cv) ++static void tok_str_add2(TCCState *st, TokenString *s, int t, int tf, CValue *cv) + { + int len, *str; + +@@ -2348,8 +1493,9 @@ + + /* allocate space for worst case */ + if (len + TOK_MAX_SIZE > s->allocated_len) +- str = tok_str_realloc(s); ++ str = tok_str_realloc(st, s); + str[len++] = t; ++ str[len++] = tf; + switch(t) { + case TOK_CINT: + case TOK_CUINT: +@@ -2368,7 +1514,7 @@ + + nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2; + while ((len + nb_words) > s->allocated_len) +- str = tok_str_realloc(s); ++ str = tok_str_realloc(st, s); + cstr = (CString *)(str + len); + cstr->data = NULL; + cstr->size = cv->cstr->size; +@@ -2404,7 +1550,7 @@ + } + + /* add the current parse token in token string 's' */ +-static void tok_str_add_tok(TokenString *s) ++static void tok_str_add_tok(TCCState *st, TokenString *s) + { + CValue cval; + +@@ -2412,18 +1558,18 @@ + if (file->line_num != s->last_line_num) { + s->last_line_num = file->line_num; + cval.i = s->last_line_num; +- tok_str_add2(s, TOK_LINENUM, &cval); ++ tok_str_add2(st, s, TOK_LINENUM, 0, &cval); + } +- tok_str_add2(s, tok, &tokc); ++ tok_str_add2(st, s, tok, tok_flags, &tokc); + } + + #if LDOUBLE_SIZE == 12 +-#define LDOUBLE_GET(p, cv) \ ++#define LDOUBLE_GET(st, p, cv) \ + cv.tab[0] = p[0]; \ + cv.tab[1] = p[1]; \ + cv.tab[2] = p[2]; + #elif LDOUBLE_SIZE == 8 +-#define LDOUBLE_GET(p, cv) \ ++#define LDOUBLE_GET(st, p, cv) \ + cv.tab[0] = p[0]; \ + cv.tab[1] = p[1]; + #else +@@ -2433,9 +1579,10 @@ + + /* get a token from an integer array and increment pointer + accordingly. we code it as a macro to avoid pointer aliasing. */ +-#define TOK_GET(t, p, cv) \ ++#define TOK_GET(t, tf, p, cv) \ + { \ + t = *p++; \ ++ tf = *p++; \ + switch(t) { \ + case TOK_CINT: \ + case TOK_CUINT: \ +@@ -2460,7 +1607,7 @@ + p += 2; \ + break; \ + case TOK_CLDOUBLE: \ +- LDOUBLE_GET(p, cv); \ ++ LDOUBLE_GET(st, p, cv); \ + p += LDOUBLE_SIZE / 4; \ + break; \ + default: \ +@@ -2469,11 +1616,11 @@ + } + + /* defines handling */ +-static inline void define_push(int v, int macro_type, int *str, Sym *first_arg) ++static inline void define_push(TCCState *st, int v, int macro_type, int *str, Sym *first_arg) + { + Sym *s; + +- s = sym_push2(&define_stack, v, macro_type, (int)str); ++ s = sym_push2(st, &define_stack, v, macro_type, (int)str); + s->next = first_arg; + table_ident[v - TOK_IDENT]->sym_define = s; + } +@@ -2488,7 +1635,7 @@ + s->v = 0; + } + +-static inline Sym *define_find(int v) ++static inline Sym *define_find(TCCState *st, int v) + { + v -= TOK_IDENT; + if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) +@@ -2497,7 +1644,7 @@ + } + + /* free define stack until top reaches 'b' */ +-static void free_defines(Sym *b) ++static void free_defines(TCCState *st, Sym *b) + { + Sym *top, *top1; + int v; +@@ -2507,18 +1654,18 @@ + top1 = top->prev; + /* do not free args or predefined defines */ + if (top->c) +- tok_str_free((int *)top->c); ++ tok_str_free(st, (int *)top->c); + v = top->v; + if (v >= TOK_IDENT && v < tok_ident) + table_ident[v - TOK_IDENT]->sym_define = NULL; +- sym_free(top); ++ sym_free(st, top); + top = top1; + } + define_stack = b; + } + + /* label lookup */ +-static Sym *label_find(int v) ++static Sym *label_find(TCCState *st, int v) + { + v -= TOK_IDENT; + if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) +@@ -2526,10 +1673,10 @@ + return table_ident[v]->sym_label; + } + +-static Sym *label_push(Sym **ptop, int v, int flags) ++static Sym *label_push(TCCState *st, Sym **ptop, int v, int flags) + { + Sym *s, **ps; +- s = sym_push2(ptop, v, 0, 0); ++ s = sym_push2(st, ptop, v, 0, 0); + s->r = flags; + ps = &table_ident[v - TOK_IDENT]->sym_label; + if (ptop == &global_label_stack) { +@@ -2545,47 +1692,47 @@ + + /* pop labels until element last is reached. Look if any labels are + undefined. Define symbols if '&&label' was used. */ +-static void label_pop(Sym **ptop, Sym *slast) ++static void label_pop(TCCState * state, Sym **ptop, Sym *slast) + { +- Sym *s, *s1; +- for(s = *ptop; s != slast; s = s1) { +- s1 = s->prev; ++ Sym *s, *st; ++ for(s = *ptop; s != slast; s = st) { ++ st = s->prev; + if (s->r == LABEL_DECLARED) { +- warning("label '%s' declared but not used", get_tok_str(s->v, NULL)); ++ warning(state, "label '%s' declared but not used", get_tok_str(state, s->v, NULL)); + } else if (s->r == LABEL_FORWARD) { +- error("label '%s' used but not defined", +- get_tok_str(s->v, NULL)); ++ tcc_error(state, "label '%s' used but not defined", ++ get_tok_str(state, s->v, NULL)); + } else { + if (s->c) { + /* define corresponding symbol. A size of + 1 is put. */ +- put_extern_sym(s, cur_text_section, (long)s->next, 1); ++ put_extern_sym(state, s, cur_text_section, (long)s->next, 1); + } + } + /* remove label */ + table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok; +- sym_free(s); ++ sym_free(state, s); + } + *ptop = slast; + } + + /* eval an expression for #if/#elif */ +-static int expr_preprocess(void) ++static int expr_preprocess(TCCState *st) + { + int c, t; + TokenString str; + +- tok_str_new(&str); ++ tok_str_new(st, &str); + while (tok != TOK_LINEFEED && tok != TOK_EOF) { +- next(); /* do macro subst */ ++ next(st); /* do macro subst */ + if (tok == TOK_DEFINED) { +- next_nomacro(); ++ next_nomacro(st); + t = tok; + if (t == '(') +- next_nomacro(); +- c = define_find(tok) != 0; ++ next_nomacro(st); ++ c = define_find(st, tok) != 0; + if (t == '(') +- next_nomacro(); ++ next_nomacro(st); + tok = TOK_CINT; + tokc.i = c; + } else if (tok >= TOK_IDENT) { +@@ -2593,37 +1740,37 @@ + tok = TOK_CINT; + tokc.i = 0; + } +- tok_str_add_tok(&str); ++ tok_str_add_tok(st, &str); + } +- tok_str_add(&str, -1); /* simulate end of file */ +- tok_str_add(&str, 0); ++ tok_str_add(st, &str, -1, 0); /* simulate end of file */ ++ tok_str_add(st, &str, 0, 0); + /* now evaluate C constant expression */ + macro_ptr = str.str; +- next(); +- c = expr_const(); ++ next(st); ++ c = expr_const(st); + macro_ptr = NULL; +- tok_str_free(str.str); ++ tok_str_free(st, str.str); + return c != 0; + } + + #if defined(PARSE_DEBUG) || defined(PP_DEBUG) +-static void tok_print(int *str) ++static void tok_print(TCCState *st, int *str) + { +- int t; ++ int t, tf; + CValue cval; + + while (1) { +- TOK_GET(t, str, cval); ++ TOK_GET(st, t, tf, str, cval); + if (!t) + break; +- printf(" %s", get_tok_str(t, &cval)); ++ printf(st, " %s", get_tok_str(st, t, &cval)); + } + printf("\n"); + } + #endif + + /* parse after #define */ +-static void parse_define(void) ++static void parse_define(TCCState *st) + { + Sym *s, *first, **ps; + int v, t, varg, is_vaargs, c; +@@ -2631,56 +1778,56 @@ + + v = tok; + if (v < TOK_IDENT) +- error("invalid macro name '%s'", get_tok_str(tok, &tokc)); ++ tcc_error(st, "invalid macro name '%s'", get_tok_str(st, tok, &tokc)); + /* XXX: should check if same macro (ANSI) */ + first = NULL; + t = MACRO_OBJ; + /* '(' must be just after macro definition for MACRO_FUNC */ + c = file->buf_ptr[0]; + if (c == '\\') +- c = handle_stray1(file->buf_ptr); ++ c = handle_stray1(st, file->buf_ptr); + if (c == '(') { +- next_nomacro(); +- next_nomacro(); ++ next_nomacro(st); ++ next_nomacro(st); + ps = &first; + while (tok != ')') { + varg = tok; +- next_nomacro(); ++ next_nomacro(st); + is_vaargs = 0; + if (varg == TOK_DOTS) { + varg = TOK___VA_ARGS__; + is_vaargs = 1; + } else if (tok == TOK_DOTS && gnu_ext) { + is_vaargs = 1; +- next_nomacro(); ++ next_nomacro(st); + } + if (varg < TOK_IDENT) +- error("badly punctuated parameter list"); +- s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0); ++ tcc_error(st,"badly punctuated parameter list"); ++ s = sym_push2(st,&define_stack, varg | SYM_FIELD, is_vaargs, 0); + *ps = s; + ps = &s->next; + if (tok != ',') + break; +- next_nomacro(); ++ next_nomacro(st); + } + t = MACRO_FUNC; + } +- tok_str_new(&str); +- next_nomacro(); ++ tok_str_new(st, &str); ++ next_nomacro(st); + /* EOF testing necessary for '-D' handling */ + while (tok != TOK_LINEFEED && tok != TOK_EOF) { +- tok_str_add2(&str, tok, &tokc); +- next_nomacro(); ++ tok_str_add2(st,&str, tok, tok_flags, &tokc); ++ next_nomacro(st); + } +- tok_str_add(&str, 0); ++ tok_str_add(st,&str, 0, 0); + #ifdef PP_DEBUG +- printf("define %s %d: ", get_tok_str(v, NULL), t); +- tok_print(str.str); ++ printf("define %s %d: ", get_tok_str(st,v, NULL), t); ++ tok_print(st, str.str); + #endif +- define_push(v, t, str.str, first); ++ define_push(st, v, t, str.str, first); + } + +-static inline int hash_cached_include(int type, const char *filename) ++static inline int hash_cached_include(TCCState *st, int type, const char *filename) + { + const unsigned char *s; + unsigned int h; +@@ -2697,17 +1844,17 @@ + } + + /* XXX: use a token or a hash table to accelerate matching ? */ +-static CachedInclude *search_cached_include(TCCState *s1, ++static CachedInclude *search_cached_include(TCCState *st, + int type, const char *filename) + { + CachedInclude *e; + int i, h; +- h = hash_cached_include(type, filename); +- i = s1->cached_includes_hash[h]; ++ h = hash_cached_include(st, type, filename); ++ i = st->cached_includes_hash[h]; + for(;;) { + if (i == 0) + break; +- e = s1->cached_includes[i - 1]; ++ e = st->cached_includes[i - 1]; + if (e->type == type && !strcmp(e->filename, filename)) + return e; + i = e->hash_next; +@@ -2715,81 +1862,80 @@ + return NULL; + } + +-static inline void add_cached_include(TCCState *s1, int type, ++static inline void add_cached_include(TCCState *st, int type, + const char *filename, int ifndef_macro) + { + CachedInclude *e; + int h; + +- if (search_cached_include(s1, type, filename)) ++ if (search_cached_include(st, type, filename)) + return; + #ifdef INC_DEBUG +- printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL)); ++ printf("adding cached '%s' %s\n", filename, get_tok_str(st, ifndef_macro, NULL)); + #endif +- e = tcc_malloc(sizeof(CachedInclude) + strlen(filename)); ++ e = tcc_malloc(st, sizeof(CachedInclude) + strlen(filename)); + if (!e) + return; + e->type = type; + strcpy(e->filename, filename); + e->ifndef_macro = ifndef_macro; +- dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e); ++ dynarray_add(st, (void ***)&st->cached_includes, &st->nb_cached_includes, e); + /* add in hash table */ +- h = hash_cached_include(type, filename); +- e->hash_next = s1->cached_includes_hash[h]; +- s1->cached_includes_hash[h] = s1->nb_cached_includes; ++ h = hash_cached_include(st, type, filename); ++ e->hash_next = st->cached_includes_hash[h]; ++ st->cached_includes_hash[h] = st->nb_cached_includes; + } + +-static void pragma_parse(TCCState *s1) ++static void pragma_parse(TCCState *st) + { + int val; + +- next(); ++ next(st); + if (tok == TOK_pack) { + /* + This may be: +- #pragma pack(1) // set +- #pragma pack() // reset to default +- #pragma pack(push,1) // push & set +- #pragma pack(pop) // restore previous ++ #pragma pack(1) set ++ #pragma pack() reset to default ++ #pragma pack(push,1) push & set ++ #pragma pack(pop) restore previous + */ +- next(); +- skip('('); ++ next(st); ++ skip(st, '('); + if (tok == TOK_ASM_pop) { +- next(); +- if (s1->pack_stack_ptr <= s1->pack_stack) { ++ next(st); ++ if (st->pack_stack_ptr <= st->pack_stack) { + stk_error: +- error("out of pack stack"); ++ tcc_error(st,"out of pack stack"); + } +- s1->pack_stack_ptr--; ++ st->pack_stack_ptr--; + } else { + val = 0; + if (tok != ')') { + if (tok == TOK_ASM_push) { +- next(); +- if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1) ++ next(st); ++ if (st->pack_stack_ptr >= st->pack_stack + PACK_STACK_SIZE - 1) + goto stk_error; +- s1->pack_stack_ptr++; +- skip(','); ++ st->pack_stack_ptr++; ++ skip(st, ','); + } + if (tok != TOK_CINT) { + pack_error: +- error("invalid pack pragma"); ++ tcc_error(st, "invalid pack pragma"); + } + val = tokc.i; + if (val < 1 || val > 16 || (val & (val - 1)) != 0) + goto pack_error; +- next(); ++ next(st); + } +- *s1->pack_stack_ptr = val; +- skip(')'); ++ *st->pack_stack_ptr = val; ++ skip(st, ')'); + } + } + } + + /* is_bof is true if first non space token at beginning of file */ +-static void preprocess(int is_bof) ++static void preprocess(TCCState * st, int is_bof) + { +- TCCState *s1 = tcc_state; + int size, i, c, n, saved_parse_flags; + char buf[1024], *q, *p; + char buf1[1024]; +@@ -2800,67 +1946,67 @@ + saved_parse_flags = parse_flags; + parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | + PARSE_FLAG_LINEFEED; +- next_nomacro(); ++ next_nomacro(st); + redo: + switch(tok) { + case TOK_DEFINE: +- next_nomacro(); +- parse_define(); ++ next_nomacro(st); ++ parse_define(st); + break; + case TOK_UNDEF: +- next_nomacro(); +- s = define_find(tok); ++ next_nomacro(st); ++ s = define_find(st, tok); + /* undefine symbol by putting an invalid name */ + if (s) + define_undef(s); + break; + case TOK_INCLUDE: + case TOK_INCLUDE_NEXT: +- ch = file->buf_ptr[0]; ++ fch = file->buf_ptr[0]; + /* XXX: incorrect if comments : use next_nomacro with a special mode */ +- skip_spaces(); +- if (ch == '<') { ++ skip_spaces(st); ++ if (fch == '<') { + c = '>'; + goto read_name; +- } else if (ch == '\"') { +- c = ch; ++ } else if (fch == '\"') { ++ c = fch; + read_name: + /* XXX: better stray handling */ +- minp(); ++ minp(st); + q = buf; +- while (ch != c && ch != '\n' && ch != CH_EOF) { ++ while (fch != c && fch != '\n' && fch != CH_EOF) { + if ((q - buf) < sizeof(buf) - 1) +- *q++ = ch; +- minp(); ++ *q++ = fch; ++ minp(st); + } + *q = '\0'; +- minp(); ++ minp(st); + #if 0 + /* eat all spaces and comments after include */ + /* XXX: slightly incorrect */ + while (ch1 != '\n' && ch1 != CH_EOF) +- inp(); ++ inp(st); + #endif + } else { + /* computed #include : either we have only strings or + we have anything enclosed in '<>' */ +- next(); ++ next(st); + buf[0] = '\0'; + if (tok == TOK_STR) { + while (tok != TOK_LINEFEED) { + if (tok != TOK_STR) { + include_syntax: +- error("'#include' expects \"FILENAME\" or "); ++ tcc_error(st,"'#include' expects \"FILENAME\" or "); + } +- pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data); +- next(); ++ pstrcat(st, buf, sizeof(buf), (char *)tokc.cstr->data); ++ next(st); + } + c = '\"'; + } else { + int len; + while (tok != TOK_LINEFEED) { +- pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc)); +- next(); ++ pstrcat(st, buf, sizeof(buf), get_tok_str(st,tok, &tokc)); ++ next(st); + } + len = strlen(buf); + /* check syntax and remove '<>' */ +@@ -2872,8 +2018,8 @@ + } + } + +- e = search_cached_include(s1, c, buf); +- if (e && define_find(e->ifndef_macro)) { ++ e = search_cached_include(st, c, buf); ++ if (e && define_find(st, e->ifndef_macro)) { + /* no need to parse the include because the 'ifndef macro' + is defined */ + #ifdef INC_DEBUG +@@ -2890,8 +2036,8 @@ + size = sizeof(buf1) - 1; + memcpy(buf1, file->filename, size); + buf1[size] = '\0'; +- pstrcat(buf1, sizeof(buf1), buf); +- f = tcc_open(s1, buf1); ++ pstrcat(st, buf1, sizeof(buf1), buf); ++ f = tcc_open(st, buf1); + if (f) { + if (tok == TOK_INCLUDE_NEXT) + tok = TOK_INCLUDE; +@@ -2899,20 +2045,20 @@ + goto found; + } + } +- if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE) +- error("#include recursion too deep"); ++ if (st->include_stack_ptr >= st->include_stack + INCLUDE_STACK_SIZE) ++ tcc_error(st, "#include recursion too deep"); + /* now search in all the include paths */ +- n = s1->nb_include_paths + s1->nb_sysinclude_paths; ++ n = st->nb_include_paths + st->nb_sysinclude_paths; + for(i = 0; i < n; i++) { + const char *path; +- if (i < s1->nb_include_paths) +- path = s1->include_paths[i]; ++ if (i < st->nb_include_paths) ++ path = st->include_paths[i]; + else +- path = s1->sysinclude_paths[i - s1->nb_include_paths]; +- pstrcpy(buf1, sizeof(buf1), path); +- pstrcat(buf1, sizeof(buf1), "/"); +- pstrcat(buf1, sizeof(buf1), buf); +- f = tcc_open(s1, buf1); ++ path = st->sysinclude_paths[i - st->nb_include_paths]; ++ pstrcpy(st, buf1, sizeof(buf1), path); ++ pstrcat(st, buf1, sizeof(buf1), "/"); ++ pstrcat(st, buf1, sizeof(buf1), buf); ++ f = tcc_open(st, buf1); + if (f) { + if (tok == TOK_INCLUDE_NEXT) + tok = TOK_INCLUDE; +@@ -2920,24 +2066,24 @@ + goto found; + } + } +- error("include file '%s' not found", buf); ++ tcc_error(st, "include file '%s' not found", buf); + f = NULL; + found: + #ifdef INC_DEBUG + printf("%s: including %s\n", file->filename, buf1); + #endif + f->inc_type = c; +- pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf); ++ pstrcpy(st, f->inc_filename, sizeof(f->inc_filename), buf); + /* push current file in stack */ + /* XXX: fix current line init */ +- *s1->include_stack_ptr++ = file; ++ *st->include_stack_ptr++ = file; + file = f; + /* add include file debug info */ + if (do_debug) { +- put_stabs(file->filename, N_BINCL, 0, 0, 0); ++ put_stabs(st, file->filename, N_BINCL, 0, 0, 0); + } +- tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL; +- ch = file->buf_ptr[0]; ++ next_tok_flags |= TOK_FLAG_BOW | TOK_FLAG_BOF | TOK_FLAG_BOL; ++ fch = file->buf_ptr[0]; + goto the_end; + } + break; +@@ -2945,104 +2091,104 @@ + c = 1; + goto do_ifdef; + case TOK_IF: +- c = expr_preprocess(); ++ c = expr_preprocess(st); + goto do_if; + case TOK_IFDEF: + c = 0; + do_ifdef: +- next_nomacro(); ++ next_nomacro(st); + if (tok < TOK_IDENT) +- error("invalid argument for '#if%sdef'", c ? "n" : ""); ++ tcc_error(st,"invalid argument for '#if%sdef'", c ? "n" : ""); + if (is_bof) { + if (c) { + #ifdef INC_DEBUG +- printf("#ifndef %s\n", get_tok_str(tok, NULL)); ++ printf("#ifndef %s\n", get_tok_str(st, tok, NULL)); + #endif + file->ifndef_macro = tok; + } + } +- c = (define_find(tok) != 0) ^ c; ++ c = (define_find(st, tok) != 0) ^ c; + do_if: +- if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) +- error("memory full"); +- *s1->ifdef_stack_ptr++ = c; ++ if (st->ifdef_stack_ptr >= st->ifdef_stack + IFDEF_STACK_SIZE) ++ tcc_error(st, "memory full"); ++ *st->ifdef_stack_ptr++ = c; + goto test_skip; + case TOK_ELSE: +- if (s1->ifdef_stack_ptr == s1->ifdef_stack) +- error("#else without matching #if"); +- if (s1->ifdef_stack_ptr[-1] & 2) +- error("#else after #else"); +- c = (s1->ifdef_stack_ptr[-1] ^= 3); ++ if (st->ifdef_stack_ptr == st->ifdef_stack) ++ tcc_error(st, "#else without matching #if"); ++ if (st->ifdef_stack_ptr[-1] & 2) ++ tcc_error(st, "#else after #else"); ++ c = (st->ifdef_stack_ptr[-1] ^= 3); + goto test_skip; + case TOK_ELIF: +- if (s1->ifdef_stack_ptr == s1->ifdef_stack) +- error("#elif without matching #if"); +- c = s1->ifdef_stack_ptr[-1]; ++ if (st->ifdef_stack_ptr == st->ifdef_stack) ++ tcc_error(st, "#elif without matching #if"); ++ c = st->ifdef_stack_ptr[-1]; + if (c > 1) +- error("#elif after #else"); ++ tcc_error(st, "#elif after #else"); + /* last #if/#elif expression was true: we skip */ + if (c == 1) + goto skip; +- c = expr_preprocess(); +- s1->ifdef_stack_ptr[-1] = c; ++ c = expr_preprocess(st); ++ st->ifdef_stack_ptr[-1] = c; + test_skip: + if (!(c & 1)) { + skip: +- preprocess_skip(); ++ preprocess_skip(st); + is_bof = 0; + goto redo; + } + break; + case TOK_ENDIF: +- if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr) +- error("#endif without matching #if"); +- s1->ifdef_stack_ptr--; ++ if (st->ifdef_stack_ptr <= file->ifdef_stack_ptr) ++ tcc_error(st, "#endif without matching #if"); ++ st->ifdef_stack_ptr--; + /* '#ifndef macro' was at the start of file. Now we check if + an '#endif' is exactly at the end of file */ + if (file->ifndef_macro && +- s1->ifdef_stack_ptr == file->ifdef_stack_ptr) { ++ st->ifdef_stack_ptr == file->ifdef_stack_ptr) { + file->ifndef_macro_saved = file->ifndef_macro; + /* need to set to zero to avoid false matches if another + #ifndef at middle of file */ + file->ifndef_macro = 0; + while (tok != TOK_LINEFEED) +- next_nomacro(); +- tok_flags |= TOK_FLAG_ENDIF; ++ next_nomacro(st); ++ next_tok_flags |= TOK_FLAG_ENDIF; + goto the_end; + } + break; + case TOK_LINE: +- next(); ++ next(st); + if (tok != TOK_CINT) +- error("#line"); ++ tcc_error(st, "#line"); + file->line_num = tokc.i - 1; /* the line number will be incremented after */ +- next(); ++ next(st); + if (tok != TOK_LINEFEED) { + if (tok != TOK_STR) +- error("#line"); +- pstrcpy(file->filename, sizeof(file->filename), ++ tcc_error(st, "#line"); ++ pstrcpy(st, file->filename, sizeof(file->filename), + (char *)tokc.cstr->data); + } + break; + case TOK_ERROR: + case TOK_WARNING: + c = tok; +- ch = file->buf_ptr[0]; +- skip_spaces(); ++ fch = file->buf_ptr[0]; ++ skip_spaces(st); + q = buf; +- while (ch != '\n' && ch != CH_EOF) { ++ while (fch != '\n' && fch != CH_EOF) { + if ((q - buf) < sizeof(buf) - 1) +- *q++ = ch; +- minp(); ++ *q++ = fch; ++ minp(st); + } + *q = '\0'; + if (c == TOK_ERROR) +- error("#error %s", buf); ++ tcc_error(st, "#error %s", buf); + else +- warning("#warning %s", buf); ++ warning(st, "#warning %s", buf); + break; + case TOK_PRAGMA: +- pragma_parse(s1); ++ pragma_parse(st); + break; + default: + if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) { +@@ -3050,19 +2196,19 @@ + to emulate cpp behaviour */ + } else { + if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS)) +- error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc)); ++ tcc_error(st, "invalid preprocessing directive #%s", get_tok_str(st,tok, &tokc)); + } + break; + } + /* ignore other preprocess commands or #! for C scripts */ + while (tok != TOK_LINEFEED) +- next_nomacro(); ++ next_nomacro(st); + the_end: + parse_flags = saved_parse_flags; + } + + /* evaluate escape codes in a string. */ +-static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long) ++static void parse_escape_string(TCCState *st, CString *outstr, const uint8_t *buf, int is_long) + { + int c, n; + const uint8_t *p; +@@ -3083,11 +2229,11 @@ + n = c - '0'; + p++; + c = *p; +- if (isoct(c)) { ++ if (isoct(st, c)) { + n = n * 8 + c - '0'; + p++; + c = *p; +- if (isoct(c)) { ++ if (isoct(st, c)) { + n = n * 8 + c - '0'; + p++; + } +@@ -3095,6 +2241,8 @@ + c = n; + goto add_char_nonext; + case 'x': ++ case 'u': ++ case 'U': + p++; + n = 0; + for(;;) { +@@ -3103,7 +2251,7 @@ + c = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + c = c - 'A' + 10; +- else if (isnum(c)) ++ else if (isnum(st, c)) + c = c - '0'; + else + break; +@@ -3146,24 +2294,24 @@ + default: + invalid_escape: + if (c >= '!' && c <= '~') +- warning("unknown escape sequence: \'\\%c\'", c); ++ warning(st, "unknown escape sequence: \'\\%c\'", c); + else +- warning("unknown escape sequence: \'\\x%x\'", c); ++ warning(st, "unknown escape sequence: \'\\x%x\'", c); + break; + } + } + p++; + add_char_nonext: + if (!is_long) +- cstr_ccat(outstr, c); ++ cstr_ccat(st, outstr, c); + else +- cstr_wccat(outstr, c); ++ cstr_wccat(st, outstr, c); + } + /* add a trailing '\0' */ + if (!is_long) +- cstr_ccat(outstr, '\0'); ++ cstr_ccat(st, outstr, '\0'); + else +- cstr_wccat(outstr, '\0'); ++ cstr_wccat(st, outstr, '\0'); + } + + /* we use 64 bit numbers */ +@@ -3191,7 +2339,7 @@ + + /* parse number in null terminated string 'p' and return it in the + current token */ +-void parse_number(const char *p) ++void parse_number(TCCState *st, const char *p) + { + int b, t, shift, frac_bits, s, exp_val, ch; + char *q; +@@ -3225,7 +2373,7 @@ + t = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + t = ch - 'A' + 10; +- else if (isnum(ch)) ++ else if (isnum(st, ch)) + t = ch - '0'; + else + break; +@@ -3233,7 +2381,7 @@ + break; + if (q >= token_buf + STRING_MAX_SIZE) { + num_too_long: +- error("number too long"); ++ tcc_error(st, "number too long"); + } + *q++ = ch; + ch = *p++; +@@ -3282,14 +2430,14 @@ + break; + } + if (t >= b) +- error("invalid digit"); ++ tcc_error(st, "invalid digit"); + bn_lshift(bn, shift, t); + frac_bits += shift; + ch = *p++; + } + } + if (ch != 'p' && ch != 'P') +- expect("exponent"); ++ expect(st, "exponent"); + ch = *p++; + s = 1; + exp_val = 0; +@@ -3300,7 +2448,7 @@ + ch = *p++; + } + if (ch < '0' || ch > '9') +- expect("exponent digits"); ++ expect(st, "exponent digits"); + while (ch >= '0' && ch <= '9') { + exp_val = exp_val * 10 + ch - '0'; + ch = *p++; +@@ -3311,7 +2459,7 @@ + /* XXX: should patch directly float number */ + d = (double)bn[1] * 4294967296.0 + (double)bn[0]; + d = ldexp(d, exp_val - frac_bits); +- t = toup(ch); ++ t = toup(st, ch); + if (t == 'F') { + ch = *p++; + tok = TOK_CFLOAT; +@@ -3353,7 +2501,7 @@ + ch = *p++; + } + if (ch < '0' || ch > '9') +- expect("exponent digits"); ++ expect(st, "exponent digits"); + while (ch >= '0' && ch <= '9') { + if (q >= token_buf + STRING_MAX_SIZE) + goto num_too_long; +@@ -3362,7 +2510,7 @@ + } + } + *q = '\0'; +- t = toup(ch); ++ t = toup(st, ch); + errno = 0; + if (t == 'F') { + ch = *p++; +@@ -3401,14 +2549,14 @@ + } else { + t = t - '0'; + if (t >= b) +- error("invalid digit"); ++ tcc_error(st, "invalid digit"); + } + n1 = n; + n = n * b + t; + /* detect overflow */ + /* XXX: this test is not reliable */ + if (n < n1) +- error("integer constant overflow"); ++ tcc_error(st, "integer constant overflow"); + } + + /* XXX: not exactly ANSI compliant */ +@@ -3425,10 +2573,10 @@ + lcount = 0; + ucount = 0; + for(;;) { +- t = toup(ch); ++ t = toup(st, ch); + if (t == 'L') { + if (lcount >= 2) +- error("three 'l's in integer constant"); ++ tcc_error(st, "three 'l's in integer constant"); + lcount++; + if (lcount == 2) { + if (tok == TOK_CINT) +@@ -3439,7 +2587,7 @@ + ch = *p++; + } else if (t == 'U') { + if (ucount >= 1) +- error("two 'u's in integer constant"); ++ tcc_error(st, "two 'u's in integer constant"); + ucount++; + if (tok == TOK_CINT) + tok = TOK_CUINT; +@@ -3458,9 +2606,9 @@ + } + + +-#define PARSE2(c1, tok1, c2, tok2) \ ++#define PARSE2(st, c1, tok1, c2, tok2) \ + case c1: \ +- PEEKC(c, p); \ ++ PEEKC(st, c, p); \ + if (c == c2) { \ + p++; \ + tok = tok2; \ +@@ -3470,7 +2618,7 @@ + break; + + /* return next token without macro substitution */ +-static inline void next_nomacro1(void) ++static inline void next_nomacro1(TCCState *st) + { + int t, c, is_long; + TokenSym *ts; +@@ -3487,13 +2635,14 @@ + case '\v': + case '\r': + p++; ++ next_tok_flags |= TOK_FLAG_BOW; + goto redo_no_start; + + case '\\': + /* first look if it is in fact an end of buffer */ + if (p >= file->buf_end) { + file->buf_ptr = p; +- handle_eob(); ++ handle_eob(st); + p = file->buf_ptr; + if (p >= file->buf_end) + goto parse_eof; +@@ -3501,17 +2650,16 @@ + goto redo_no_start; + } else { + file->buf_ptr = p; +- ch = *p; +- handle_stray(); ++ fch = *p; ++ handle_stray(st); + p = file->buf_ptr; + goto redo_no_start; + } + parse_eof: + { +- TCCState *s1 = tcc_state; + if (parse_flags & PARSE_FLAG_LINEFEED) { + tok = TOK_LINEFEED; +- } else if (s1->include_stack_ptr == s1->include_stack || ++ } else if (st->include_stack_ptr == st->include_stack || + !(parse_flags & PARSE_FLAG_PREPROCESS)) { + /* no include left : end of file. */ + tok = TOK_EOF; +@@ -3520,22 +2668,22 @@ + + /* test if previous '#endif' was after a #ifdef at + start of file */ +- if (tok_flags & TOK_FLAG_ENDIF) { ++ if (next_tok_flags & TOK_FLAG_ENDIF) { + #ifdef INC_DEBUG +- printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL)); ++ printf("#endif %s\n", get_tok_str(st, file->ifndef_macro_saved, NULL)); + #endif +- add_cached_include(s1, file->inc_type, file->inc_filename, ++ add_cached_include(st, file->inc_type, file->inc_filename, + file->ifndef_macro_saved); + } + + /* add end of include file debug info */ + if (do_debug) { +- put_stabd(N_EINCL, 0, 0); ++ put_stabd(st, N_EINCL, 0, 0); + } + /* pop include stack */ + tcc_close(file); +- s1->include_stack_ptr--; +- file = *s1->include_stack_ptr; ++ st->include_stack_ptr--; ++ file = *st->include_stack_ptr; + p = file->buf_ptr; + goto redo_no_start; + } +@@ -3547,7 +2695,7 @@ + tok = TOK_LINEFEED; + } else { + file->line_num++; +- tok_flags |= TOK_FLAG_BOL; ++ next_tok_flags |= TOK_FLAG_BOW | TOK_FLAG_BOL; + p++; + goto redo_no_start; + } +@@ -3555,11 +2703,11 @@ + + case '#': + /* XXX: simplify */ +- PEEKC(c, p); +- if ((tok_flags & TOK_FLAG_BOL) && ++ PEEKC(st, c, p); ++ if ((next_tok_flags & TOK_FLAG_BOL) && + (parse_flags & PARSE_FLAG_PREPROCESS)) { + file->buf_ptr = p; +- preprocess(tok_flags & TOK_FLAG_BOF); ++ preprocess(st, next_tok_flags & TOK_FLAG_BOF); + p = file->buf_ptr; + goto redo_no_start; + } else { +@@ -3568,7 +2716,7 @@ + tok = TOK_TWOSHARPS; + } else { + if (parse_flags & PARSE_FLAG_ASM_COMMENTS) { +- p = parse_line_comment(p - 1); ++ p = parse_line_comment(st, p - 1); + goto redo_no_start; + } else { + tok = '#'; +@@ -3621,24 +2769,24 @@ + goto token_found; + pts = &(ts->hash_next); + } +- ts = tok_alloc_new(pts, p1, len); ++ ts = tok_alloc_new(st, pts, p1, len); + token_found: ; + } else { + /* slower case */ +- cstr_reset(&tokcstr); ++ cstr_reset(st, &tokcstr); + + while (p1 < p) { +- cstr_ccat(&tokcstr, *p1); ++ cstr_ccat(st, &tokcstr, *p1); + p1++; + } + p--; +- PEEKC(c, p); ++ PEEKC(st, c, p); + parse_ident_slow: + while (isidnum_table[c]) { +- cstr_ccat(&tokcstr, c); +- PEEKC(c, p); ++ cstr_ccat(st, &tokcstr, c); ++ PEEKC(st, c, p); + } +- ts = tok_alloc(tokcstr.data, tokcstr.size); ++ ts = tok_alloc(st, tokcstr.data, tokcstr.size); + } + tok = ts->tok; + break; +@@ -3648,13 +2796,13 @@ + /* fast case */ + goto parse_ident_fast; + } else { +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '\'' || c == '\"') { + is_long = 1; + goto str_const; + } else { +- cstr_reset(&tokcstr); +- cstr_ccat(&tokcstr, 'L'); ++ cstr_reset(st, &tokcstr); ++ cstr_ccat(st, &tokcstr, 'L'); + goto parse_ident_slow; + } + } +@@ -3663,36 +2811,36 @@ + case '4': case '5': case '6': case '7': + case '8': case '9': + +- cstr_reset(&tokcstr); ++ cstr_reset(st, &tokcstr); + /* after the first digit, accept digits, alpha, '.' or sign if + prefixed by 'eEpP' */ + parse_num: + for(;;) { + t = c; +- cstr_ccat(&tokcstr, c); +- PEEKC(c, p); +- if (!(isnum(c) || isid(c) || c == '.' || ++ cstr_ccat(st, &tokcstr, c); ++ PEEKC(st, c, p); ++ if (!(isnum(st, c) || isid(st, c) || c == '.' || + ((c == '+' || c == '-') && + (t == 'e' || t == 'E' || t == 'p' || t == 'P')))) + break; + } + /* We add a trailing '\0' to ease parsing */ +- cstr_ccat(&tokcstr, '\0'); ++ cstr_ccat(st, &tokcstr, '\0'); + tokc.cstr = &tokcstr; + tok = TOK_PPNUM; + break; + case '.': + /* special dot handling because it can also start a number */ +- PEEKC(c, p); +- if (isnum(c)) { +- cstr_reset(&tokcstr); +- cstr_ccat(&tokcstr, '.'); ++ PEEKC(st, c, p); ++ if (isnum(st, c)) { ++ cstr_reset(st, &tokcstr); ++ cstr_ccat(st, &tokcstr, '.'); + goto parse_num; + } else if (c == '.') { +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c != '.') +- expect("'.'"); +- PEEKC(c, p); ++ expect(st, "'.'"); ++ PEEKC(st, c, p); + tok = TOK_DOTS; + } else { + tok = '.'; +@@ -3709,14 +2857,14 @@ + sep = c; + + /* parse the string */ +- cstr_new(&str); +- p = parse_pp_string(p, sep, &str); +- cstr_ccat(&str, '\0'); ++ cstr_new(st, &str); ++ p = parse_pp_string(st, p, sep, &str); ++ cstr_ccat(st, &str, '\0'); + + /* eval the escape (should be done as TOK_PPNUM) */ +- cstr_reset(&tokcstr); +- parse_escape_string(&tokcstr, str.data, is_long); +- cstr_free(&str); ++ cstr_reset(st, &tokcstr); ++ parse_escape_string(st, &tokcstr, str.data, is_long); ++ cstr_free(st, &str); + + if (sep == '\'') { + int char_size; +@@ -3724,16 +2872,16 @@ + if (!is_long) + char_size = 1; + else +- char_size = sizeof(int); ++ char_size = sizeof(nwchar_t); + if (tokcstr.size <= char_size) +- error("empty character constant"); ++ tcc_error(st, "empty character constant"); + if (tokcstr.size > 2 * char_size) +- warning("multi-character character constant"); ++ warning(st, "multi-character character constant"); + if (!is_long) { + tokc.i = *(int8_t *)tokcstr.data; + tok = TOK_CCHAR; + } else { +- tokc.i = *(int *)tokcstr.data; ++ tokc.i = *(nwchar_t *)tokcstr.data; + tok = TOK_LCHAR; + } + } else { +@@ -3747,12 +2895,12 @@ + break; + + case '<': +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '=') { + p++; + tok = TOK_LE; + } else if (c == '<') { +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '=') { + p++; + tok = TOK_A_SHL; +@@ -3765,12 +2913,12 @@ + break; + + case '>': +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '=') { + p++; + tok = TOK_GE; + } else if (c == '>') { +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '=') { + p++; + tok = TOK_A_SAR; +@@ -3783,7 +2931,7 @@ + break; + + case '&': +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '&') { + p++; + tok = TOK_LAND; +@@ -3796,7 +2944,7 @@ + break; + + case '|': +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '|') { + p++; + tok = TOK_LOR; +@@ -3809,7 +2957,7 @@ + break; + + case '+': +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '+') { + p++; + tok = TOK_INC; +@@ -3822,7 +2970,7 @@ + break; + + case '-': +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '-') { + p++; + tok = TOK_DEC; +@@ -3837,20 +2985,22 @@ + } + break; + +- PARSE2('!', '!', '=', TOK_NE) +- PARSE2('=', '=', '=', TOK_EQ) +- PARSE2('*', '*', '=', TOK_A_MUL) +- PARSE2('%', '%', '=', TOK_A_MOD) +- PARSE2('^', '^', '=', TOK_A_XOR) ++ PARSE2(st, '!', '!', '=', TOK_NE) ++ PARSE2(st, '=', '=', '=', TOK_EQ) ++ PARSE2(st, '*', '*', '=', TOK_A_MUL) ++ PARSE2(st, '%', '%', '=', TOK_A_MOD) ++ PARSE2(st, '^', '^', '=', TOK_A_XOR) + + /* comments or operator */ + case '/': +- PEEKC(c, p); ++ PEEKC(st, c, p); + if (c == '*') { +- p = parse_comment(p); ++ p = parse_comment(st, p); ++ next_tok_flags |= TOK_FLAG_BOW; + goto redo_no_start; + } else if (c == '/') { +- p = parse_line_comment(p); ++ p = parse_line_comment(st, p); ++ next_tok_flags |= TOK_FLAG_BOW; + goto redo_no_start; + } else if (c == '=') { + p++; +@@ -3878,82 +3028,85 @@ + p++; + break; + default: +- error("unrecognized character \\x%02x", c); ++ tcc_error(st, "unrecognized character \\x%02x", c); + break; + } + file->buf_ptr = p; +- tok_flags = 0; ++ tok_flags = next_tok_flags; ++ next_tok_flags = 0; + #if defined(PARSE_DEBUG) +- printf("token = %s\n", get_tok_str(tok, &tokc)); ++ printf("token = %s\n", get_tok_str(st, tok, &tokc)); + #endif + } + + /* return next token without macro substitution. Can read input from + macro_ptr buffer */ +-static void next_nomacro(void) ++static void next_nomacro(TCCState *st) + { + if (macro_ptr) { + redo: + tok = *macro_ptr; + if (tok) { +- TOK_GET(tok, macro_ptr, tokc); ++ TOK_GET(tok, tok_flags, macro_ptr, tokc); + if (tok == TOK_LINENUM) { + file->line_num = tokc.i; + goto redo; + } + } + } else { +- next_nomacro1(); ++ next_nomacro1(st ); + } + } + + /* substitute args in macro_str and return allocated string */ +-static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) ++static int *macro_arg_subst(TCCState *state, Sym **nested_list, int *macro_str, Sym *args) + { +- int *st, last_tok, t, notfirst; ++ int *st, last_tok, t, tf, save_tf, notfirst; + Sym *s; + CValue cval; + TokenString str; + CString cstr; + +- tok_str_new(&str); ++ tok_str_new(state, &str); + last_tok = 0; + while(1) { +- TOK_GET(t, macro_str, cval); ++ TOK_GET(t, tf, macro_str, cval); ++ save_tf = tf; + if (!t) + break; + if (t == '#') { + /* stringize */ +- TOK_GET(t, macro_str, cval); ++ TOK_GET(t, tf, macro_str, cval); + if (!t) + break; +- s = sym_find2(args, t); ++ s = sym_find2(state, args, t); + if (s) { +- cstr_new(&cstr); ++ cstr_new(state, &cstr); + st = (int *)s->c; + notfirst = 0; + while (*st) { +- if (notfirst) +- cstr_ccat(&cstr, ' '); +- TOK_GET(t, st, cval); +- cstr_cat(&cstr, get_tok_str(t, &cval)); ++ TOK_GET(t, tf, st, cval); ++ if (notfirst && tf & TOK_FLAG_BOW) ++ cstr_ccat(state, &cstr, ' '); ++ cstr_cat(state, &cstr, get_tok_str(state, t, &cval)); + notfirst = 1; + } +- cstr_ccat(&cstr, '\0'); ++ cstr_ccat(state, &cstr, '\0'); + #ifdef PP_DEBUG + printf("stringize: %s\n", (char *)cstr.data); + #endif + /* add string */ + cval.cstr = &cstr; +- tok_str_add2(&str, TOK_STR, &cval); +- cstr_free(&cstr); ++ tok_str_add2(state, &str, TOK_STR, save_tf, &cval); ++ cstr_free(state, &cstr); + } else { +- tok_str_add2(&str, t, &cval); ++ tok_str_add2(state, &str, t, save_tf, &cval); + } + } else if (t >= TOK_IDENT) { +- s = sym_find2(args, t); ++ s = sym_find2(state, args, t); + if (s) { + st = (int *)s->c; ++ st[1] = save_tf; + /* if '##' is present before or after, no arg substitution */ + if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) { + /* special case for var arg macros : ## eats the +@@ -3963,39 +3116,40 @@ + problems */ + if (gnu_ext && s->type.t && + last_tok == TOK_TWOSHARPS && +- str.len >= 2 && str.str[str.len - 2] == ',') { ++ str.len >= 4 && str.str[str.len - 4] == ',') { + if (*st == 0) { + /* suppress ',' '##' */ +- str.len -= 2; ++ str.len -= 4; ++ next_tok_flags = tok_flags; + } else { + /* suppress '##' and add variable */ +- str.len--; ++ str.len -= 2; + goto add_var; + } + } else { + int t1; + add_var: + for(;;) { +- TOK_GET(t1, st, cval); ++ TOK_GET(t1, tf, st, cval); + if (!t1) + break; +- tok_str_add2(&str, t1, &cval); ++ tok_str_add2(state, &str, t1, save_tf, &cval); + } + } + } else { + /* NOTE: the stream cannot be read when macro + substituing an argument */ +- macro_subst(&str, nested_list, st, NULL); ++ macro_subst(state, &str, nested_list, st, NULL); + } + } else { +- tok_str_add(&str, t); ++ tok_str_add(state, &str, t, tf); + } + } else { +- tok_str_add2(&str, t, &cval); ++ tok_str_add2(state, &str, t, tf, &cval); + } + last_tok = t; + } +- tok_str_add(&str, 0); ++ tok_str_add(state, &str, 0, 0); + return str.str; + } + +@@ -4009,7 +3163,7 @@ + result to (tok_str,tok_len). 'nested_list' is the list of all + macros we got inside to avoid recursing. Return non zero if no + substitution needs to be done */ +-static int macro_subst_tok(TokenString *tok_str, ++static int macro_subst_tok(TCCState *st, TokenString *tok_str, + Sym **nested_list, Sym *s, struct macro_level **can_read_stream) + { + Sym *args, *sa, *sa1; +@@ -4047,14 +3201,15 @@ + add_cstr: + t1 = TOK_STR; + add_cstr1: +- cstr_new(&cstr); +- cstr_cat(&cstr, cstrval); +- cstr_ccat(&cstr, '\0'); ++ cstr_new(st, &cstr); ++ cstr_cat(st, &cstr, cstrval); ++ cstr_ccat(st, &cstr, '\0'); + cval.cstr = &cstr; +- tok_str_add2(tok_str, t1, &cval); +- cstr_free(&cstr); ++ tok_str_add2(st, tok_str, t1, tok_flags, &cval); ++ cstr_free(st, &cstr); + } else { + mstr = (int *)s->c; ++ mstr[1] = tok_flags; + mstr_allocated = 0; + if (s->type.t == MACRO_FUNC) { + /* NOTE: we do not use next_nomacro to avoid eating the +@@ -4077,17 +3232,17 @@ + } + } else { + /* XXX: incorrect with comments */ +- ch = file->buf_ptr[0]; +- while (is_space(ch) || ch == '\n') +- cinp(); +- t = ch; ++ fch = file->buf_ptr[0]; ++ while (is_space(st, fch) || fch == '\n') ++ cinp(st); ++ t = fch; + } + if (t != '(') /* no macro subst */ + return -1; + + /* argument macro */ +- next_nomacro(); +- next_nomacro(); ++ next_nomacro(st); ++ next_nomacro(st); + args = NULL; + sa = s->next; + /* NOTE: empty args are allowed, except if no args */ +@@ -4096,9 +3251,9 @@ + if (!args && !sa && tok == ')') + break; + if (!sa) +- error("macro '%s' used with too many args", +- get_tok_str(s->v, 0)); +- tok_str_new(&str); ++ tcc_error(st, "macro '%s' used with too many args", ++ get_tok_str(st, s->v, 0)); ++ tok_str_new(st, &str); + parlevel = 0; + /* NOTE: non zero sa->t indicates VA_ARGS */ + while ((parlevel > 0 || +@@ -4109,11 +3264,11 @@ + parlevel++; + else if (tok == ')') + parlevel--; +- tok_str_add2(&str, tok, &tokc); +- next_nomacro(); ++ tok_str_add2(st, &str, tok, tok_flags, &tokc); ++ next_nomacro(st); + } +- tok_str_add(&str, 0); +- sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str); ++ tok_str_add(st, &str, 0, 0); ++ sym_push2(st, &args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str); + sa = sa->next; + if (tok == ')') { + /* special case for gcc var args: add an empty +@@ -4124,45 +3279,45 @@ + break; + } + if (tok != ',') +- expect(","); +- next_nomacro(); ++ expect(st, ","); ++ next_nomacro(st); + } + if (sa) { +- error("macro '%s' used with too few args", +- get_tok_str(s->v, 0)); ++ tcc_error(st, "macro '%s' used with too few args", ++ get_tok_str(st, s->v, 0)); + } + + /* now subst each arg */ +- mstr = macro_arg_subst(nested_list, mstr, args); ++ mstr = macro_arg_subst(st, nested_list, mstr, args); + /* free memory */ + sa = args; + while (sa) { + sa1 = sa->prev; +- tok_str_free((int *)sa->c); +- sym_free(sa); ++ tok_str_free(st, (int *)sa->c); ++ sym_free(st, sa); + sa = sa1; + } + mstr_allocated = 1; + } +- sym_push2(nested_list, s->v, 0, 0); +- macro_subst(tok_str, nested_list, mstr, can_read_stream); ++ sym_push2(st, nested_list, s->v, 0, 0); ++ macro_subst(st, tok_str, nested_list, mstr, can_read_stream); + /* pop nested defined symbol */ + sa1 = *nested_list; + *nested_list = sa1->prev; +- sym_free(sa1); ++ sym_free(st, sa1); + if (mstr_allocated) +- tok_str_free(mstr); ++ tok_str_free(st, mstr); + } + return 0; + } + + /* handle the '##' operator. Return NULL if no '##' seen. Otherwise + return the resulting string (which must be freed). */ +-static inline int *macro_twosharps(const int *macro_str) ++static inline int *macro_twosharps(TCCState *st, const int *macro_str) + { + TokenSym *ts; + const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr; +- int t; ++ int t, tf; + const char *p1, *p2; + CValue cval; + TokenString macro_str1; +@@ -4172,7 +3327,7 @@ + /* we search the first '##' */ + for(;;) { + macro_ptr1 = macro_str; +- TOK_GET(t, macro_str, cval); ++ TOK_GET(t, tf, macro_str, cval); + /* nothing more to do if end of string */ + if (t == 0) + return NULL; +@@ -4181,42 +3336,48 @@ + } + + /* we saw '##', so we need more processing to handle it */ +- cstr_new(&cstr); +- tok_str_new(¯o_str1); ++ cstr_new(st, &cstr); ++ tok_str_new(st, ¯o_str1); + tok = t; ++ tok_flags = tf; + tokc = cval; + + /* add all tokens seen so far */ + for(ptr = start_macro_ptr; ptr < macro_ptr1;) { +- TOK_GET(t, ptr, cval); +- tok_str_add2(¯o_str1, t, &cval); ++ TOK_GET(t, tf, ptr, cval); ++ tok_str_add2(st, ¯o_str1, t, tf, &cval); + } + saved_macro_ptr = macro_ptr; + /* XXX: get rid of the use of macro_ptr here */ + macro_ptr = (int *)macro_str; + for(;;) { + while (*macro_ptr == TOK_TWOSHARPS) { +- macro_ptr++; ++ macro_ptr+=2; + macro_ptr1 = macro_ptr; + t = *macro_ptr; + if (t) { +- TOK_GET(t, macro_ptr, cval); ++ TOK_GET(t, tf, macro_ptr, cval); + /* We concatenate the two tokens if we have an + identifier or a preprocessing number */ +- cstr_reset(&cstr); +- p1 = get_tok_str(tok, &tokc); +- cstr_cat(&cstr, p1); +- p2 = get_tok_str(t, &cval); +- cstr_cat(&cstr, p2); +- cstr_ccat(&cstr, '\0'); ++ cstr_reset(st, &cstr); ++ p1 = get_tok_str(st, tok, &tokc); ++ cstr_cat(st, &cstr, p1); ++ p2 = get_tok_str(st, t, &cval); ++ cstr_cat(st, &cstr, p2); ++ cstr_ccat(st, &cstr, '\0'); + + if ((tok >= TOK_IDENT || tok == TOK_PPNUM) && + (t >= TOK_IDENT || t == TOK_PPNUM)) { + if (tok == TOK_PPNUM) { + /* if number, then create a number token */ +- /* NOTE: no need to allocate because +- tok_str_add2() does it */ +- tokc.cstr = &cstr; ++ /* NOTE: we cannot use cstr directly for this ++ because if there are multiple token pastings ++ in a sequence the concatenation will reset ++ cstr before the final token is ready. */ ++ cstr_reset(st, &tokcstr); ++ cstr_cat(st, &tokcstr, cstr.data); ++ cstr_ccat(st, &tokcstr, '\0'); ++ tokc.cstr = &tokcstr; + } else { + /* if identifier, we must do a test to + validate we have a correct identifier */ +@@ -4230,11 +3391,11 @@ + if (c == '\0') + break; + p++; +- if (!isnum(c) && !isid(c)) ++ if (!isnum(st, c) && !isid(st, c)) + goto error_pasting; + } + } +- ts = tok_alloc(cstr.data, strlen(cstr.data)); ++ ts = tok_alloc(st, cstr.data, strlen(cstr.data)); + tok = ts->tok; /* modify current token */ + } + } else { +@@ -4262,14 +3423,14 @@ + error_pasting: + /* NOTE: because get_tok_str use a static buffer, + we must save it */ +- cstr_reset(&cstr); +- p1 = get_tok_str(tok, &tokc); +- cstr_cat(&cstr, p1); +- cstr_ccat(&cstr, '\0'); +- p2 = get_tok_str(t, &cval); +- warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2); ++ cstr_reset(st, &cstr); ++ p1 = get_tok_str(st, tok, &tokc); ++ cstr_cat(st, &cstr, p1); ++ cstr_ccat(st, &cstr, '\0'); ++ p2 = get_tok_str(st, t, &cval); ++ warning(st, "pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2); + /* cannot merge tokens: just add them separately */ +- tok_str_add2(¯o_str1, tok, &tokc); ++ tok_str_add2(st, ¯o_str1, tok, tok_flags, &tokc); + /* XXX: free associated memory ? */ + tok = t; + tokc = cval; +@@ -4277,14 +3438,14 @@ + } + } + } +- tok_str_add2(¯o_str1, tok, &tokc); +- next_nomacro(); ++ tok_str_add2(st, ¯o_str1, tok, tok_flags, &tokc); ++ next_nomacro(st); + if (tok == 0) + break; + } + macro_ptr = (int *)saved_macro_ptr; +- cstr_free(&cstr); +- tok_str_add(¯o_str1, 0); ++ cstr_free(st, &cstr); ++ tok_str_add(st, ¯o_str1, 0, 0); + return macro_str1.str; + } + +@@ -4292,19 +3453,19 @@ + /* do macro substitution of macro_str and add result to + (tok_str,tok_len). 'nested_list' is the list of all macros we got + inside to avoid recursing. */ +-static void macro_subst(TokenString *tok_str, Sym **nested_list, ++static void macro_subst(TCCState *st, TokenString *tok_str, Sym **nested_list, + const int *macro_str, struct macro_level ** can_read_stream) + { + Sym *s; + int *macro_str1; + const int *ptr; +- int t, ret; ++ int t, tf, ret; + CValue cval; + struct macro_level ml; + + /* first scan for '##' operator handling */ + ptr = macro_str; +- macro_str1 = macro_twosharps(ptr); ++ macro_str1 = macro_twosharps(st, ptr); + if (macro_str1) + ptr = macro_str1; + while (1) { +@@ -4312,20 +3473,21 @@ + file stream due to a macro function call */ + if (ptr == NULL) + break; +- TOK_GET(t, ptr, cval); ++ TOK_GET(t, tf, ptr, cval); + if (t == 0) + break; +- s = define_find(t); ++ s = define_find(st, t); + if (s != NULL) { + /* if nested substitution, do nothing */ +- if (sym_find2(*nested_list, t)) ++ if (sym_find2(st, *nested_list, t)) + goto no_subst; + ml.p = macro_ptr; + if (can_read_stream) + ml.prev = *can_read_stream, *can_read_stream = &ml; + macro_ptr = (int *)ptr; + tok = t; +- ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream); ++ tok_flags = tf; ++ ret = macro_subst_tok(st, tok_str, nested_list, s, can_read_stream); + ptr = (int *)macro_ptr; + macro_ptr = ml.p; + if (can_read_stream && *can_read_stream == &ml) +@@ -4334,36 +3496,37 @@ + goto no_subst; + } else { + no_subst: +- tok_str_add2(tok_str, t, &cval); ++ tok_str_add2(st, tok_str, t, tf, &cval); + } + } + if (macro_str1) +- tok_str_free(macro_str1); ++ tok_str_free(st, macro_str1); + } + ++ + /* return next token with macro substitution */ +-static void next(void) ++static void next(TCCState *st) + { + Sym *nested_list, *s; + TokenString str; + struct macro_level *ml; + + redo: +- next_nomacro(); ++ next_nomacro(st); + if (!macro_ptr) { + /* if not reading from macro substituted string, then try + to substitute macros */ + if (tok >= TOK_IDENT && + (parse_flags & PARSE_FLAG_PREPROCESS)) { +- s = define_find(tok); ++ s = define_find(st, tok); + if (s) { + /* we have a macro: we try to substitute */ +- tok_str_new(&str); ++ tok_str_new(st, &str); + nested_list = NULL; + ml = NULL; +- if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) { ++ if (macro_subst_tok(st, &str, &nested_list, s, &ml) == 0) { + /* substitution done, NOTE: maybe empty */ +- tok_str_add(&str, 0); ++ tok_str_add(st, &str, 0, 0); + macro_ptr = str.str; + macro_ptr_allocated = str.str; + goto redo; +@@ -4378,7 +3541,7 @@ + unget_buffer_enabled = 0; + } else { + /* end of macro string: free it */ +- tok_str_free(macro_ptr_allocated); ++ tok_str_free(st, macro_ptr_allocated); + macro_ptr = NULL; + } + goto redo; +@@ -4388,13 +3551,14 @@ + /* convert preprocessor tokens into C tokens */ + if (tok == TOK_PPNUM && + (parse_flags & PARSE_FLAG_TOK_NUM)) { +- parse_number((char *)tokc.cstr->data); ++ parse_number(st, (char *)tokc.cstr->data); + } ++ + } + + /* push back current token and set current token to 'last_tok'. Only + identifier case handled for labels. */ +-static inline void unget_tok(int last_tok) ++static inline void unget_tok(TCCState *st, int last_tok) + { + int i, n; + int *q; +@@ -4403,7 +3567,7 @@ + q = unget_saved_buffer; + macro_ptr = q; + *q++ = tok; +- n = tok_ext_size(tok) - 1; ++ n = tok_ext_size(st, tok) - 1; + for(i=0;i= vstack + (VSTACK_SIZE - 1)) +- error("memory full"); ++ tcc_error(st, "memory full"); + /* cannot let cpu flags if other instruction are generated. Also + avoid leaving VT_JMP anywhere except on the top of the stack + because it would complicate the code generator. */ + if (vtop >= vstack) { + v = vtop->r & VT_VALMASK; + if (v == VT_CMP || (v & ~1) == VT_JMP) +- gv(RC_INT); ++ gv(st, RC_INT); + } + vtop++; + vtop->type = *type; +@@ -4441,47 +3605,47 @@ + } + + /* push integer constant */ +-void vpushi(int v) ++void vpushi(TCCState *st, int v) + { + CValue cval; + cval.i = v; +- vsetc(&int_type, VT_CONST, &cval); ++ vsetc(st, &int_type, VT_CONST, &cval); + } + + /* Return a static symbol pointing to a section */ +-static Sym *get_sym_ref(CType *type, Section *sec, ++static Sym *get_sym_ref(TCCState *st, CType *type, Section *sec, + unsigned long offset, unsigned long size) + { + int v; + Sym *sym; + + v = anon_sym++; +- sym = global_identifier_push(v, type->t | VT_STATIC, 0); ++ sym = global_identifier_push(st, v, type->t | VT_STATIC, 0); + sym->type.ref = type->ref; + sym->r = VT_CONST | VT_SYM; +- put_extern_sym(sym, sec, offset, size); ++ put_extern_sym(st, sym, sec, offset, size); + return sym; + } + + /* push a reference to a section offset by adding a dummy symbol */ +-static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) ++static void vpush_ref(TCCState *s, CType *type, Section *sec, unsigned long offset, unsigned long size) + { + CValue cval; + + cval.ul = 0; +- vsetc(type, VT_CONST | VT_SYM, &cval); +- vtop->sym = get_sym_ref(type, sec, offset, size); ++ vsetc(s, type, VT_CONST | VT_SYM, &cval); ++ vtop->sym = get_sym_ref(s, type, sec, offset, size); + } + + /* define a new external reference to a symbol 'v' of type 'u' */ +-static Sym *external_global_sym(int v, CType *type, int r) ++static Sym *external_global_sym(TCCState * st, int v, CType *type, int r) + { + Sym *s; + +- s = sym_find(v); ++ s = sym_find(st, v); + if (!s) { + /* push forward reference */ +- s = global_identifier_push(v, type->t | VT_EXTERN, 0); ++ s = global_identifier_push(st, v, type->t | VT_EXTERN, 0); + s->type.ref = type->ref; + s->r = r | VT_CONST | VT_SYM; + } +@@ -4489,51 +3653,51 @@ + } + + /* define a new external reference to a symbol 'v' of type 'u' */ +-static Sym *external_sym(int v, CType *type, int r) ++static Sym *external_sym(TCCState *st, int v, CType *type, int r) + { + Sym *s; + +- s = sym_find(v); ++ s = sym_find(st, v); + if (!s) { + /* push forward reference */ +- s = sym_push(v, type, r | VT_CONST | VT_SYM, 0); ++ s = sym_push(st, v, type, r | VT_CONST | VT_SYM, 0); + s->type.t |= VT_EXTERN; + } else { +- if (!is_compatible_types(&s->type, type)) +- error("incompatible types for redefinition of '%s'", +- get_tok_str(v, NULL)); ++ if (!is_compatible_types(st, &s->type, type)) ++ tcc_error(st, "incompatible types for redefinition of '%s'", ++ get_tok_str(st, v, NULL)); + } + return s; + } + + /* push a reference to global symbol v */ +-static void vpush_global_sym(CType *type, int v) ++static void vpush_global_sym(TCCState *st, CType *type, int v) + { + Sym *sym; + CValue cval; + +- sym = external_global_sym(v, type, 0); ++ sym = external_global_sym(st, v, type, 0); + cval.ul = 0; +- vsetc(type, VT_CONST | VT_SYM, &cval); ++ vsetc(st, type, VT_CONST | VT_SYM, &cval); + vtop->sym = sym; + } + +-void vset(CType *type, int r, int v) ++void vset(TCCState *st, CType *type, int r, int v) + { + CValue cval; + + cval.i = v; +- vsetc(type, r, &cval); ++ vsetc(st, type, r, &cval); + } + +-void vseti(int r, int v) ++void vseti(TCCState *st, int r, int v) + { + CType type; + type.t = VT_INT; +- vset(&type, r, v); ++ vset(st, &type, r, v); + } + +-void vswap(void) ++void vswap(TCCState *st) + { + SValue tmp; + +@@ -4542,21 +3706,21 @@ + vtop[-1] = tmp; + } + +-void vpushv(SValue *v) ++void vpushv(TCCState *st, SValue *v) + { + if (vtop >= vstack + (VSTACK_SIZE - 1)) +- error("memory full"); ++ tcc_error(st, "memory full"); + vtop++; + *vtop = *v; + } + +-void vdup(void) ++void vdup(TCCState *st) + { +- vpushv(vtop); ++ vpushv(st, vtop); + } + + /* save r to the memory stack, and mark it as being free */ +-void save_reg(int r) ++void save_reg(TCCState *st, int r) + { + int l, saved, size, align; + SValue *p, sv; +@@ -4567,7 +3731,8 @@ + l = 0; + for(p=vstack;p<=vtop;p++) { + if ((p->r & VT_VALMASK) == r || +- (p->r2 & VT_VALMASK) == r) { ++ ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) ++ { + /* must save value on stack if not already done */ + if (!saved) { + /* NOTE: must reload 'r' because r might be equal to r2 */ +@@ -4575,24 +3740,24 @@ + /* store register in the stack */ + type = &p->type; + if ((p->r & VT_LVAL) || +- (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG)) ++ (!is_float(st, type->t) && (type->t & VT_BTYPE) != VT_LLONG)) + type = &int_type; +- size = type_size(type, &align); ++ size = type_size(st, type, &align); + loc = (loc - size) & -align; + sv.type.t = type->t; + sv.r = VT_LOCAL | VT_LVAL; + sv.c.ul = loc; +- store(r, &sv); ++ store(st, r, &sv); + #ifdef TCC_TARGET_I386 + /* x86 specific: need to pop fp register ST0 if saved */ + if (r == TREG_ST0) { +- o(0xd9dd); /* fstp %st(1) */ ++ o(st, 0xd9dd); /* fstp %st(1) */ + } + #endif + /* special long long case */ + if ((type->t & VT_BTYPE) == VT_LLONG) { + sv.c.ul += 4; +- store(p->r2, &sv); ++ store(st, p->r2, &sv); + } + l = loc; + saved = 1; +@@ -4604,7 +3769,7 @@ + p->c.ul */ + p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL; + } else { +- p->r = lvalue_type(p->type.t) | VT_LOCAL; ++ p->r = lvalue_type(st, p->type.t) | VT_LOCAL; + } + p->r2 = VT_CONST; + p->c.ul = l; +@@ -4614,7 +3779,7 @@ + + /* find a register of class 'rc2' with at most one reference on stack. + * If none, call get_reg(rc) */ +-int get_reg_ex(int rc, int rc2) ++int get_reg_ex(TCCState *st, int rc, int rc2) + { + int r; + SValue *p; +@@ -4632,11 +3797,11 @@ + return r; + } + } +- return get_reg(rc); ++ return get_reg(st, rc); + } + + /* find a free register of class 'rc'. If none, save one register */ +-int get_reg(int rc) ++int get_reg(TCCState *st, int rc) + { + int r; + SValue *p; +@@ -4665,7 +3830,7 @@ + r = p->r2 & VT_VALMASK; + if (r < VT_CONST && (reg_classes[r] & rc)) { + save_found: +- save_reg(r); ++ save_reg(st, r); + return r; + } + } +@@ -4674,7 +3839,7 @@ + } + + /* save registers up to (vtop - n) stack entry */ +-void save_regs(int n) ++void save_regs(TCCState *st, int n) + { + int r; + SValue *p, *p1; +@@ -4682,28 +3847,28 @@ + for(p = vstack;p <= p1; p++) { + r = p->r & VT_VALMASK; + if (r < VT_CONST) { +- save_reg(r); ++ save_reg(st, r); + } + } + } + + /* move register 's' to 'r', and flush previous value of r to memory + if needed */ +-void move_reg(int r, int s) ++void move_reg(TCCState *st, int r, int s) + { + SValue sv; + + if (r != s) { +- save_reg(r); ++ save_reg(st, r); + sv.type.t = VT_INT; + sv.r = s; + sv.c.ul = 0; +- load(r, &sv); ++ load(st, r, &sv); + } + } + + /* get address of vtop (vtop MUST BE an lvalue) */ +-void gaddrof(void) ++void gaddrof(TCCState *st) + { + vtop->r &= ~VT_LVAL; + /* tricky: if saved lvalue, then we can go back to lvalue */ +@@ -4711,9 +3876,9 @@ + vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL; + } + +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + /* generate lvalue bound code */ +-void gbound(void) ++void gbound(TCCState *st) + { + int lval_type; + CType type1; +@@ -4727,14 +3892,14 @@ + /* must save type because we must set it to int to get pointer */ + type1 = vtop->type; + vtop->type.t = VT_INT; +- gaddrof(); +- vpushi(0); +- gen_bounded_ptr_add(); ++ gaddrof(st ); ++ vpushi(st, 0); ++ gen_bounded_ptr_add(st); + vtop->r |= lval_type; + vtop->type = type1; + } + /* then check for dereferencing */ +- gen_bounded_ptr_deref(); ++ gen_bounded_ptr_deref(st); + } + } + #endif +@@ -4742,7 +3907,7 @@ + /* store vtop a register belonging to class 'rc'. lvalues are + converted to values. Cannot be used if cannot be converted to + register value (such as structures). */ +-int gv(int rc) ++int gv(TCCState *st, int rc) + { + int r, r2, rc2, bit_pos, bit_size, size, align, i; + unsigned long long ll; +@@ -4754,38 +3919,55 @@ + /* remove bit field info to avoid loops */ + vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); + /* generate shifts */ +- vpushi(32 - (bit_pos + bit_size)); +- gen_op(TOK_SHL); +- vpushi(32 - bit_size); ++ vpushi(st, 32 - (bit_pos + bit_size)); ++ gen_op(st, TOK_SHL); ++ vpushi(st, 32 - bit_size); + /* NOTE: transformed to SHR if unsigned */ +- gen_op(TOK_SAR); +- r = gv(rc); ++ gen_op(st, TOK_SAR); ++ r = gv(st, rc); + } else { +- if (is_float(vtop->type.t) && ++ if (is_float(st, vtop->type.t) && + (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { + Sym *sym; + int *ptr; + unsigned long offset; ++#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) ++ CValue check; ++#endif + + /* XXX: unify with initializers handling ? */ + /* CPUs usually cannot use float constants, so we store them + generically in data segment */ +- size = type_size(&vtop->type, &align); ++ size = type_size(st, &vtop->type, &align); + offset = (data_section->data_offset + align - 1) & -align; + data_section->data_offset = offset; + /* XXX: not portable yet */ +- ptr = section_ptr_add(data_section, size); ++#ifdef __i386__ ++ /* long doubles are defined to be 96 bit wide by ++ the i386 ABI but the x87 only uses the first 80. The rest ++ is filled with garbage by now, so clear it before writing */ ++ if(size == 12) ++ vtop->c.tab[2] &= 0xffff; ++#endif ++ ptr = section_ptr_add(st, data_section, size); + size = size >> 2; ++#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) ++ check.d = 1; ++ if(check.tab[0]) ++ for(i=0;ic.tab[size-1-i]; ++ else ++#endif + for(i=0;ic.tab[i]; +- sym = get_sym_ref(&vtop->type, data_section, offset, size << 2); ++ sym = get_sym_ref(st, &vtop->type, data_section, offset, size << 2); + vtop->r |= VT_LVAL | VT_SYM; + vtop->sym = sym; + vtop->c.ul = 0; + } +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + if (vtop->r & VT_MUSTBOUND) +- gbound(); ++ gbound(st ); + #endif + + r = vtop->r & VT_VALMASK; +@@ -4798,7 +3980,7 @@ + !(reg_classes[r] & rc) || + ((vtop->type.t & VT_BTYPE) == VT_LLONG && + !(reg_classes[vtop->r2] & rc))) { +- r = get_reg(rc); ++ r = get_reg(st, rc); + if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { + /* two register type load : expand to two words + temporarily */ +@@ -4806,30 +3988,30 @@ + /* load constant */ + ll = vtop->c.ull; + vtop->c.ui = ll; /* first word */ +- load(r, vtop); ++ load(st, r, vtop); + vtop->r = r; /* save register value */ +- vpushi(ll >> 32); /* second word */ ++ vpushi(st, ll >> 32); /* second word */ + } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */ + (vtop->r & VT_LVAL)) { + /* We do not want to modifier the long long + pointer here, so the safest (and less + efficient) is to save all the other registers + in the stack. XXX: totally inefficient. */ +- save_regs(1); ++ save_regs(st, 1); + /* load from memory */ +- load(r, vtop); +- vdup(); ++ load(st, r, vtop); ++ vdup(st); + vtop[-1].r = r; /* save register value */ + /* increment pointer to get second word */ + vtop->type.t = VT_INT; +- gaddrof(); +- vpushi(4); +- gen_op('+'); ++ gaddrof(st); ++ vpushi(st, 4); ++ gen_op(st, '+'); + vtop->r |= VT_LVAL; + } else { + /* move registers */ +- load(r, vtop); +- vdup(); ++ load(st, r, vtop); ++ vdup(st ); + vtop[-1].r = r; /* save register value */ + vtop->r = vtop[-1].r2; + } +@@ -4837,12 +4019,12 @@ + rc2 = RC_INT; + if (rc == RC_IRET) + rc2 = RC_LRET; +- r2 = get_reg(rc2); +- load(r2, vtop); +- vpop(); ++ r2 = get_reg(st, rc2); ++ load(st, r2, vtop); ++ vpop(st); + /* write second register */ + vtop->r2 = r2; +- } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) { ++ } else if ((vtop->r & VT_LVAL) && !is_float(st, vtop->type.t)) { + int t1, t; + /* lvalue of scalar type : need to use lvalue type + because of possible cast */ +@@ -4856,12 +4038,12 @@ + if (vtop->r & VT_LVAL_UNSIGNED) + t |= VT_UNSIGNED; + vtop->type.t = t; +- load(r, vtop); ++ load(st, r, vtop); + /* restore wanted type */ + vtop->type.t = t1; + } else { + /* one register type load */ +- load(r, vtop); ++ load(st, r, vtop); + } + } + vtop->r = r; +@@ -4875,7 +4057,7 @@ + } + + /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */ +-void gv2(int rc1, int rc2) ++void gv2(TCCState *st, int rc1, int rc2) + { + int v; + +@@ -4884,36 +4066,36 @@ + reload errors */ + v = vtop[0].r & VT_VALMASK; + if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) { +- vswap(); +- gv(rc1); +- vswap(); +- gv(rc2); ++ vswap(st); ++ gv(st, rc1); ++ vswap(st); ++ gv(st, rc2); + /* test if reload is needed for first register */ + if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) { +- vswap(); +- gv(rc1); +- vswap(); ++ vswap(st); ++ gv(st, rc1); ++ vswap(st); + } + } else { +- gv(rc2); +- vswap(); +- gv(rc1); +- vswap(); ++ gv(st, rc2); ++ vswap(st); ++ gv(st, rc1); ++ vswap(st); + /* test if reload is needed for first register */ + if ((vtop[0].r & VT_VALMASK) >= VT_CONST) { +- gv(rc2); ++ gv(st, rc2); + } + } + } + + /* expand long long on stack in two int registers */ +-void lexpand(void) ++void lexpand(TCCState *st) + { + int u; + + u = vtop->type.t & VT_UNSIGNED; +- gv(RC_INT); +- vdup(); ++ gv(st, RC_INT); ++ vdup(st); + vtop[0].r = vtop[-1].r2; + vtop[0].r2 = VT_CONST; + vtop[-1].r2 = VT_CONST; +@@ -4928,7 +4110,7 @@ + int u,v; + + u = vtop->type.t & VT_UNSIGNED; +- vdup(); ++ vdup(st); + vtop->r2 = VT_CONST; + vtop->type.t = VT_INT | u; + v=vtop[-1].r & (VT_VALMASK | VT_LVAL); +@@ -4941,7 +4123,7 @@ + vtop->r = vtop[-1].r; + } else if (v > VT_CONST) { + vtop--; +- lexpand(); ++ lexpand(st); + } else + vtop->r = vtop[-1].r2; + vtop[-1].r2 = VT_CONST; +@@ -4950,18 +4132,18 @@ + #endif + + /* build a long long from two ints */ +-void lbuild(int t) ++void lbuild(TCCState *st, int t) + { +- gv2(RC_INT, RC_INT); ++ gv2(st, RC_INT, RC_INT); + vtop[-1].r2 = vtop[0].r; + vtop[-1].type.t = t; +- vpop(); ++ vpop(st); + } + + /* rotate n first stack elements to the bottom + I1 ... In -> I2 ... In I1 [top is right] + */ +-void vrotb(int n) ++void vrotb(TCCState *s, int n) + { + int i; + SValue tmp; +@@ -4975,7 +4157,7 @@ + /* rotate n first stack elements to the top + I1 ... In -> In I1 ... I(n-1) [top is right] + */ +-void vrott(int n) ++void vrott(TCCState *s, int n) + { + int i; + SValue tmp; +@@ -4990,7 +4172,7 @@ + /* like vrott but in other direction + In ... I1 -> I(n-1) ... I1 In [top is right] + */ +-void vnrott(int n) ++void vnrott(TCCState *s, int n) + { + int i; + SValue tmp; +@@ -5003,14 +4185,14 @@ + #endif + + /* pop stack value */ +-void vpop(void) ++void vpop(TCCState *st) + { + int v; + v = vtop->r & VT_VALMASK; + #ifdef TCC_TARGET_I386 + /* for x86, we need to pop the FP stack */ +- if (v == TREG_ST0 && !nocode_wanted) { +- o(0xd9dd); /* fstp %st(1) */ ++ if (v == TREG_ST0) { ++ o(st, 0xd9dd); /* fstp %st(1) */ + } else + #endif + if (v == VT_JMP || v == VT_JMPI) { +@@ -5022,47 +4204,47 @@ + + /* convert stack entry to register and duplicate its value in another + register */ +-void gv_dup(void) ++void gv_dup(TCCState *st) + { + int rc, t, r, r1; + SValue sv; + + t = vtop->type.t; + if ((t & VT_BTYPE) == VT_LLONG) { +- lexpand(); +- gv_dup(); +- vswap(); +- vrotb(3); +- gv_dup(); +- vrotb(4); ++ lexpand(st); ++ gv_dup(st); ++ vswap(st); ++ vrotb(st, 3); ++ gv_dup(st); ++ vrotb(st, 4); + /* stack: H L L1 H1 */ +- lbuild(t); +- vrotb(3); +- vrotb(3); +- vswap(); +- lbuild(t); +- vswap(); ++ lbuild(st, t); ++ vrotb(st, 3); ++ vrotb(st, 3); ++ vswap(st); ++ lbuild(st, t); ++ vswap(st); + } else { + /* duplicate value */ + rc = RC_INT; + sv.type.t = VT_INT; +- if (is_float(t)) { ++ if (is_float(st, t)) { + rc = RC_FLOAT; + sv.type.t = t; + } +- r = gv(rc); +- r1 = get_reg(rc); ++ r = gv(st, rc); ++ r1 = get_reg(st, rc); + sv.r = r; + sv.c.ul = 0; +- load(r1, &sv); /* move r to r1 */ +- vdup(); ++ load(st, r1, &sv); /* move r to r1 */ ++ vdup(st); + /* duplicates value */ + vtop->r = r1; + } + } + + /* generate CPU independent (unsigned) long long operations */ +-void gen_opl(int op) ++void gen_opl(TCCState *st, int op) + { + int t, a, b, op1, c, i; + int func; +@@ -5083,10 +4265,10 @@ + func = TOK___umoddi3; + gen_func: + /* call generic long long function */ +- vpush_global_sym(&func_old_type, func); +- vrott(3); +- gfunc_call(2); +- vpushi(0); ++ vpush_global_sym(st, &func_old_type, func); ++ vrott(st, 3); ++ gfunc_call(st, 2); ++ vpushi(st, 0); + vtop->r = REG_IRET; + vtop->r2 = REG_LRET; + break; +@@ -5097,10 +4279,10 @@ + case '+': + case '-': + t = vtop->type.t; +- vswap(); +- lexpand(); +- vrotb(3); +- lexpand(); ++ vswap(st); ++ lexpand(st); ++ vrotb(st, 3); ++ lexpand(st); + /* stack: L1 H1 L2 H2 */ + tmp = vtop[0]; + vtop[0] = vtop[-3]; +@@ -5108,106 +4290,106 @@ + tmp = vtop[-2]; + vtop[-2] = vtop[-3]; + vtop[-3] = tmp; +- vswap(); ++ vswap(st); + /* stack: H1 H2 L1 L2 */ + if (op == '*') { +- vpushv(vtop - 1); +- vpushv(vtop - 1); +- gen_op(TOK_UMULL); +- lexpand(); ++ vpushv(st, vtop - 1); ++ vpushv(st, vtop - 1); ++ gen_op(st, TOK_UMULL); ++ lexpand(st); + /* stack: H1 H2 L1 L2 ML MH */ + for(i=0;i<4;i++) +- vrotb(6); ++ vrotb(st, 6); + /* stack: ML MH H1 H2 L1 L2 */ + tmp = vtop[0]; + vtop[0] = vtop[-2]; + vtop[-2] = tmp; + /* stack: ML MH H1 L2 H2 L1 */ +- gen_op('*'); +- vrotb(3); +- vrotb(3); +- gen_op('*'); ++ gen_op(st, '*'); ++ vrotb(st, 3); ++ vrotb(st, 3); ++ gen_op(st, '*'); + /* stack: ML MH M1 M2 */ +- gen_op('+'); +- gen_op('+'); ++ gen_op(st, '+'); ++ gen_op(st, '+'); + } else if (op == '+' || op == '-') { + /* XXX: add non carry method too (for MIPS or alpha) */ + if (op == '+') + op1 = TOK_ADDC1; + else + op1 = TOK_SUBC1; +- gen_op(op1); ++ gen_op(st, op1); + /* stack: H1 H2 (L1 op L2) */ +- vrotb(3); +- vrotb(3); +- gen_op(op1 + 1); /* TOK_xxxC2 */ ++ vrotb(st, 3); ++ vrotb(st, 3); ++ gen_op(st, op1 + 1); /* TOK_xxxC2 */ + } else { +- gen_op(op); ++ gen_op(st, op); + /* stack: H1 H2 (L1 op L2) */ +- vrotb(3); +- vrotb(3); ++ vrotb(st, 3); ++ vrotb(st, 3); + /* stack: (L1 op L2) H1 H2 */ +- gen_op(op); ++ gen_op(st, op); + /* stack: (L1 op L2) (H1 op H2) */ + } + /* stack: L H */ +- lbuild(t); ++ lbuild(st, t); + break; + case TOK_SAR: + case TOK_SHR: + case TOK_SHL: + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + t = vtop[-1].type.t; +- vswap(); +- lexpand(); +- vrotb(3); ++ vswap(st); ++ lexpand(st); ++ vrotb(st, 3); + /* stack: L H shift */ + c = (int)vtop->c.i; + /* constant: simpler */ + /* NOTE: all comments are for SHL. the other cases are + done by swaping words */ +- vpop(); ++ vpop(st); + if (op != TOK_SHL) +- vswap(); ++ vswap(st); + if (c >= 32) { + /* stack: L H */ +- vpop(); ++ vpop(st); + if (c > 32) { +- vpushi(c - 32); +- gen_op(op); ++ vpushi(st, c - 32); ++ gen_op(st, op); + } + if (op != TOK_SAR) { +- vpushi(0); ++ vpushi(st, 0); + } else { +- gv_dup(); +- vpushi(31); +- gen_op(TOK_SAR); ++ gv_dup(st); ++ vpushi(st, 31); ++ gen_op(st, TOK_SAR); + } +- vswap(); ++ vswap(st); + } else { +- vswap(); +- gv_dup(); ++ vswap(st); ++ gv_dup(st); + /* stack: H L L */ +- vpushi(c); +- gen_op(op); +- vswap(); +- vpushi(32 - c); ++ vpushi(st, c); ++ gen_op(st, op); ++ vswap(st); ++ vpushi(st, 32 - c); + if (op == TOK_SHL) +- gen_op(TOK_SHR); ++ gen_op(st, TOK_SHR); + else +- gen_op(TOK_SHL); +- vrotb(3); ++ gen_op(st, TOK_SHL); ++ vrotb(st, 3); + /* stack: L L H */ +- vpushi(c); ++ vpushi(st, c); + if (op == TOK_SHL) +- gen_op(TOK_SHL); ++ gen_op(st, TOK_SHL); + else +- gen_op(TOK_SHR); +- gen_op('|'); ++ gen_op(st, TOK_SHR); ++ gen_op(st, '|'); + } + if (op != TOK_SHL) +- vswap(); +- lbuild(t); ++ vswap(st); ++ lbuild(st, t); + } else { + /* XXX: should provide a faster fallback on x86 ? */ + switch(op) { +@@ -5226,10 +4408,10 @@ + default: + /* compare operations */ + t = vtop->type.t; +- vswap(); +- lexpand(); +- vrotb(3); +- lexpand(); ++ vswap(st); ++ lexpand(st); ++ vrotb(st, 3); ++ lexpand(st); + /* stack: L1 H1 L2 H2 */ + tmp = vtop[-1]; + vtop[-1] = vtop[-2]; +@@ -5249,23 +4431,23 @@ + op1 = TOK_UGE; + a = 0; + b = 0; +- gen_op(op1); ++ gen_op(st, op1); + if (op1 != TOK_NE) { +- a = gtst(1, 0); ++ a = gtst(st, 1, 0); + } + if (op != TOK_EQ) { + /* generate non equal test */ + /* XXX: NOT PORTABLE yet */ + if (a == 0) { +- b = gtst(0, 0); ++ b = gtst(st, 0, 0); + } else { + #if defined(TCC_TARGET_I386) +- b = psym(0x850f, 0); ++ b = psym(st, 0x850f, 0); + #elif defined(TCC_TARGET_ARM) + b = ind; +- o(0x1A000000 | encbranch(ind, 0, 1)); ++ o(st, 0x1A000000 | encbranch(ind, 0, 1)); + #elif defined(TCC_TARGET_C67) +- error("not implemented"); ++ tcc_error("not implemented"); + #else + #error not supported + #endif +@@ -5281,35 +4463,43 @@ + op1 = TOK_UGT; + else if (op1 == TOK_GE) + op1 = TOK_UGE; +- gen_op(op1); +- a = gtst(1, a); ++ gen_op(st, op1); ++ a = gtst(st, 1, a); + gsym(b); +- vseti(VT_JMPI, a); ++ vseti(st, VT_JMPI, a); + break; + } + } + +-/* handle integer constant optimizations and various machine +- independent opt */ +-void gen_opic(int op) ++/* handle long long constant and various machine independent optimizations */ ++void gen_opic(TCCState *st, int op) + { +- int fc, c1, c2, n; ++ int c1, c2, t1, t2; + SValue *v1, *v2; ++ long long l1, l2; + + v1 = vtop - 1; + v2 = vtop; +- /* currently, we cannot do computations with forward symbols */ +- c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; +- c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; ++ t1 = v1->type.t & VT_BTYPE; ++ t2 = v2->type.t & VT_BTYPE; ++ l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i; ++ l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i; ++ ++ /* For forward symbols we can only constify &&, || or == NULL */ ++ c2 = VT_SYM; ++ if (op == TOK_EQ && (v1->c.ll == 0 || v2->c.ll == 0)) c2 = 0; ++ if (op == TOK_LAND || op == TOK_LOR) c2 = 0; ++ c1 = (v1->r & (VT_VALMASK | VT_LVAL | c2)) == VT_CONST; ++ c2 = (v2->r & (VT_VALMASK | VT_LVAL | c2)) == VT_CONST; ++ + if (c1 && c2) { +- fc = v2->c.i; + switch(op) { +- case '+': v1->c.i += fc; break; +- case '-': v1->c.i -= fc; break; +- case '&': v1->c.i &= fc; break; +- case '^': v1->c.i ^= fc; break; +- case '|': v1->c.i |= fc; break; +- case '*': v1->c.i *= fc; break; ++ case '+': l1 += l2; break; ++ case '-': l1 -= l2; break; ++ case '&': l1 &= l2; break; ++ case '^': l1 ^= l2; break; ++ case '|': l1 |= l2; break; ++ case '*': l1 *= l2; break; + + case TOK_PDIV: + case '/': +@@ -5317,66 +4507,68 @@ + case TOK_UDIV: + case TOK_UMOD: + /* if division by zero, generate explicit division */ +- if (fc == 0) { ++ if (l2 == 0) { + if (const_wanted) +- error("division by zero in constant"); ++ tcc_error(st, "division by zero in constant"); + goto general_case; + } + switch(op) { +- default: v1->c.i /= fc; break; +- case '%': v1->c.i %= fc; break; +- case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break; +- case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break; ++ default: l1 /= l2; break; ++ case '%': l1 %= l2; break; ++ case TOK_UDIV: l1 = (unsigned long long)l1 / l2; break; ++ case TOK_UMOD: l1 = (unsigned long long)l1 % l2; break; + } + break; +- case TOK_SHL: v1->c.i <<= fc; break; +- case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break; +- case TOK_SAR: v1->c.i >>= fc; break; ++ case TOK_SHL: l1 <<= l2; break; ++ case TOK_SHR: l1 = (unsigned long long)l1 >> l2; break; ++ case TOK_SAR: l1 >>= l2; break; + /* tests */ +- case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break; +- case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break; +- case TOK_EQ: v1->c.i = v1->c.i == fc; break; +- case TOK_NE: v1->c.i = v1->c.i != fc; break; +- case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break; +- case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break; +- case TOK_LT: v1->c.i = v1->c.i < fc; break; +- case TOK_GE: v1->c.i = v1->c.i >= fc; break; +- case TOK_LE: v1->c.i = v1->c.i <= fc; break; +- case TOK_GT: v1->c.i = v1->c.i > fc; break; ++ case TOK_ULT: l1 = (unsigned long long)l1 < (unsigned long long)l2; break; ++ case TOK_UGE: l1 = (unsigned long long)l1 >= (unsigned long long)l2; break; ++ case TOK_EQ: l1 = l1 == l2; break; ++ case TOK_NE: l1 = l1 != l2; break; ++ case TOK_ULE: l1 = (unsigned long long)l1 <= (unsigned long long)l2; break; ++ case TOK_UGT: l1 = (unsigned long long)l1 > (unsigned long long)l2; break; ++ case TOK_LT: l1 = l1 < l2; break; ++ case TOK_GE: l1 = l1 >= l2; break; ++ case TOK_LE: l1 = l1 <= l2; break; ++ case TOK_GT: l1 = l1 > l2; break; + /* logical */ +- case TOK_LAND: v1->c.i = v1->c.i && fc; break; +- case TOK_LOR: v1->c.i = v1->c.i || fc; break; ++ case TOK_LAND: l1 = l1 && l2; break; ++ case TOK_LOR: l1 = l1 || l2; break; + default: + goto general_case; + } ++ v1->c.ll = l1; + vtop--; + } else { + /* if commutative ops, put c2 as constant */ + if (c1 && (op == '+' || op == '&' || op == '^' || + op == '|' || op == '*')) { +- vswap(); ++ vswap(st); + swap(&c1, &c2); ++ l2 = l1; + } +- fc = vtop->c.i; ++ /* Filter out NOP operations like x*1, x-0, x&-1... */ + if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV || + op == TOK_PDIV) && +- fc == 1) || ++ l2 == 1) || + ((op == '+' || op == '-' || op == '|' || op == '^' || + op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && +- fc == 0) || ++ l2 == 0) || + (op == '&' && +- fc == -1))) { ++ l2 == -1))) { + /* nothing to do */ + vtop--; + } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { + /* try to use shifts instead of muls or divs */ +- if (fc > 0 && (fc & (fc - 1)) == 0) { +- n = -1; +- while (fc) { +- fc >>= 1; ++ if (l2 > 0 && (l2 & (l2 - 1)) == 0) { ++ int n = -1; ++ while (l2) { ++ l2 >>= 1; + n++; + } +- vtop->c.i = n; ++ vtop->c.ll = n; + if (op == '*') + op = TOK_SHL; + else if (op == TOK_PDIV) +@@ -5390,23 +4582,22 @@ + (VT_CONST | VT_SYM)) { + /* symbol + constant case */ + if (op == '-') +- fc = -fc; ++ l2 = -l2; + vtop--; +- vtop->c.i += fc; ++ vtop->c.ll += l2; + } else { + general_case: +- if (!nocode_wanted) { + /* call low level op generator */ +- gen_opi(op); +- } else { +- vtop--; +- } ++ if (cur_text_section) { ++ if (t1 == VT_LLONG|| t2 == VT_LLONG) gen_opl(st, op); ++ else gen_opi(st, op); ++ } else vtop--; + } + } + } + + /* generate a floating point operation with constant propagation */ +-void gen_opif(int op) ++void gen_opif(TCCState *st, int op) + { + int c1, c2; + SValue *v1, *v2; +@@ -5431,7 +4622,7 @@ + + /* NOTE: we only do constant propagation if finite number (not + NaN or infinity) (ANSI spec) */ +- if (!ieee_finite(f1) || !ieee_finite(f2)) ++ if (!ieee_finite(st, f1) || !ieee_finite(st, f2)) + goto general_case; + + switch(op) { +@@ -5441,7 +4632,7 @@ + case '/': + if (f2 == 0.0) { + if (const_wanted) +- error("division by zero in constant"); ++ tcc_error(st, "division by zero in constant"); + goto general_case; + } + f1 /= f2; +@@ -5461,21 +4652,18 @@ + vtop--; + } else { + general_case: +- if (!nocode_wanted) { +- gen_opf(op); +- } else { +- vtop--; +- } ++ if (cur_text_section) gen_opf(st, op); ++ else vtop--; + } + } + +-static int pointed_size(CType *type) ++static int pointed_size(TCCState *st, CType *type) + { + int align; +- return type_size(pointed_type(type), &align); ++ return type_size(st, pointed_type(st, type), &align); + } + +-static inline int is_null_pointer(SValue *p) ++static inline int is_null_pointer(TCCState *st, SValue *p) + { + if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + return 0; +@@ -5483,42 +4671,43 @@ + ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0); + } + +-static inline int is_integer_btype(int bt) ++static inline int is_integer_btype(TCCState *st, int bt) + { + return (bt == VT_BYTE || bt == VT_SHORT || + bt == VT_INT || bt == VT_LLONG); + } + + /* check types for comparison or substraction of pointers */ +-static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) ++static void check_comparison_pointer_types(TCCState *st, SValue *p1, SValue *p2, int op) + { + CType *type1, *type2, tmp_type1, tmp_type2; + int bt1, bt2; + + /* null pointers are accepted for all comparisons as gcc */ +- if (is_null_pointer(p1) || is_null_pointer(p2)) ++ if (is_null_pointer(st, p1) || is_null_pointer(st, p2)) + return; + type1 = &p1->type; + type2 = &p2->type; + bt1 = type1->t & VT_BTYPE; + bt2 = type2->t & VT_BTYPE; + /* accept comparison between pointer and integer with a warning */ +- if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') { +- warning("comparison between pointer and integer"); ++ if ((is_integer_btype(st, bt1) || is_integer_btype(st, bt2)) && op != '-') { ++ if (op != TOK_LOR && op != TOK_LAND ) ++ warning(st, "comparison between pointer and integer"); + return; + } + + /* both must be pointers or implicit function pointers */ + if (bt1 == VT_PTR) { +- type1 = pointed_type(type1); ++ type1 = pointed_type(st, type1); + } else if (bt1 != VT_FUNC) + goto invalid_operands; + + if (bt2 == VT_PTR) { +- type2 = pointed_type(type2); ++ type2 = pointed_type(st, type2); + } else if (bt2 != VT_FUNC) { + invalid_operands: +- error("invalid operands to binary %s", get_tok_str(op, NULL)); ++ tcc_error(st, "invalid operands to binary %s", get_tok_str(st, op, NULL)); + } + if ((type1->t & VT_BTYPE) == VT_VOID || + (type2->t & VT_BTYPE) == VT_VOID) +@@ -5527,17 +4716,17 @@ + tmp_type2 = *type2; + tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); + tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); +- if (!is_compatible_types(&tmp_type1, &tmp_type2)) { ++ if (!is_compatible_types(st, &tmp_type1, &tmp_type2)) { + /* gcc-like error if '-' is used */ + if (op == '-') + goto invalid_operands; + else +- warning("comparison of distinct pointer types lacks a cast"); ++ warning(st, "comparison of distinct pointer types lacks a cast"); + } + } + + /* generic gen_op: handles types problems */ +-void gen_op(int op) ++void gen_op(TCCState *st, int op) + { + int u, t1, t2, bt1, bt2, t; + CType type1; +@@ -5550,8 +4739,8 @@ + if (bt1 == VT_PTR || bt2 == VT_PTR) { + /* at least one operand is a pointer */ + /* relationnal op: must be both pointers */ +- if (op >= TOK_ULT && op <= TOK_GT) { +- check_comparison_pointer_types(vtop - 1, vtop, op); ++ if (op >= TOK_ULT && op <= TOK_LOR) { ++ check_comparison_pointer_types(st, vtop - 1, vtop, op); + /* pointers are handled are unsigned */ + t = VT_INT | VT_UNSIGNED; + goto std_op; +@@ -5559,49 +4748,49 @@ + /* if both pointers, then it must be the '-' op */ + if (bt1 == VT_PTR && bt2 == VT_PTR) { + if (op != '-') +- error("cannot use pointers here"); +- check_comparison_pointer_types(vtop - 1, vtop, op); ++ tcc_error(st, "cannot use pointers here"); ++ check_comparison_pointer_types(st, vtop - 1, vtop, op); + /* XXX: check that types are compatible */ +- u = pointed_size(&vtop[-1].type); +- gen_opic(op); ++ u = pointed_size(st, &vtop[-1].type); ++ gen_opic(st, op); + /* set to integer type */ + vtop->type.t = VT_INT; +- vpushi(u); +- gen_op(TOK_PDIV); ++ vpushi(st, u); ++ gen_op(st, TOK_PDIV); + } else { + /* exactly one pointer : must be '+' or '-'. */ + if (op != '-' && op != '+') +- error("cannot use pointers here"); ++ tcc_error(st, "cannot use pointers here"); + /* Put pointer as first operand */ + if (bt2 == VT_PTR) { +- vswap(); ++ vswap(st); + swap(&t1, &t2); + } + type1 = vtop[-1].type; + /* XXX: cast to int ? (long long case) */ +- vpushi(pointed_size(&vtop[-1].type)); +- gen_op('*'); +-#ifdef CONFIG_TCC_BCHECK ++ vpushi(st, pointed_size(st, &vtop[-1].type)); ++ gen_op(st, '*'); ++#if 0 + /* if evaluating constant expression, no code should be + generated, so no bound check */ + if (do_bounds_check && !const_wanted) { + /* if bounded pointers, we generate a special code to + test bounds */ + if (op == '-') { +- vpushi(0); +- vswap(); +- gen_op('-'); ++ vpushi(st, 0); ++ vswap(st); ++ gen_op(st, '-'); + } +- gen_bounded_ptr_add(); ++ gen_bounded_ptr_add(st); + } else + #endif + { +- gen_opic(op); ++ gen_opic(st, op); + } +- /* put again type if gen_opic() swaped operands */ ++ /* put again type if gen_opic(st) swaped operands */ + vtop->type = type1; + } +- } else if (is_float(bt1) || is_float(bt2)) { ++ } else if (is_float(st, bt1) || is_float(st, bt2)) { + /* compute bigger type and do implicit casts */ + if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) { + t = VT_LDOUBLE; +@@ -5613,7 +4802,7 @@ + /* floats can only be used for a few operations */ + if (op != '+' && op != '-' && op != '*' && op != '/' && + (op < TOK_ULT || op > TOK_GT)) +- error("invalid operands for binary operation"); ++ tcc_error(st, "invalid operands for binary operation"); + goto std_op; + } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) { + /* cast to biggest op */ +@@ -5649,21 +4838,19 @@ + else if (op == TOK_GE) + op = TOK_UGE; + } +- vswap(); ++ vswap(st); + type1.t = t; +- gen_cast(&type1); +- vswap(); ++ gen_cast(st, &type1); ++ vswap(st); + /* special case for shifts and long long: we keep the shift as + an integer */ + if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) + type1.t = VT_INT; +- gen_cast(&type1); +- if (is_float(t)) +- gen_opif(op); +- else if ((t & VT_BTYPE) == VT_LLONG) +- gen_opl(op); ++ gen_cast(st, &type1); ++ if (is_float(st, t)) ++ gen_opif(st, op); + else +- gen_opic(op); ++ gen_opic(st, op); + if (op >= TOK_ULT && op <= TOK_GT) { + /* relationnal op: the result is an int */ + vtop->type.t = VT_INT; +@@ -5674,28 +4861,28 @@ + } + + /* generic itof for unsigned long long case */ +-void gen_cvt_itof1(int t) ++void gen_cvt_itof1(TCCState *st, int t) + { + if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) == + (VT_LLONG | VT_UNSIGNED)) { + + if (t == VT_FLOAT) +- vpush_global_sym(&func_old_type, TOK___ulltof); ++ vpush_global_sym(st, &func_old_type, TOK___ulltof); + else if (t == VT_DOUBLE) +- vpush_global_sym(&func_old_type, TOK___ulltod); ++ vpush_global_sym(st, &func_old_type, TOK___ulltod); + else +- vpush_global_sym(&func_old_type, TOK___ulltold); +- vrott(2); +- gfunc_call(1); +- vpushi(0); ++ vpush_global_sym(st, &func_old_type, TOK___ulltold); ++ vrott(st, 2); ++ gfunc_call(st, 1); ++ vpushi(st, 0); + vtop->r = REG_FRET; + } else { +- gen_cvt_itof(t); ++ gen_cvt_itof(st, t); + } + } + + /* generic ftoi for unsigned long long case */ +-void gen_cvt_ftoi1(int t) ++void gen_cvt_ftoi1(TCCState *state, int t) + { + int st; + +@@ -5703,23 +4890,23 @@ + /* not handled natively */ + st = vtop->type.t & VT_BTYPE; + if (st == VT_FLOAT) +- vpush_global_sym(&func_old_type, TOK___fixunssfdi); ++ vpush_global_sym(state, &func_old_type, TOK___fixunssfdi); + else if (st == VT_DOUBLE) +- vpush_global_sym(&func_old_type, TOK___fixunsdfdi); ++ vpush_global_sym(state, &func_old_type, TOK___fixunsdfdi); + else +- vpush_global_sym(&func_old_type, TOK___fixunsxfdi); +- vrott(2); +- gfunc_call(1); +- vpushi(0); ++ vpush_global_sym(state, &func_old_type, TOK___fixunsxfdi); ++ vrott(state, 2); ++ gfunc_call(state, 1); ++ vpushi(state, 0); + vtop->r = REG_IRET; + vtop->r2 = REG_LRET; + } else { +- gen_cvt_ftoi(t); ++ gen_cvt_ftoi(state, t); + } + } + + /* force char or short cast */ +-void force_charshort_cast(int t) ++void force_charshort_cast(TCCState *st, int t) + { + int bits, dbt; + dbt = t & VT_BTYPE; +@@ -5729,19 +4916,24 @@ + else + bits = 16; + if (t & VT_UNSIGNED) { +- vpushi((1 << bits) - 1); +- gen_op('&'); ++ vpushi(st, (1 << bits) - 1); ++ gen_op(st, '&'); + } else { + bits = 32 - bits; +- vpushi(bits); +- gen_op(TOK_SHL); +- vpushi(bits); +- gen_op(TOK_SAR); ++ vpushi(st, bits); ++ gen_op(st, TOK_SHL); ++ /* result must be signed or the SAR is converted to an SHL ++ This was not the case when "t" was a signed short ++ and the last value on the stack was an unsigned int ++ */ ++ vtop->type.t &= (~VT_UNSIGNED); ++ vpushi(st, bits); ++ gen_op(st, TOK_SAR); + } + } + + /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ +-static void gen_cast(CType *type) ++static void gen_cast(TCCState *st, CType *type) + { + int sbt, dbt, sf, df, c; + +@@ -5750,20 +4942,20 @@ + be incorrect */ + if (vtop->r & VT_MUSTCAST) { + vtop->r &= ~VT_MUSTCAST; +- force_charshort_cast(vtop->type.t); ++ force_charshort_cast(st, vtop->type.t); + } + + /* bitfields first get cast to ints */ + if (vtop->type.t & VT_BITFIELD) { +- gv(RC_INT); ++ gv(st, RC_INT); + } + + dbt = type->t & (VT_BTYPE | VT_UNSIGNED); + sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); + +- if (sbt != dbt && !nocode_wanted) { +- sf = is_float(sbt); +- df = is_float(dbt); ++ if (sbt != dbt && cur_text_section) { ++ sf = is_float(st, sbt); ++ df = is_float(st, dbt); + c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; + if (sf && df) { + /* convert from fp to fp */ +@@ -5784,7 +4976,7 @@ + vtop->c.ld = (long double)vtop->c.d; + } else { + /* non constant case: generate code */ +- gen_cvt_ftof(dbt); ++ gen_cvt_ftof(st, dbt); + } + } else if (df) { + /* convert int to fp */ +@@ -5812,13 +5004,17 @@ + } else { + do_itof: + #if !defined(TCC_TARGET_ARM) +- gen_cvt_itof1(dbt); ++ gen_cvt_itof1(st, dbt); + #else +- gen_cvt_itof(dbt); ++ gen_cvt_itof(st, dbt); + #endif + } + } else if (sf) { + /* convert fp to int */ ++ if (dbt == VT_BOOL) { ++ vpushi(st, 0); ++ gen_op(st, TOK_NE); ++ } else { + /* we handle char/short/etc... with generic code */ + if (dbt != (VT_INT | VT_UNSIGNED) && + dbt != (VT_LLONG | VT_UNSIGNED) && +@@ -5848,12 +5044,13 @@ + } + } else { + do_ftoi: +- gen_cvt_ftoi1(dbt); ++ gen_cvt_ftoi1(st, dbt); + } + if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) { +- /* additional cast for char/short/bool... */ ++ /* additional cast for char/short... */ + vtop->type.t = dbt; +- gen_cast(type); ++ gen_cast(st, type); ++ } + } + } else if ((dbt & VT_BTYPE) == VT_LLONG) { + if ((sbt & VT_BTYPE) != VT_LLONG) { +@@ -5865,45 +5062,54 @@ + vtop->c.ll = vtop->c.i; + } else { + /* machine independent conversion */ +- gv(RC_INT); ++ gv(st, RC_INT); + /* generate high word */ + if (sbt == (VT_INT | VT_UNSIGNED)) { +- vpushi(0); +- gv(RC_INT); ++ vpushi(st, 0); ++ gv(st, RC_INT); + } else { +- gv_dup(); +- vpushi(31); +- gen_op(TOK_SAR); ++ gv_dup(st); ++ vpushi(st, 31); ++ gen_op(st, TOK_SAR); + } + /* patch second register */ + vtop[-1].r2 = vtop->r; +- vpop(); ++ vpop(st); + } + } + } else if (dbt == VT_BOOL) { + /* scalar to bool */ +- vpushi(0); +- gen_op(TOK_NE); ++ vpushi(st, 0); ++ gen_op(st, TOK_NE); + } else if ((dbt & VT_BTYPE) == VT_BYTE || + (dbt & VT_BTYPE) == VT_SHORT) { +- force_charshort_cast(dbt); ++ if (sbt == VT_PTR) { ++ vtop->type.t = VT_INT; ++ warning(st, "nonportable conversion from pointer to char/short"); ++ } ++ force_charshort_cast(st, dbt); + } else if ((dbt & VT_BTYPE) == VT_INT) { + /* scalar to int */ + if (sbt == VT_LLONG) { + /* from long long: just take low order word */ +- lexpand(); +- vpop(); ++ lexpand(st); ++ vpop(st); + } + /* if lvalue and single word type, nothing to do because + the lvalue already contains the real type size (see + VT_LVAL_xxx constants) */ + } ++ } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) { ++ /* if we are casting between pointer types, ++ we must update the VT_LVAL_xxx size */ ++ vtop->r = (vtop->r & ~VT_LVAL_TYPE) ++ | (lvalue_type(st, type->ref->type.t) & VT_LVAL_TYPE); + } + vtop->type = *type; + } + + /* return type size. Put alignment at 'a' */ +-static int type_size(CType *type, int *a) ++static int type_size(TCCState *st, CType *type, int *a) + { + Sym *s; + int bt; +@@ -5917,7 +5123,7 @@ + } else if (bt == VT_PTR) { + if (type->t & VT_ARRAY) { + s = type->ref; +- return type_size(&s->type, a) * s->c; ++ return type_size(st, &s->type, a) * s->c; + } else { + *a = PTR_SIZE; + return PTR_SIZE; +@@ -5928,6 +5134,12 @@ + } else if (bt == VT_DOUBLE || bt == VT_LLONG) { + #ifdef TCC_TARGET_I386 + *a = 4; ++#elif defined(TCC_TARGET_ARM) ++#ifdef TCC_ARM_EABI ++ *a = 8; ++#else ++ *a = 4; ++#endif + #else + *a = 8; + #endif +@@ -5946,43 +5158,43 @@ + } + + /* return the pointed type of t */ +-static inline CType *pointed_type(CType *type) ++static inline CType *pointed_type(TCCState *st, CType *type) + { + return &type->ref->type; + } + + /* modify type so that its it is a pointer to type. */ +-static void mk_pointer(CType *type) ++static void mk_pointer(TCCState *st, CType *type) + { + Sym *s; +- s = sym_push(SYM_FIELD, type, 0, -1); ++ s = sym_push(st, SYM_FIELD, type, 0, -1); + type->t = VT_PTR | (type->t & ~VT_TYPE); + type->ref = s; + } + + /* compare function types. OLD functions match any new functions */ +-static int is_compatible_func(CType *type1, CType *type2) ++static int is_compatible_func(TCCState *state, CType *type1, CType *type2) + { +- Sym *s1, *s2; ++ Sym *st, *s2; + +- s1 = type1->ref; ++ st = type1->ref; + s2 = type2->ref; +- if (!is_compatible_types(&s1->type, &s2->type)) ++ if (!is_compatible_types(state, &st->type, &s2->type)) + return 0; + /* check func_call */ +- if (s1->r != s2->r) ++ if (st->r != s2->r) + return 0; + /* XXX: not complete */ +- if (s1->c == FUNC_OLD || s2->c == FUNC_OLD) ++ if (st->c == FUNC_OLD || s2->c == FUNC_OLD) + return 1; +- if (s1->c != s2->c) ++ if (st->c != s2->c) + return 0; +- while (s1 != NULL) { ++ while (st != NULL) { + if (s2 == NULL) + return 0; +- if (!is_compatible_types(&s1->type, &s2->type)) ++ if (!is_compatible_types(state, &st->type, &s2->type)) + return 0; +- s1 = s1->next; ++ st = st->next; + s2 = s2->next; + } + if (s2) +@@ -5993,9 +5205,9 @@ + /* return true if type1 and type2 are exactly the same (including + qualifiers). + +- - enums are not checked as gcc __builtin_types_compatible_p () ++ - enums are not checked as gcc __builtin_types_compatible_p (st) + */ +-static int is_compatible_types(CType *type1, CType *type2) ++static int is_compatible_types(TCCState *st, CType *type1, CType *type2) + { + int bt1, t1, t2; + +@@ -6007,13 +5219,13 @@ + /* test more complicated cases */ + bt1 = t1 & VT_BTYPE; + if (bt1 == VT_PTR) { +- type1 = pointed_type(type1); +- type2 = pointed_type(type2); +- return is_compatible_types(type1, type2); ++ type1 = pointed_type(st, type1); ++ type2 = pointed_type(st, type2); ++ return is_compatible_types(st, type1, type2); + } else if (bt1 == VT_STRUCT) { + return (type1->ref == type2->ref); + } else if (bt1 == VT_FUNC) { +- return is_compatible_func(type1, type2); ++ return is_compatible_func(st, type1, type2); + } else { + return 1; + } +@@ -6023,7 +5235,7 @@ + printed in the type */ + /* XXX: union */ + /* XXX: add array and function pointers */ +-void type_to_str(char *buf, int buf_size, ++void type_to_str(TCCState *st, char *buf, int buf_size, + CType *type, const char *varstr) + { + int bt, v, t; +@@ -6035,11 +5247,11 @@ + bt = t & VT_BTYPE; + buf[0] = '\0'; + if (t & VT_CONSTANT) +- pstrcat(buf, buf_size, "const "); ++ pstrcat(st, buf, buf_size, "const "); + if (t & VT_VOLATILE) +- pstrcat(buf, buf_size, "volatile "); ++ pstrcat(st, buf, buf_size, "volatile "); + if (t & VT_UNSIGNED) +- pstrcat(buf, buf_size, "unsigned "); ++ pstrcat(st, buf, buf_size, "unsigned "); + switch(bt) { + case VT_VOID: + tstr = "void"; +@@ -6071,7 +5283,7 @@ + case VT_LDOUBLE: + tstr = "long double"; + add_tstr: +- pstrcat(buf, buf_size, tstr); ++ pstrcat(st, buf, buf_size, tstr); + break; + case VT_ENUM: + case VT_STRUCT: +@@ -6079,45 +5291,45 @@ + tstr = "struct "; + else + tstr = "enum "; +- pstrcat(buf, buf_size, tstr); ++ pstrcat(st, buf, buf_size, tstr); + v = type->ref->v & ~SYM_STRUCT; + if (v >= SYM_FIRST_ANOM) +- pstrcat(buf, buf_size, ""); ++ pstrcat(st, buf, buf_size, ""); + else +- pstrcat(buf, buf_size, get_tok_str(v, NULL)); ++ pstrcat(st, buf, buf_size, get_tok_str(st, v, NULL)); + break; + case VT_FUNC: + s = type->ref; +- type_to_str(buf, buf_size, &s->type, varstr); +- pstrcat(buf, buf_size, "("); ++ type_to_str(st, buf, buf_size, &s->type, varstr); ++ pstrcat(st, buf, buf_size, "("); + sa = s->next; + while (sa != NULL) { +- type_to_str(buf1, sizeof(buf1), &sa->type, NULL); +- pstrcat(buf, buf_size, buf1); ++ type_to_str(st, buf1, sizeof(buf1), &sa->type, NULL); ++ pstrcat(st, buf, buf_size, buf1); + sa = sa->next; + if (sa) +- pstrcat(buf, buf_size, ", "); ++ pstrcat(st, buf, buf_size, ", "); + } +- pstrcat(buf, buf_size, ")"); ++ pstrcat(st, buf, buf_size, ")"); + goto no_var; + case VT_PTR: + s = type->ref; +- pstrcpy(buf1, sizeof(buf1), "*"); ++ pstrcpy(st, buf1, sizeof(buf1), "*"); + if (varstr) +- pstrcat(buf1, sizeof(buf1), varstr); +- type_to_str(buf, buf_size, &s->type, buf1); ++ pstrcat(st, buf1, sizeof(buf1), varstr); ++ type_to_str(st, buf, buf_size, &s->type, buf1); + goto no_var; + } + if (varstr) { +- pstrcat(buf, buf_size, " "); +- pstrcat(buf, buf_size, varstr); ++ pstrcat(st, buf, buf_size, " "); ++ pstrcat(st, buf, buf_size, varstr); + } + no_var: ; + } + + /* verify type compatibility to store vtop in 'dt' type, and generate + casts if needed. */ +-static void gen_assign_cast(CType *dt) ++static void gen_assign_cast(TCCState *state, CType *dt) + { + CType *st, *type1, *type2, tmp_type1, tmp_type2; + char buf1[256], buf2[256]; +@@ -6127,30 +5339,30 @@ + dbt = dt->t & VT_BTYPE; + sbt = st->t & VT_BTYPE; + if (dt->t & VT_CONSTANT) +- warning("assignment of read-only location"); ++ warning(state, "assignment of read-only location"); + switch(dbt) { + case VT_PTR: + /* special cases for pointers */ + /* '0' can also be a pointer */ +- if (is_null_pointer(vtop)) ++ if (is_null_pointer(state, vtop)) + goto type_ok; + /* accept implicit pointer to integer cast with warning */ +- if (is_integer_btype(sbt)) { +- warning("assignment makes pointer from integer without a cast"); ++ if (is_integer_btype(state, sbt)) { ++ warning(state, "assignment makes pointer from integer without a cast"); + goto type_ok; + } +- type1 = pointed_type(dt); ++ type1 = pointed_type(state, dt); + /* a function is implicitely a function pointer */ + if (sbt == VT_FUNC) { + if ((type1->t & VT_BTYPE) != VT_VOID && +- !is_compatible_types(pointed_type(dt), st)) ++ !is_compatible_types(state, pointed_type(state, dt), st)) + goto error; + else + goto type_ok; + } + if (sbt != VT_PTR) + goto error; +- type2 = pointed_type(st); ++ type2 = pointed_type(state, st); + if ((type1->t & VT_BTYPE) == VT_VOID || + (type2->t & VT_BTYPE) == VT_VOID) { + /* void * can match anything */ +@@ -6160,20 +5372,20 @@ + tmp_type2 = *type2; + tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); + tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); +- if (!is_compatible_types(&tmp_type1, &tmp_type2)) +- goto error; ++ if (!is_compatible_types(state, &tmp_type1, &tmp_type2)) ++ warning(state, "assignment from incompatible pointer type"); + } + /* check const and volatile */ + if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) || + (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE))) +- warning("assignment discards qualifiers from pointer target type"); ++ warning(state, "assignment discards qualifiers from pointer target type"); + break; + case VT_BYTE: + case VT_SHORT: + case VT_INT: + case VT_LLONG: + if (sbt == VT_PTR || sbt == VT_FUNC) { +- warning("assignment makes integer from pointer without a cast"); ++ warning(state, "assignment makes integer from pointer without a cast"); + } + /* XXX: more tests */ + break; +@@ -6182,20 +5394,20 @@ + tmp_type2 = *st; + tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE); + tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE); +- if (!is_compatible_types(&tmp_type1, &tmp_type2)) { ++ if (!is_compatible_types(state, &tmp_type1, &tmp_type2)) { + error: +- type_to_str(buf1, sizeof(buf1), st, NULL); +- type_to_str(buf2, sizeof(buf2), dt, NULL); +- error("cannot cast '%s' to '%s'", buf1, buf2); ++ type_to_str(state, buf1, sizeof(buf1), st, NULL); ++ type_to_str(state, buf2, sizeof(buf2), dt, NULL); ++ tcc_error(state, "cannot cast '%s' to '%s'", buf1, buf2); + } + break; + } + type_ok: +- gen_cast(dt); ++ gen_cast(state, dt); + } + + /* store vtop in lvalue pushed on stack */ +-void vstore(void) ++void vstore(TCCState *st) + { + int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast; + +@@ -6209,39 +5421,46 @@ + vtop->type.t = ft & VT_TYPE; + /* XXX: factorize */ + if (ft & VT_CONSTANT) +- warning("assignment of read-only location"); ++ warning(st, "assignment of read-only location"); + } else { + delayed_cast = 0; + if (!(ft & VT_BITFIELD)) +- gen_assign_cast(&vtop[-1].type); ++ gen_assign_cast(st, &vtop[-1].type); + } + + if (sbt == VT_STRUCT) { + /* if structure, only generate pointer */ + /* structure assignment : generate memcpy */ + /* XXX: optimize if small size */ +- if (!nocode_wanted) { +- size = type_size(&vtop->type, &align); ++ if (cur_text_section) { ++ size = type_size(st, &vtop->type, &align); + +- vpush_global_sym(&func_old_type, TOK_memcpy); ++#ifdef TCC_ARM_EABI ++ if(!(align & 7)) ++ vpush_global_sym(st, &func_old_type, TOK_memcpy8); ++ else if(!(align & 3)) ++ vpush_global_sym(st, &func_old_type, TOK_memcpy4); ++ else ++#endif ++ vpush_global_sym(st, &func_old_type, TOK_memcpy); + + /* destination */ +- vpushv(vtop - 2); ++ vpushv(st, vtop - 2); + vtop->type.t = VT_INT; +- gaddrof(); ++ gaddrof(st); + /* source */ +- vpushv(vtop - 2); ++ vpushv(st, vtop - 2); + vtop->type.t = VT_INT; +- gaddrof(); ++ gaddrof(st); + /* type size */ +- vpushi(size); +- gfunc_call(3); ++ vpushi(st, size); ++ gfunc_call(st, 3); + +- vswap(); +- vpop(); ++ vswap(st); ++ vpop(st); + } else { +- vswap(); +- vpop(); ++ vswap(st); ++ vpop(st); + } + /* leave source on stack */ + } else if (ft & VT_BITFIELD) { +@@ -6251,83 +5470,92 @@ + /* remove bit field info to avoid loops */ + vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); + ++ /* duplicate source into other register */ ++ gv_dup(st); ++ vswap(st); ++ vrott(st, 3); ++ + /* duplicate destination */ +- vdup(); ++ vdup(st); + vtop[-1] = vtop[-2]; + + /* mask and shift source */ +- vpushi((1 << bit_size) - 1); +- gen_op('&'); +- vpushi(bit_pos); +- gen_op(TOK_SHL); ++ vpushi(st, (1 << bit_size) - 1); ++ gen_op(st, '&'); ++ vpushi(st, bit_pos); ++ gen_op(st, TOK_SHL); + /* load destination, mask and or with source */ +- vswap(); +- vpushi(~(((1 << bit_size) - 1) << bit_pos)); +- gen_op('&'); +- gen_op('|'); ++ vswap(st); ++ vpushi(st, ~(((1 << bit_size) - 1) << bit_pos)); ++ gen_op(st, '&'); ++ gen_op(st, '|'); + /* store result */ +- vstore(); ++ vstore(st); ++ ++ /* pop off shifted source from "duplicate source..." above */ ++ vpop(st); ++ + } else { +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + /* bound check case */ + if (vtop[-1].r & VT_MUSTBOUND) { +- vswap(); +- gbound(); +- vswap(); ++ vswap(st); ++ gbound(st); ++ vswap(st); + } + #endif +- if (!nocode_wanted) { ++ if (cur_text_section) { + rc = RC_INT; +- if (is_float(ft)) ++ if (is_float(st, ft)) + rc = RC_FLOAT; +- r = gv(rc); /* generate value */ ++ r = gv(st, rc); /* generate value */ + /* if lvalue was saved on stack, must read it */ + if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { + SValue sv; +- t = get_reg(RC_INT); ++ t = get_reg(st, RC_INT); + sv.type.t = VT_INT; + sv.r = VT_LOCAL | VT_LVAL; + sv.c.ul = vtop[-1].c.ul; +- load(t, &sv); ++ load(st, t, &sv); + vtop[-1].r = t | VT_LVAL; + } +- store(r, vtop - 1); ++ store(st, r, vtop - 1); + /* two word case handling : store second register at word + 4 */ + if ((ft & VT_BTYPE) == VT_LLONG) { +- vswap(); ++ vswap(st); + /* convert to int to increment easily */ + vtop->type.t = VT_INT; +- gaddrof(); +- vpushi(4); +- gen_op('+'); ++ gaddrof(st); ++ vpushi(st, 4); ++ gen_op(st, '+'); + vtop->r |= VT_LVAL; +- vswap(); ++ vswap(st); + /* XXX: it works because r2 is spilled last ! */ +- store(vtop->r2, vtop - 1); ++ store(st, vtop->r2, vtop - 1); + } + } +- vswap(); +- vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ ++ vswap(st); ++ vtop--; /* NOT vpop(st) because on x86 it would flush the fp stack */ + vtop->r |= delayed_cast; + } + } + + /* post defines POST/PRE add. c is the token ++ or -- */ +-void inc(int post, int c) ++void inc(TCCState *st, int post, int c) + { +- test_lvalue(); +- vdup(); /* save lvalue */ ++ test_lvalue(st); ++ vdup(st); /* save lvalue */ + if (post) { +- gv_dup(); /* duplicate value */ +- vrotb(3); +- vrotb(3); ++ gv_dup(st); /* duplicate value */ ++ vrotb(st, 3); ++ vrotb(st, 3); + } + /* add constant */ +- vpushi(c - TOK_MID); +- gen_op('+'); +- vstore(); /* store value */ ++ vpushi(st, c - TOK_MID); ++ gen_op(st, '+'); ++ vstore(st); /* store value */ + if (post) +- vpop(); /* if post op, return saved value */ ++ vpop(st); /* if post op, return saved value */ + } + + /* Parse GNUC __attribute__ extension. Currently, the following +@@ -6338,37 +5566,37 @@ + - unused : currently ignored, but may be used someday. + - regparm(n) : pass function parameters in registers (i386 only) + */ +-static void parse_attribute(AttributeDef *ad) ++static void parse_attribute(TCCState *st, AttributeDef *ad) + { + int t, n; + + while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) { +- next(); +- skip('('); +- skip('('); ++ next(st); ++ skip(st, '('); ++ skip(st, '('); + while (tok != ')') { + if (tok < TOK_IDENT) +- expect("attribute name"); ++ expect(st, "attribute name"); + t = tok; +- next(); ++ next(st); + switch(t) { + case TOK_SECTION1: + case TOK_SECTION2: +- skip('('); ++ skip(st, '('); + if (tok != TOK_STR) +- expect("section name"); +- ad->section = find_section(tcc_state, (char *)tokc.cstr->data); +- next(); +- skip(')'); ++ expect(st, "section name"); ++ ad->section = find_section(st, (char *)tokc.cstr->data); ++ next(st); ++ skip(st, ')'); + break; + case TOK_ALIGNED1: + case TOK_ALIGNED2: + if (tok == '(') { +- next(); +- n = expr_const(); ++ next(st); ++ n = expr_const(st); + if (n <= 0 || (n & (n - 1)) != 0) +- error("alignment must be a positive power of two"); +- skip(')'); ++ tcc_error(st, "alignment must be a positive power of two"); ++ skip(st, ')'); + } else { + n = MAX_ALIGN; + } +@@ -6401,63 +5629,69 @@ + #ifdef TCC_TARGET_I386 + case TOK_REGPARM1: + case TOK_REGPARM2: +- skip('('); +- n = expr_const(); ++ skip(st, '('); ++ n = expr_const(st); + if (n > 3) + n = 3; + else if (n < 0) + n = 0; + if (n > 0) + ad->func_call = FUNC_FASTCALL1 + n - 1; +- skip(')'); ++ skip(st, ')'); ++ break; ++ case TOK_FASTCALL1: ++ case TOK_FASTCALL2: ++ case TOK_FASTCALL3: ++ ad->func_call = FUNC_FASTCALLW; + break; + #endif + case TOK_DLLEXPORT: + ad->dllexport = 1; + break; + default: +- if (tcc_state->warn_unsupported) +- warning("'%s' attribute ignored", get_tok_str(t, NULL)); ++ if (st->warn_unsupported) ++ warning(st, "'%s' attribute ignored", get_tok_str(st, t, NULL)); + /* skip parameters */ +- /* XXX: skip parenthesis too */ + if (tok == '(') { +- next(); +- while (tok != ')' && tok != -1) +- next(); +- next(); ++ int parenthesis = 0; ++ do { ++ if (tok == '(') parenthesis++; ++ else if (tok == ')') parenthesis--; ++ next(st); ++ } while (parenthesis && tok != -1); + } + break; + } + if (tok != ',') + break; +- next(); ++ next(st); + } +- skip(')'); +- skip(')'); ++ skip(st, ')'); ++ skip(st, ')'); + } + } + + /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ +-static void struct_decl(CType *type, int u) ++static void struct_decl(TCCState *st, CType *type, int u) + { + int a, v, size, align, maxalign, c, offset; + int bit_size, bit_pos, bsize, bt, lbit_pos; +- Sym *s, *ss, **ps; ++ Sym *s, *ss, *ass, **ps; + AttributeDef ad; + CType type1, btype; + + a = tok; /* save decl type */ +- next(); ++ next(st); + if (tok != '{') { + v = tok; +- next(); ++ next(st); + /* struct already defined ? return it */ + if (v < TOK_IDENT) +- expect("struct/union/enum name"); +- s = struct_find(v); ++ expect(st, "struct/union/enum name"); ++ s = struct_find(st, v); + if (s) { + if (s->type.t != a) +- error("invalid type"); ++ tcc_error(st, "invalid type"); + goto do_decl; + } + } else { +@@ -6465,7 +5699,7 @@ + } + type1.t = a; + /* we put an undefined size for struct/union */ +- s = sym_push(v | SYM_STRUCT, &type1, 0, -1); ++ s = sym_push(st, v | SYM_STRUCT, &type1, 0, -1); + s->r = 0; /* default alignment is zero as gcc */ + /* put struct/union/enum name in type */ + do_decl: +@@ -6473,9 +5707,9 @@ + type->ref = s; + + if (tok == '{') { +- next(); ++ next(st); + if (s->c != -1) +- error("struct/union/enum already defined"); ++ tcc_error(st, "struct/union/enum already defined"); + /* cannot be empty */ + c = 0; + /* non empty enums are not allowed */ +@@ -6483,62 +5717,64 @@ + for(;;) { + v = tok; + if (v < TOK_UIDENT) +- expect("identifier"); +- next(); ++ expect(st, "identifier"); ++ next(st); + if (tok == '=') { +- next(); +- c = expr_const(); ++ next(st); ++ c = expr_const(st); + } + /* enum symbols have static storage */ +- ss = sym_push(v, &int_type, VT_CONST, c); ++ ss = sym_push(st, v, &int_type, VT_CONST, c); + ss->type.t |= VT_STATIC; + if (tok != ',') + break; +- next(); ++ next(st); + c++; + /* NOTE: we accept a trailing comma */ + if (tok == '}') + break; + } +- skip('}'); ++ skip(st, '}'); + } else { + maxalign = 1; + ps = &s->next; + bit_pos = 0; + offset = 0; + while (tok != '}') { +- parse_btype(&btype, &ad); ++ parse_btype(st, &btype, &ad); + while (1) { + bit_size = -1; + v = 0; + type1 = btype; + if (tok != ':') { +- type_decl(&type1, &ad, &v, TYPE_DIRECT); ++ type_decl(st, &type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT); ++ if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT) ++ expect(st, "identifier"); + if ((type1.t & VT_BTYPE) == VT_FUNC || + (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE))) +- error("invalid type for '%s'", +- get_tok_str(v, NULL)); ++ tcc_error(st, "invalid type for '%s'", ++ get_tok_str(st, v, NULL)); + } + if (tok == ':') { +- next(); +- bit_size = expr_const(); ++ next(st); ++ bit_size = expr_const(st); + /* XXX: handle v = 0 case for messages */ + if (bit_size < 0) +- error("negative width in bit-field '%s'", +- get_tok_str(v, NULL)); ++ tcc_error(st, "negative width in bit-field '%s'", ++ get_tok_str(st, v, NULL)); + if (v && bit_size == 0) +- error("zero width for bit-field '%s'", +- get_tok_str(v, NULL)); ++ tcc_error(st, "zero width for bit-field '%s'", ++ get_tok_str(st, v, NULL)); + } +- size = type_size(&type1, &align); ++ size = type_size(st, &type1, &align); + if (ad.aligned) { + if (align < ad.aligned) + align = ad.aligned; + } else if (ad.packed) { + align = 1; +- } else if (*tcc_state->pack_stack_ptr) { +- if (align > *tcc_state->pack_stack_ptr) +- align = *tcc_state->pack_stack_ptr; ++ } else if (*st->pack_stack_ptr) { ++ if (align > *st->pack_stack_ptr) ++ align = *st->pack_stack_ptr; + } + lbit_pos = 0; + if (bit_size >= 0) { +@@ -6548,11 +5784,11 @@ + bt != VT_SHORT && + bt != VT_BOOL && + bt != VT_ENUM) +- error("bitfields must have scalar type"); ++ tcc_error(st, "bitfields must have scalar type"); + bsize = size * 8; + if (bit_size > bsize) { +- error("width of '%s' exceeds its type", +- get_tok_str(v, NULL)); ++ tcc_error(st, "width of '%s' exceeds its type", ++ get_tok_str(st, v, NULL)); + } else if (bit_size == bsize) { + /* no need for bit fields */ + bit_pos = 0; +@@ -6576,13 +5812,14 @@ + } else { + bit_pos = 0; + } +- if (v) { ++ if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) { + /* add new memory data only if starting + bit field */ + if (lbit_pos == 0) { + if (a == TOK_STRUCT) { + c = (c + align - 1) & -align; + offset = c; ++ if (size > 0) + c += size; + } else { + offset = 0; +@@ -6594,7 +5831,7 @@ + } + #if 0 + printf("add field %s offset=%d", +- get_tok_str(v, NULL), offset); ++ get_tok_str(st, v, NULL), offset); + if (type1.t & VT_BITFIELD) { + printf(" pos=%d size=%d", + (type1.t >> VT_STRUCT_SHIFT) & 0x3f, +@@ -6602,17 +5839,26 @@ + } + printf("\n"); + #endif +- ss = sym_push(v | SYM_FIELD, &type1, 0, offset); ++ } ++ if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) { ++ ass = type1.ref; ++ while ((ass = ass->next) != NULL) { ++ ss = sym_push(st, ass->v, &ass->type, 0, offset + ass->c); ++ *ps = ss; ++ ps = &ss->next; ++ } ++ } else if (v) { ++ ss = sym_push(st, v | SYM_FIELD, &type1, 0, offset); + *ps = ss; + ps = &ss->next; + } + if (tok == ';' || tok == TOK_EOF) + break; +- skip(','); ++ skip(st, ','); + } +- skip(';'); ++ skip(st, ';'); + } +- skip('}'); ++ skip(st, '}'); + /* store size and alignment */ + s->c = (c + maxalign - 1) & -maxalign; + s->r = maxalign; +@@ -6623,31 +5869,32 @@ + /* return 0 if no type declaration. otherwise, return the basic type + and skip it. + */ +-static int parse_btype(CType *type, AttributeDef *ad) ++static int parse_btype(TCCState *st, CType *type, AttributeDef *ad) + { +- int t, u, type_found, typespec_found; ++ int t, u, type_found, typespec_found, typedef_found; + Sym *s; + CType type1; + + memset(ad, 0, sizeof(AttributeDef)); + type_found = 0; + typespec_found = 0; ++ typedef_found = 0; + t = 0; + while(1) { + switch(tok) { + case TOK_EXTENSION: + /* currently, we really ignore extension */ +- next(); ++ next(st); + continue; + + /* basic types */ + case TOK_CHAR: + u = VT_BYTE; + basic_type: +- next(); ++ next(st); + basic_type1: + if ((t & VT_BTYPE) != 0) +- error("too many basic types"); ++ tcc_error(st, "too many basic types"); + t |= u; + typespec_found = 1; + break; +@@ -6658,11 +5905,11 @@ + u = VT_SHORT; + goto basic_type; + case TOK_INT: +- next(); ++ next(st); + typespec_found = 1; + break; + case TOK_LONG: +- next(); ++ next(st); + if ((t & VT_BTYPE) == VT_DOUBLE) { + t = (t & ~VT_BTYPE) | VT_LDOUBLE; + } else if ((t & VT_BTYPE) == VT_LONG) { +@@ -6679,7 +5926,7 @@ + u = VT_FLOAT; + goto basic_type; + case TOK_DOUBLE: +- next(); ++ next(st); + if ((t & VT_BTYPE) == VT_LONG) { + t = (t & ~VT_BTYPE) | VT_LDOUBLE; + } else { +@@ -6688,14 +5935,14 @@ + } + break; + case TOK_ENUM: +- struct_decl(&type1, VT_ENUM); ++ struct_decl(st, &type1, VT_ENUM); + basic_type2: + u = type1.t; + type->ref = type1.ref; + goto basic_type1; + case TOK_STRUCT: + case TOK_UNION: +- struct_decl(&type1, VT_STRUCT); ++ struct_decl(st, &type1, VT_STRUCT); + goto basic_type2; + + /* type modifiers */ +@@ -6703,83 +5950,85 @@ + case TOK_CONST2: + case TOK_CONST3: + t |= VT_CONSTANT; +- next(); ++ next(st); + break; + case TOK_VOLATILE1: + case TOK_VOLATILE2: + case TOK_VOLATILE3: + t |= VT_VOLATILE; +- next(); ++ next(st); + break; + case TOK_SIGNED1: + case TOK_SIGNED2: + case TOK_SIGNED3: + typespec_found = 1; + t |= VT_SIGNED; +- next(); ++ next(st); + break; + case TOK_REGISTER: + case TOK_AUTO: + case TOK_RESTRICT1: + case TOK_RESTRICT2: + case TOK_RESTRICT3: +- next(); ++ next(st); + break; + case TOK_UNSIGNED: + t |= VT_UNSIGNED; +- next(); ++ next(st); + typespec_found = 1; + break; + + /* storage */ + case TOK_EXTERN: + t |= VT_EXTERN; +- next(); ++ next(st); + break; + case TOK_STATIC: + t |= VT_STATIC; +- next(); ++ next(st); + break; + case TOK_TYPEDEF: + t |= VT_TYPEDEF; +- next(); ++ next(st); + break; + case TOK_INLINE1: + case TOK_INLINE2: + case TOK_INLINE3: + t |= VT_INLINE; +- next(); ++ next(st); + break; + + /* GNUC attribute */ + case TOK_ATTRIBUTE1: + case TOK_ATTRIBUTE2: +- parse_attribute(ad); ++ parse_attribute(st, ad); + break; + /* GNUC typeof */ + case TOK_TYPEOF1: + case TOK_TYPEOF2: + case TOK_TYPEOF3: +- next(); +- parse_expr_type(&type1); ++ next(st); ++ parse_expr_type(st, &type1); + goto basic_type2; + default: +- if (typespec_found) ++ if (typespec_found || typedef_found) + goto the_end; +- s = sym_find(tok); ++ s = sym_find(st, tok); + if (!s || !(s->type.t & VT_TYPEDEF)) + goto the_end; ++ typedef_found = 1; + t |= (s->type.t & ~VT_TYPEDEF); + type->ref = s->type.ref; +- next(); ++ next(st); ++ typespec_found = 1; + break; + } + type_found = 1; + } + the_end: + if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED)) +- error("signed and unsigned modifier"); +- if (tcc_state->char_is_unsigned) { ++ tcc_error(st, "signed and unsigned modifier"); ++ if (st->char_is_unsigned) { + if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE) + t |= VT_UNSIGNED; + } +@@ -6794,7 +6043,7 @@ + + /* convert a function parameter type (array to pointer and function to + function pointer) */ +-static inline void convert_parameter_type(CType *pt) ++static inline void convert_parameter_type(TCCState *st, CType *pt) + { + /* remove const and volatile qualifiers (XXX: const could be used + to indicate a const function parameter */ +@@ -6802,29 +6051,29 @@ + /* array must be transformed to pointer according to ANSI C */ + pt->t &= ~VT_ARRAY; + if ((pt->t & VT_BTYPE) == VT_FUNC) { +- mk_pointer(pt); ++ mk_pointer(st, pt); + } + } + +-static void post_type(CType *type, AttributeDef *ad) ++static void parse_function_parameters(TCCState *st, CType *type, AttributeDef *ad) + { + int n, l, t1; + Sym **plast, *s, *first; + AttributeDef ad1; + CType pt; + +- if (tok == '(') { +- /* function declaration */ +- next(); ++ /* Starting with '(' parse attributes for function declaration */ ++ next(st); + l = 0; + first = NULL; + plast = &first; +- while (tok != ')') { ++ if (tok != ')') { ++ for(;;) { + /* read param name and compute offset */ + if (l != FUNC_OLD) { +- if (!parse_btype(&pt, &ad1)) { ++ if (!parse_btype(st, &pt, &ad1)) { + if (l) { +- error("invalid type"); ++ tcc_error(st, "invalid type"); + } else { + l = FUNC_OLD; + goto old_proto; +@@ -6833,72 +6082,89 @@ + l = FUNC_NEW; + if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')') + break; +- type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT); ++ type_decl(st, &pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT); + if ((pt.t & VT_BTYPE) == VT_VOID) +- error("parameter declared as void"); ++ tcc_error(st, "parameter declared as void"); + } else { + old_proto: + n = tok; ++ if (n < TOK_UIDENT) ++ expect(st, "identifier"); + pt.t = VT_INT; +- next(); ++ next(st); + } +- convert_parameter_type(&pt); +- s = sym_push(n | SYM_FIELD, &pt, 0, 0); ++ convert_parameter_type(st, &pt); ++ s = sym_push(st, n | SYM_FIELD, &pt, 0, 0); + *plast = s; + plast = &s->next; +- if (tok == ',') { +- next(); ++ if (tok == ')') ++ break; ++ skip(st, ','); + if (l == FUNC_NEW && tok == TOK_DOTS) { + l = FUNC_ELLIPSIS; +- next(); ++ next(st); + break; + } + } + } + /* if no parameters, then old type prototype */ +- if (l == 0) +- l = FUNC_OLD; +- skip(')'); ++ if (!l) l = FUNC_OLD; ++ skip(st, ')'); + t1 = type->t & VT_STORAGE; + /* NOTE: const is ignored in returned type as it has a special + meaning in gcc / C++ */ + type->t &= ~(VT_STORAGE | VT_CONSTANT); +- post_type(type, ad); + /* we push a anonymous symbol which will contain the function prototype */ +- s = sym_push(SYM_FIELD, type, ad->func_call, l); ++ s = sym_push(st, SYM_FIELD, type, ad->func_call, l); + s->next = first; + type->t = t1 | VT_FUNC; + type->ref = s; +- } else if (tok == '[') { +- /* array definition */ +- next(); +- n = -1; ++} ++ ++static void parse_array_dimensions(TCCState *st, CType *type) ++{ ++ int n = -1, t1; ++ Sym *s; ++ ++ /* Starting with '[' parse array dimensions */ ++ next(st); ++ if (tok == TOK_RESTRICT1) next(st); + if (tok != ']') { +- n = expr_const(); +- if (n < 0) +- error("invalid array size"); ++ char *message = "invalid array size"; ++ expr_const1(st); ++ /* Conventional constant array? */ ++ if ((vtop->r & (VT_VALMASK |VT_LVAL | VT_SYM)) == VT_CONST) { ++ n = vtop->c.i; ++ vpop(st); ++ ++ if (n < 0)tcc_error(st, message); ++ } else if (!local_stack)tcc_error(st, message); ++ else { ++ gen_assign_cast(st, &int_type); ++ n = -2; ++ tcc_error(st, "dynamic arrays not implemented yet"); ++ } + } +- skip(']'); ++ skip(st, ']'); + /* parse next post type */ + t1 = type->t & VT_STORAGE; + type->t &= ~VT_STORAGE; +- post_type(type, ad); ++ if (tok == '[') parse_array_dimensions(st, type); + + /* we push a anonymous symbol which will contain the array + element type */ +- s = sym_push(SYM_FIELD, type, 0, n); ++ s = sym_push(st, SYM_FIELD, type, 0, n); + type->t = t1 | VT_ARRAY | VT_PTR; + type->ref = s; + } +-} + + /* Parse a type declaration (except basic type), and return the type + in 'type'. 'td' is a bitmask indicating which kind of type decl is + expected. 'type' should contain the basic type. 'ad' is the + attribute definition of the basic type. It can be modified by +- type_decl(). ++ type_decl(st). + */ +-static void type_decl(CType *type, AttributeDef *ad, int *v, int td) ++static void type_decl(TCCState *st, CType *type, AttributeDef *ad, int *v, int td) + { + Sym *s; + CType type1, *type2; +@@ -6907,7 +6173,7 @@ + while (tok == '*') { + qualifiers = 0; + redo: +- next(); ++ next(st); + switch(tok) { + case TOK_CONST1: + case TOK_CONST2: +@@ -6924,39 +6190,40 @@ + case TOK_RESTRICT3: + goto redo; + } +- mk_pointer(type); ++ mk_pointer(st, type); + type->t |= qualifiers; + } + + /* XXX: clarify attribute handling */ + if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) +- parse_attribute(ad); ++ parse_attribute(st, ad); + + /* recursive type */ +- /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */ ++ /* XXX: incorrect if abstract type for functions (e.g. 'int (st)') */ + type1.t = 0; /* XXX: same as int */ + if (tok == '(') { +- next(); ++ next(st); + /* XXX: this is not correct to modify 'ad' at this point, but + the syntax is not clear */ + if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) +- parse_attribute(ad); +- type_decl(&type1, ad, v, td); +- skip(')'); ++ parse_attribute(st, ad); ++ type_decl(st, &type1, ad, v, td); ++ skip(st, ')'); + } else { + /* type identifier */ + if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) { + *v = tok; +- next(); ++ next(st); + } else { + if (!(td & TYPE_ABSTRACT)) +- expect("identifier"); ++ expect(st, "identifier"); + *v = 0; + } + } +- post_type(type, ad); ++ if (tok == '(') parse_function_parameters(st, type, ad); ++ else if (tok == '[') parse_array_dimensions(st, type); + if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) +- parse_attribute(ad); ++ parse_attribute(st, ad); + if (!type1.t) + return; + /* append type at the end of type1 */ +@@ -6973,7 +6240,7 @@ + } + + /* compute the lvalue VT_LVAL_xxx needed to match type t. */ +-static int lvalue_type(int t) ++static int lvalue_type(TCCState *st, int t) + { + int bt, r; + r = VT_LVAL; +@@ -6990,16 +6257,20 @@ + } + + /* indirection with full error checking and bound check */ +-static void indir(void) ++static void indir(TCCState *st) + { +- if ((vtop->type.t & VT_BTYPE) != VT_PTR) +- expect("pointer"); +- if ((vtop->r & VT_LVAL) && !nocode_wanted) +- gv(RC_INT); +- vtop->type = *pointed_type(&vtop->type); +- /* an array is never an lvalue */ +- if (!(vtop->type.t & VT_ARRAY)) { +- vtop->r |= lvalue_type(vtop->type.t); ++ if ((vtop->type.t & VT_BTYPE) != VT_PTR) { ++ if ((vtop->type.t & VT_BTYPE) == VT_FUNC) ++ return; ++ expect(st, "pointer"); ++ } ++ if ((vtop->r & VT_LVAL) && cur_text_section) ++ gv(st, RC_INT); ++ vtop->type = *pointed_type(st, &vtop->type); ++ /* Arrays and functions are never lvalues */ ++ if (!(vtop->type.t & VT_ARRAY) ++ && (vtop->type.t & VT_BTYPE) != VT_FUNC) { ++ vtop->r |= lvalue_type(st, vtop->type.t); + /* if bound checking, the referenced pointer must be checked */ + if (do_bounds_check) + vtop->r |= VT_MUSTBOUND; +@@ -7007,7 +6278,7 @@ + } + + /* pass a parameter to a function and do type checking and casting */ +-static void gfunc_param_typed(Sym *func, Sym *arg) ++static void gfunc_param_typed(TCCState *st, Sym *func, Sym *arg) + { + int func_type; + CType type; +@@ -7018,52 +6289,52 @@ + /* default casting : only need to convert float to double */ + if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) { + type.t = VT_DOUBLE; +- gen_cast(&type); ++ gen_cast(st, &type); + } + } else if (arg == NULL) { +- error("too many arguments to function"); ++ tcc_error(st, "too many arguments to function"); + } else { + type = arg->type; + type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */ +- gen_assign_cast(&type); ++ gen_assign_cast(st, &type); + } + } + + /* parse an expression of the form '(type)' or '(expr)' and return its + type */ +-static void parse_expr_type(CType *type) ++static void parse_expr_type(TCCState *st, CType *type) + { + int n; + AttributeDef ad; + +- skip('('); +- if (parse_btype(type, &ad)) { +- type_decl(type, &ad, &n, TYPE_ABSTRACT); ++ skip(st, '('); ++ if (parse_btype(st, type, &ad)) { ++ type_decl(st, type, &ad, &n, TYPE_ABSTRACT); + } else { +- expr_type(type); ++ expr_type(st, type); + } +- skip(')'); ++ skip(st, ')'); + } + +-static void parse_type(CType *type) ++static void parse_type(TCCState *st, CType *type) + { + AttributeDef ad; + int n; + +- if (!parse_btype(type, &ad)) { +- expect("type"); ++ if (!parse_btype(st, type, &ad)) { ++ expect(st, "type"); + } +- type_decl(type, &ad, &n, TYPE_ABSTRACT); ++ type_decl(st, type, &ad, &n, TYPE_ABSTRACT); + } + +-static void vpush_tokc(int t) ++static void vpush_tokc(TCCState *st, int t) + { + CType type; + type.t = t; +- vsetc(&type, VT_CONST, &tokc); ++ vsetc(st, &type, VT_CONST, &tokc); + } + +-static void unary(void) ++static void unary(TCCState *st) + { + int n, t, align, size, r; + CType type; +@@ -7075,37 +6346,37 @@ + tok_next: + switch(tok) { + case TOK_EXTENSION: +- next(); ++ next(st); + goto tok_next; + case TOK_CINT: + case TOK_CCHAR: + case TOK_LCHAR: +- vpushi(tokc.i); +- next(); ++ vpushi(st, tokc.i); ++ next(st); + break; + case TOK_CUINT: +- vpush_tokc(VT_INT | VT_UNSIGNED); +- next(); ++ vpush_tokc(st, VT_INT | VT_UNSIGNED); ++ next(st); + break; + case TOK_CLLONG: +- vpush_tokc(VT_LLONG); +- next(); ++ vpush_tokc(st, VT_LLONG); ++ next(st); + break; + case TOK_CULLONG: +- vpush_tokc(VT_LLONG | VT_UNSIGNED); +- next(); ++ vpush_tokc(st, VT_LLONG | VT_UNSIGNED); ++ next(st); + break; + case TOK_CFLOAT: +- vpush_tokc(VT_FLOAT); +- next(); ++ vpush_tokc(st, VT_FLOAT); ++ next(st); + break; + case TOK_CDOUBLE: +- vpush_tokc(VT_DOUBLE); +- next(); ++ vpush_tokc(st, VT_DOUBLE); ++ next(st); + break; + case TOK_CLDOUBLE: +- vpush_tokc(VT_LDOUBLE); +- next(); ++ vpush_tokc(st, VT_LDOUBLE); ++ next(st); + break; + case TOK___FUNCTION__: + if (!gnu_ext) +@@ -7119,36 +6390,40 @@ + len = strlen(funcname) + 1; + /* generate char[len] type */ + type.t = VT_BYTE; +- mk_pointer(&type); ++ mk_pointer(st, &type); + type.t |= VT_ARRAY; + type.ref->c = len; +- vpush_ref(&type, data_section, data_section->data_offset, len); +- ptr = section_ptr_add(data_section, len); ++ vpush_ref(st, &type, data_section, data_section->data_offset, len); ++ ptr = section_ptr_add(st, data_section, len); + memcpy(ptr, funcname, len); +- next(); ++ next(st); + } + break; + case TOK_LSTR: ++#ifdef WIN32 ++ t = VT_SHORT | VT_UNSIGNED; ++#else + t = VT_INT; ++#endif + goto str_init; + case TOK_STR: + /* string parsing */ + t = VT_BYTE; + str_init: +- if (tcc_state->warn_write_strings) ++ if (st->warn_write_strings) + t |= VT_CONSTANT; + type.t = t; +- mk_pointer(&type); ++ mk_pointer(st, &type); + type.t |= VT_ARRAY; + memset(&ad, 0, sizeof(AttributeDef)); +- decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0); ++ decl_initializer_alloc(st, &type, &ad, VT_CONST, 2, 0, 0); + break; + case '(': +- next(); ++ next(st); + /* cast ? */ +- if (parse_btype(&type, &ad)) { +- type_decl(&type, &ad, &n, TYPE_ABSTRACT); +- skip(')'); ++ if (parse_btype(st, &type, &ad)) { ++ type_decl(st, &type, &ad, &n, TYPE_ABSTRACT); ++ skip(st, ')'); + /* check ISOC99 compound literal */ + if (tok == '{') { + /* data is allocated locally by default */ +@@ -7158,170 +6433,174 @@ + r = VT_LOCAL; + /* all except arrays are lvalues */ + if (!(type.t & VT_ARRAY)) +- r |= lvalue_type(type.t); ++ r |= lvalue_type(st, type.t); + memset(&ad, 0, sizeof(AttributeDef)); +- decl_initializer_alloc(&type, &ad, r, 1, 0, 0); ++ decl_initializer_alloc(st, &type, &ad, r, 1, 0, 0); + } else { +- unary(); +- gen_cast(&type); ++ unary(st); ++ gen_cast(st, &type); + } + } else if (tok == '{') { + /* save all registers */ +- save_regs(0); ++ save_regs(st, 0); + /* statement expression : we do not accept break/continue + inside as GCC does */ +- block(NULL, NULL, NULL, NULL, 0, 1); +- skip(')'); ++ block(st, NULL, NULL, NULL, NULL, 0, 1); ++ skip(st, ')'); + } else { +- gexpr(); +- skip(')'); ++ gexpr(st); ++ skip(st, ')'); + } + break; + case '*': +- next(); +- unary(); +- indir(); ++ next(st); ++ unary(st); ++ indir(st); + break; + case '&': +- next(); +- unary(); ++ next(st); ++ unary(st); + /* functions names must be treated as function pointers, + except for unary '&' and sizeof. Since we consider that + functions are not lvalues, we only have to handle it + there and in function calls. */ + /* arrays can also be used although they are not lvalues */ + if ((vtop->type.t & VT_BTYPE) != VT_FUNC && +- !(vtop->type.t & VT_ARRAY)) +- test_lvalue(); +- mk_pointer(&vtop->type); +- gaddrof(); ++ !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL)) ++ test_lvalue(st); ++ mk_pointer(st, &vtop->type); ++ gaddrof(st); + break; + case '!': +- next(); +- unary(); ++ next(st); ++ unary(st); + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) + vtop->c.i = !vtop->c.i; + else if ((vtop->r & VT_VALMASK) == VT_CMP) + vtop->c.i = vtop->c.i ^ 1; +- else +- vseti(VT_JMP, gtst(1, 0)); ++ else { ++ save_regs(st, 1); ++ vseti(st, VT_JMP, gtst(st, 1, 0)); ++ } + break; + case '~': +- next(); +- unary(); +- vpushi(-1); +- gen_op('^'); ++ next(st); ++ unary(st); ++ vpushi(st, -1); ++ gen_op(st, '^'); + break; + case '+': +- next(); ++ next(st); + /* in order to force cast, we add zero */ +- unary(); ++ unary(st); + if ((vtop->type.t & VT_BTYPE) == VT_PTR) +- error("pointer not accepted for unary plus"); +- vpushi(0); +- gen_op('+'); ++ tcc_error(st, "pointer not accepted for unary plus"); ++ vpushi(st, 0); ++ gen_op(st, '+'); + break; + case TOK_SIZEOF: + case TOK_ALIGNOF1: + case TOK_ALIGNOF2: + t = tok; +- next(); ++ next(st); + if (tok == '(') { +- parse_expr_type(&type); ++ parse_expr_type(st, &type); + } else { +- unary_type(&type); ++ unary_type(st, &type); + } +- size = type_size(&type, &align); ++ size = type_size(st, &type, &align); + if (t == TOK_SIZEOF) { + if (size < 0) +- error("sizeof applied to an incomplete type"); +- vpushi(size); ++ tcc_error(st, "sizeof applied to an incomplete type"); ++ vpushi(st, size); + } else { +- vpushi(align); ++ vpushi(st, align); + } ++ vtop->type.t |= VT_UNSIGNED; + break; + + case TOK_builtin_types_compatible_p: + { + CType type1, type2; +- next(); +- skip('('); +- parse_type(&type1); +- skip(','); +- parse_type(&type2); +- skip(')'); ++ next(st); ++ skip(st, '('); ++ parse_type(st, &type1); ++ skip(st, ','); ++ parse_type(st, &type2); ++ skip(st, ')'); + type1.t &= ~(VT_CONSTANT | VT_VOLATILE); + type2.t &= ~(VT_CONSTANT | VT_VOLATILE); +- vpushi(is_compatible_types(&type1, &type2)); ++ vpushi(st, is_compatible_types(st, &type1, &type2)); + } + break; + case TOK_builtin_constant_p: + { +- int saved_nocode_wanted, res; +- next(); +- skip('('); +- saved_nocode_wanted = nocode_wanted; +- nocode_wanted = 1; +- gexpr(); ++ Section *saved_text_section; ++ int res; ++ next(st); ++ skip(st, '('); ++ saved_text_section = cur_text_section; ++ cur_text_section = NULL; ++ gexpr(st); + res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; +- vpop(); +- nocode_wanted = saved_nocode_wanted; +- skip(')'); +- vpushi(res); ++ vpop(st); ++ cur_text_section = saved_text_section; ++ skip(st, ')'); ++ vpushi(st, res); + } + break; + case TOK_INC: + case TOK_DEC: + t = tok; +- next(); +- unary(); +- inc(0, t); ++ next(st); ++ unary(st); ++ inc(st, 0, t); + break; + case '-': +- next(); +- vpushi(0); +- unary(); +- gen_op('-'); ++ next(st); ++ vpushi(st, 0); ++ unary(st); ++ gen_op(st, '-'); + break; + case TOK_LAND: + if (!gnu_ext) + goto tok_identifier; +- next(); ++ next(st); + /* allow to take the address of a label */ + if (tok < TOK_UIDENT) +- expect("label identifier"); +- s = label_find(tok); ++ expect(st, "label identifier"); ++ s = label_find(st, tok); + if (!s) { +- s = label_push(&global_label_stack, tok, LABEL_FORWARD); ++ s = label_push(st, &global_label_stack, tok, LABEL_FORWARD); + } else { + if (s->r == LABEL_DECLARED) + s->r = LABEL_FORWARD; + } + if (!s->type.t) { + s->type.t = VT_VOID; +- mk_pointer(&s->type); ++ mk_pointer(st, &s->type); + s->type.t |= VT_STATIC; + } +- vset(&s->type, VT_CONST | VT_SYM, 0); ++ vset(st, &s->type, VT_CONST | VT_SYM, 0); + vtop->sym = s; +- next(); ++ next(st); + break; + default: + tok_identifier: + t = tok; +- next(); ++ next(st); + if (t < TOK_UIDENT) +- expect("identifier"); +- s = sym_find(t); ++ expect(st, "identifier"); ++ s = sym_find(st, t); + if (!s) { + if (tok != '(') +- error("'%s' undeclared", get_tok_str(t, NULL)); ++ tcc_error(st, "'%s' undeclared", get_tok_str(st, t, NULL)); + /* for simple function calls, we tolerate undeclared +- external reference to int() function */ +- if (tcc_state->warn_implicit_function_declaration) +- warning("implicit declaration of function '%s'", +- get_tok_str(t, NULL)); +- s = external_global_sym(t, &func_old_type, 0); ++ external reference to int(st) function */ ++ if (st->warn_implicit_function_declaration) ++ warning(st, "implicit declaration of function '%s'", ++ get_tok_str(st, t, NULL)); ++ s = external_global_sym(st, t, &func_old_type, 0); + } + if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) == + (VT_STATIC | VT_INLINE | VT_FUNC)) { +@@ -7331,12 +6610,12 @@ + compilation unit. Inline function as always + generated in the text section. */ + if (!s->c) +- put_extern_sym(s, text_section, 0, 0); ++ put_extern_sym(st, s, text_section, 0, 0); + r = VT_SYM | VT_CONST; + } else { + r = s->r; + } +- vset(&s->type, r, s->c); ++ vset(st, &s->type, r, s->c); + /* if forward reference, we must point to s */ + if (vtop->r & VT_SYM) { + vtop->sym = s; +@@ -7348,18 +6627,18 @@ + /* post operations */ + while (1) { + if (tok == TOK_INC || tok == TOK_DEC) { +- inc(1, tok); +- next(); ++ inc(st, 1, tok); ++ next(st); + } else if (tok == '.' || tok == TOK_ARROW) { + /* field */ + if (tok == TOK_ARROW) +- indir(); +- test_lvalue(); +- gaddrof(); +- next(); ++ indir(st); ++ test_lvalue(st); ++ gaddrof(st); ++ next(st); + /* expect pointer on structure */ + if ((vtop->type.t & VT_BTYPE) != VT_STRUCT) +- expect("struct or union"); ++ expect(st, "struct or union"); + s = vtop->type.ref; + /* find field */ + tok |= SYM_FIELD; +@@ -7368,27 +6647,27 @@ + break; + } + if (!s) +- error("field not found"); ++ tcc_error(st, "field not found"); + /* add field offset to pointer */ + vtop->type = char_pointer_type; /* change type to 'char *' */ +- vpushi(s->c); +- gen_op('+'); ++ vpushi(st, s->c); ++ gen_op(st, '+'); + /* change type to field type, and set to lvalue */ + vtop->type = s->type; + /* an array is never an lvalue */ + if (!(vtop->type.t & VT_ARRAY)) { +- vtop->r |= lvalue_type(vtop->type.t); ++ vtop->r |= lvalue_type(st, vtop->type.t); + /* if bound checking, the referenced pointer must be checked */ + if (do_bounds_check) + vtop->r |= VT_MUSTBOUND; + } +- next(); ++ next(st); + } else if (tok == '[') { +- next(); +- gexpr(); +- gen_op('+'); +- indir(); +- skip(']'); ++ next(st); ++ gexpr(st); ++ gen_op(st, '+'); ++ indir(st); ++ skip(st, ']'); + } else if (tok == '(') { + SValue ret; + Sym *sa; +@@ -7398,38 +6677,38 @@ + if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { + /* pointer test (no array accepted) */ + if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) { +- vtop->type = *pointed_type(&vtop->type); ++ vtop->type = *pointed_type(st, &vtop->type); + if ((vtop->type.t & VT_BTYPE) != VT_FUNC) + goto error_func; + } else { + error_func: +- expect("function pointer"); ++ expect(st, "function pointer"); + } + } else { + vtop->r &= ~VT_LVAL; /* no lvalue */ + } + /* get return type */ + s = vtop->type.ref; +- next(); ++ next(st); + sa = s->next; /* first parameter */ + nb_args = 0; + /* compute first implicit argument if a structure is returned */ + if ((s->type.t & VT_BTYPE) == VT_STRUCT) { + /* get some space for the returned structure */ +- size = type_size(&s->type, &align); ++ size = type_size(st, &s->type, &align); + loc = (loc - size) & -align; + ret.type = s->type; + ret.r = VT_LOCAL | VT_LVAL; + /* pass it as 'int' to avoid structure arg passing + problems */ +- vseti(VT_LOCAL, loc); ++ vseti(st, VT_LOCAL, loc); + ret.c = vtop->c; + nb_args++; + } else { + ret.type = s->type; + ret.r2 = VT_CONST; + /* return in register */ +- if (is_float(ret.type.t)) { ++ if (is_float(st, ret.type.t)) { + ret.r = REG_FRET; + } else { + if ((ret.type.t & VT_BTYPE) == VT_LLONG) +@@ -7440,26 +6719,23 @@ + } + if (tok != ')') { + for(;;) { +- expr_eq(); +- gfunc_param_typed(s, sa); ++ expr_eq(st); ++ gfunc_param_typed(st, s, sa); + nb_args++; + if (sa) + sa = sa->next; + if (tok == ')') + break; +- skip(','); ++ skip(st, ','); + } + } + if (sa) +- error("too few arguments to function"); +- skip(')'); +- if (!nocode_wanted) { +- gfunc_call(nb_args); +- } else { +- vtop -= (nb_args + 1); +- } ++ tcc_error(st, "too few arguments to function"); ++ skip(st, ')'); ++ if (cur_text_section) gfunc_call(st, nb_args); ++ else vtop -= (nb_args + 1); + /* return value */ +- vsetc(&ret.type, ret.r, &ret.c); ++ vsetc(st, &ret.type, ret.r, &ret.c); + vtop->r2 = ret.r2; + } else { + break; +@@ -7467,188 +6743,190 @@ + } + } + +-static void uneq(void) ++static void uneq(TCCState *st) + { + int t; + +- unary(); ++ unary(st); + if (tok == '=' || + (tok >= TOK_A_MOD && tok <= TOK_A_DIV) || + tok == TOK_A_XOR || tok == TOK_A_OR || + tok == TOK_A_SHL || tok == TOK_A_SAR) { +- test_lvalue(); ++ test_lvalue(st); + t = tok; +- next(); ++ next(st); + if (t == '=') { +- expr_eq(); ++ expr_eq(st); + } else { +- vdup(); +- expr_eq(); +- gen_op(t & 0x7f); ++ vdup(st); ++ expr_eq(st); ++ gen_op(st, t & 0x7f); + } +- vstore(); ++ vstore(st); + } + } + +-static void expr_prod(void) ++static void expr_prod(TCCState *st) + { + int t; + +- uneq(); ++ uneq(st); + while (tok == '*' || tok == '/' || tok == '%') { + t = tok; +- next(); +- uneq(); +- gen_op(t); ++ next(st); ++ uneq(st); ++ gen_op(st, t); + } + } + +-static void expr_sum(void) ++static void expr_sum(TCCState *st) + { + int t; + +- expr_prod(); ++ expr_prod(st); + while (tok == '+' || tok == '-') { + t = tok; +- next(); +- expr_prod(); +- gen_op(t); ++ next(st); ++ expr_prod(st); ++ gen_op(st, t); + } + } + +-static void expr_shift(void) ++static void expr_shift(TCCState *st) + { + int t; + +- expr_sum(); ++ expr_sum(st); + while (tok == TOK_SHL || tok == TOK_SAR) { + t = tok; +- next(); +- expr_sum(); +- gen_op(t); ++ next(st); ++ expr_sum(st); ++ gen_op(st, t); + } + } + +-static void expr_cmp(void) ++static void expr_cmp(TCCState *st) + { + int t; + +- expr_shift(); ++ expr_shift(st); + while ((tok >= TOK_ULE && tok <= TOK_GT) || + tok == TOK_ULT || tok == TOK_UGE) { + t = tok; +- next(); +- expr_shift(); +- gen_op(t); ++ next(st); ++ expr_shift(st); ++ gen_op(st, t); + } + } + +-static void expr_cmpeq(void) ++static void expr_cmpeq(TCCState *st) + { + int t; + +- expr_cmp(); ++ expr_cmp(st); + while (tok == TOK_EQ || tok == TOK_NE) { + t = tok; +- next(); +- expr_cmp(); +- gen_op(t); ++ next(st); ++ expr_cmp(st); ++ gen_op(st, t); + } + } + +-static void expr_and(void) ++static void expr_and(TCCState *st) + { +- expr_cmpeq(); ++ expr_cmpeq(st); + while (tok == '&') { +- next(); +- expr_cmpeq(); +- gen_op('&'); ++ next(st); ++ expr_cmpeq(st); ++ gen_op(st, '&'); + } + } + +-static void expr_xor(void) ++static void expr_xor(TCCState *st) + { +- expr_and(); ++ expr_and(st); + while (tok == '^') { +- next(); +- expr_and(); +- gen_op('^'); ++ next(st); ++ expr_and(st); ++ gen_op(st, '^'); + } + } + +-static void expr_or(void) ++static void expr_or(TCCState *st) + { +- expr_xor(); ++ expr_xor(st); + while (tok == '|') { +- next(); +- expr_xor(); +- gen_op('|'); ++ next(st); ++ expr_xor(st); ++ gen_op(st, '|'); + } + } + + /* XXX: fix this mess */ +-static void expr_land_const(void) ++static void expr_land_const(TCCState *st) + { +- expr_or(); ++ expr_or(st); + while (tok == TOK_LAND) { +- next(); +- expr_or(); +- gen_op(TOK_LAND); ++ next(st); ++ expr_or(st); ++ gen_op(st, TOK_LAND); + } + } + + /* XXX: fix this mess */ +-static void expr_lor_const(void) ++static void expr_lor_const(TCCState *st) + { +- expr_land_const(); ++ expr_land_const(st); + while (tok == TOK_LOR) { +- next(); +- expr_land_const(); +- gen_op(TOK_LOR); ++ next(st); ++ expr_land_const(st); ++ gen_op(st, TOK_LOR); + } + } + + /* only used if non constant */ +-static void expr_land(void) ++static void expr_land(TCCState *st) + { + int t; + +- expr_or(); ++ expr_or(st); + if (tok == TOK_LAND) { + t = 0; ++ save_regs(st, 1); + for(;;) { +- t = gtst(1, t); ++ t = gtst(st, 1, t); + if (tok != TOK_LAND) { +- vseti(VT_JMPI, t); ++ vseti(st, VT_JMPI, t); + break; + } +- next(); +- expr_or(); ++ next(st); ++ expr_or(st); + } + } + } + +-static void expr_lor(void) ++static void expr_lor(TCCState *st) + { + int t; + +- expr_land(); ++ expr_land(st); + if (tok == TOK_LOR) { + t = 0; ++ save_regs(st, 1); + for(;;) { +- t = gtst(0, t); ++ t = gtst(st, 0, t); + if (tok != TOK_LOR) { +- vseti(VT_JMP, t); ++ vseti(st, VT_JMP, t); + break; + } +- next(); +- expr_land(); ++ next(st); ++ expr_land(st); + } + } + } + + /* XXX: better constant handling */ +-static void expr_eq(void) ++static void expr_eq(TCCState *st) + { + int tt, u, r1, r2, rc, t1, t2, bt1, bt2; + SValue sv; +@@ -7656,51 +6934,51 @@ + + if (const_wanted) { + int c1, c; +- expr_lor_const(); ++ expr_lor_const(st); + if (tok == '?') { + c = vtop->c.i; +- vpop(); +- next(); ++ vpop(st); ++ next(st); + if (tok == ':' && gnu_ext) { + c1 = c; + } else { +- gexpr(); ++ gexpr(st); + c1 = vtop->c.i; +- vpop(); ++ vpop(st); + } +- skip(':'); +- expr_eq(); ++ skip(st, ':'); ++ expr_eq(st); + if (c) + vtop->c.i = c1; + } + } else { +- expr_lor(); ++ expr_lor(st); + if (tok == '?') { +- next(); ++ next(st); + if (vtop != vstack) { + /* needed to avoid having different registers saved in + each branch */ +- if (is_float(vtop->type.t)) ++ if (is_float(st, vtop->type.t)) + rc = RC_FLOAT; + else + rc = RC_INT; +- gv(rc); +- save_regs(1); ++ gv(st, rc); ++ save_regs(st, 1); + } + if (tok == ':' && gnu_ext) { +- gv_dup(); +- tt = gtst(1, 0); ++ gv_dup(st); ++ tt = gtst(st, 1, 0); + } else { +- tt = gtst(1, 0); +- gexpr(); ++ tt = gtst(st, 1, 0); ++ gexpr(st); + } + type1 = vtop->type; + sv = *vtop; /* save value to handle it later */ + vtop--; /* no vpop so that FP stack is not flushed */ +- skip(':'); +- u = gjmp(0); ++ skip(st, ':'); ++ u = gjmp(st, 0); + gsym(tt); +- expr_eq(); ++ expr_eq(st); + type2 = vtop->type; + + t1 = type1.t; +@@ -7708,7 +6986,7 @@ + t2 = type2.t; + bt2 = t2 & VT_BTYPE; + /* cast operands to correct type according to ISOC rules */ +- if (is_float(bt1) || is_float(bt2)) { ++ if (is_float(st, bt1) || is_float(st, bt2)) { + if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) { + type.t = VT_LDOUBLE; + } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) { +@@ -7726,6 +7004,9 @@ + } else if (bt1 == VT_PTR || bt2 == VT_PTR) { + /* XXX: test pointer compatibility */ + type = type1; ++ } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { ++ /* XXX: test function pointer compatibility */ ++ type = type1; + } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { + /* XXX: test structure compatibility */ + type = type1; +@@ -7742,9 +7023,11 @@ + } + + /* now we convert second operand */ +- gen_cast(&type); ++ gen_cast(st, &type); ++ if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) ++ gaddrof(st); + rc = RC_INT; +- if (is_float(type.t)) { ++ if (is_float(st, type.t)) { + rc = RC_FLOAT; + } else if ((type.t & VT_BTYPE) == VT_LLONG) { + /* for long longs, we use fixed registers to avoid having +@@ -7752,85 +7035,85 @@ + rc = RC_IRET; + } + +- r2 = gv(rc); ++ r2 = gv(st, rc); + /* this is horrible, but we must also convert first + operand */ +- tt = gjmp(0); ++ tt = gjmp(st, 0); + gsym(u); + /* put again first value and cast it */ + *vtop = sv; +- gen_cast(&type); +- r1 = gv(rc); +- move_reg(r2, r1); ++ gen_cast(st, &type); ++ if (VT_STRUCT == (vtop->type.t & VT_BTYPE)) ++ gaddrof(st); ++ r1 = gv(st, rc); ++ move_reg(st, r2, r1); + vtop->r = r2; + gsym(tt); + } + } + } + +-static void gexpr(void) ++static void gexpr(TCCState *st) + { + while (1) { +- expr_eq(); ++ expr_eq(st); + if (tok != ',') + break; +- vpop(); +- next(); ++ vpop(st); ++ next(st); + } + } + + /* parse an expression and return its type without any side effect. */ +-static void expr_type(CType *type) ++static void expr_type(TCCState *st, CType *type) + { +- int saved_nocode_wanted; ++ Section *saved_text_section = cur_text_section; + +- saved_nocode_wanted = nocode_wanted; +- nocode_wanted = 1; +- gexpr(); ++ cur_text_section = NULL; ++ gexpr(st); + *type = vtop->type; +- vpop(); +- nocode_wanted = saved_nocode_wanted; ++ vpop(st); ++ cur_text_section = saved_text_section; + } + + /* parse a unary expression and return its type without any side + effect. */ +-static void unary_type(CType *type) ++static void unary_type(TCCState *st, CType *type) + { +- int a; ++ Section *saved_text_section = cur_text_section; + +- a = nocode_wanted; +- nocode_wanted = 1; +- unary(); ++ cur_text_section = NULL; ++ unary(st); + *type = vtop->type; +- vpop(); +- nocode_wanted = a; ++ vpop(st); ++ cur_text_section = saved_text_section; + } + + /* parse a constant expression and return value in vtop. */ +-static void expr_const1(void) ++static void expr_const1(TCCState *st) + { + int a; + a = const_wanted; + const_wanted = 1; +- expr_eq(); ++ expr_eq(st); + const_wanted = a; + } + + /* parse an integer constant and return its value. */ +-static int expr_const(void) ++static int expr_const(TCCState *st) + { + int c; +- expr_const1(); ++ expr_const1(st); + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) +- expect("constant expression"); ++ expect(st, "constant expression"); + c = vtop->c.i; +- vpop(); ++ vpop(st); + return c; + } + + /* return the label token if current token is a label, otherwise + return zero */ +-static int is_label(void) ++static int is_label(TCCState *st) + { + int last_tok; + +@@ -7839,17 +7122,17 @@ + return 0; + /* no need to save tokc because tok is an identifier */ + last_tok = tok; +- next(); ++ next(st); + if (tok == ':') { +- next(); ++ next(st); + return last_tok; + } else { +- unget_tok(last_tok); ++ unget_tok(st, last_tok); + return 0; + } + } + +-static void block(int *bsym, int *csym, int *case_sym, int *def_sym, ++static void block(TCCState *st, int *bsym, int *csym, int *case_sym, int *def_sym, + int case_reg, int is_expr) + { + int a, b, c, d; +@@ -7858,181 +7141,204 @@ + /* generate line number info */ + if (do_debug && + (last_line_num != file->line_num || last_ind != ind)) { +- put_stabn(N_SLINE, 0, file->line_num, ind - func_ind); ++ put_stabn(st, N_SLINE, 0, file->line_num, ind - func_ind); + last_ind = ind; + last_line_num = file->line_num; + } + + if (is_expr) { + /* default return value is (void) */ +- vpushi(0); ++ vpushi(st, 0); + vtop->type.t = VT_VOID; + } + + if (tok == TOK_IF) { + /* if test */ +- next(); +- skip('('); +- gexpr(); +- skip(')'); +- a = gtst(1, 0); +- block(bsym, csym, case_sym, def_sym, case_reg, 0); ++ next(st); ++ skip(st, '('); ++ gexpr(st); ++ skip(st, ')'); ++ a = gtst(st, 1, 0); ++ block(st, bsym, csym, case_sym, def_sym, case_reg, 0); + c = tok; + if (c == TOK_ELSE) { +- next(); +- d = gjmp(0); ++ next(st); ++ d = gjmp(st, 0); + gsym(a); +- block(bsym, csym, case_sym, def_sym, case_reg, 0); ++ block(st, bsym, csym, case_sym, def_sym, case_reg, 0); + gsym(d); /* patch else jmp */ + } else + gsym(a); + } else if (tok == TOK_WHILE) { +- next(); ++ next(st); + d = ind; +- skip('('); +- gexpr(); +- skip(')'); +- a = gtst(1, 0); ++ skip(st, '('); ++ gexpr(st); ++ skip(st, ')'); ++ a = gtst(st, 1, 0); + b = 0; +- block(&a, &b, case_sym, def_sym, case_reg, 0); +- gjmp_addr(d); ++ block(st, &a, &b, case_sym, def_sym, case_reg, 0); ++ gjmp_addr(st, d); + gsym(a); + gsym_addr(b, d); + } else if (tok == '{') { + Sym *llabel; + +- next(); ++ next(st); + /* record local declaration stack position */ + s = local_stack; + llabel = local_label_stack; + /* handle local labels declarations */ + if (tok == TOK_LABEL) { +- next(); ++ next(st); + for(;;) { + if (tok < TOK_UIDENT) +- expect("label identifier"); +- label_push(&local_label_stack, tok, LABEL_DECLARED); +- next(); ++ expect(st, "label identifier"); ++ label_push(st, &local_label_stack, tok, LABEL_DECLARED); ++ next(st); + if (tok == ',') { +- next(); ++ next(st); + } else { +- skip(';'); ++ skip(st, ';'); + break; + } + } + } + while (tok != '}') { +- decl(VT_LOCAL); ++ decl(st, VT_LOCAL); + if (tok != '}') { + if (is_expr) +- vpop(); +- block(bsym, csym, case_sym, def_sym, case_reg, is_expr); ++ vpop(st); ++ block(st, bsym, csym, case_sym, def_sym, case_reg, is_expr); + } + } + /* pop locally defined labels */ +- label_pop(&local_label_stack, llabel); ++ label_pop(st, &local_label_stack, llabel); + /* pop locally defined symbols */ +- sym_pop(&local_stack, s); +- next(); ++ sym_pop(st, &local_stack, s); ++ next(st); + } else if (tok == TOK_RETURN) { +- next(); ++ next(st); + if (tok != ';') { +- gexpr(); +- gen_assign_cast(&func_vt); ++ gexpr(st); ++ gen_assign_cast(st, &func_vt); + if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { + CType type; + /* if returning structure, must copy it to implicit + first pointer arg location */ ++#ifdef TCC_ARM_EABI ++ int align, size; ++ size = type_size(st, &func_vt,&align); ++ if(size <= 4) { ++ if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3)) ++ && (align & 3)) ++ { ++ int addr; ++ loc = (loc - size) & -4; ++ addr = loc; + type = func_vt; +- mk_pointer(&type); +- vset(&type, VT_LOCAL | VT_LVAL, func_vc); +- indir(); +- vswap(); +- /* copy structure value to pointer */ +- vstore(); +- } else if (is_float(func_vt.t)) { +- gv(RC_FRET); ++ vset(st, &type, VT_LOCAL | VT_LVAL, addr); ++ vswap(st); ++ vstore(st); ++ vset(st, &int_type, VT_LOCAL | VT_LVAL, addr); ++ } ++ vtop->type = int_type; ++ gv(st, RC_IRET); + } else { +- gv(RC_IRET); ++#endif ++ type = func_vt; ++ mk_pointer(st, &type); ++ vset(st, &type, VT_LOCAL | VT_LVAL, func_vc); ++ indir(st); ++ vswap(st); ++ /* copy structure value to pointer */ ++ vstore(st); ++#ifdef TCC_ARM_EABI + } +- vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ ++#endif ++ } else if (is_float(st, func_vt.t)) { ++ gv(st, RC_FRET); ++ } else { ++ gv(st, RC_IRET); ++ } ++ vtop--; /* NOT vpop(st) because on x86 it would flush the fp stack */ + } +- skip(';'); +- rsym = gjmp(rsym); /* jmp */ ++ skip(st, ';'); ++ rsym = gjmp(st, rsym); /* jmp */ + } else if (tok == TOK_BREAK) { + /* compute jump */ + if (!bsym) +- error("cannot break"); +- *bsym = gjmp(*bsym); +- next(); +- skip(';'); ++ tcc_error(st, "cannot break"); ++ *bsym = gjmp(st, *bsym); ++ next(st); ++ skip(st, ';'); + } else if (tok == TOK_CONTINUE) { + /* compute jump */ + if (!csym) +- error("cannot continue"); +- *csym = gjmp(*csym); +- next(); +- skip(';'); ++ tcc_error(st, "cannot continue"); ++ *csym = gjmp(st, *csym); ++ next(st); ++ skip(st, ';'); + } else if (tok == TOK_FOR) { + int e; +- next(); +- skip('('); ++ next(st); ++ skip(st, '('); + if (tok != ';') { +- gexpr(); +- vpop(); ++ gexpr(st); ++ vpop(st); + } +- skip(';'); ++ skip(st, ';'); + d = ind; + c = ind; + a = 0; + b = 0; + if (tok != ';') { +- gexpr(); +- a = gtst(1, 0); ++ gexpr(st); ++ a = gtst(st, 1, 0); + } +- skip(';'); ++ skip(st, ';'); + if (tok != ')') { +- e = gjmp(0); ++ e = gjmp(st, 0); + c = ind; +- gexpr(); +- vpop(); +- gjmp_addr(d); ++ gexpr(st); ++ vpop(st); ++ gjmp_addr(st, d); + gsym(e); + } +- skip(')'); +- block(&a, &b, case_sym, def_sym, case_reg, 0); +- gjmp_addr(c); ++ skip(st, ')'); ++ block(st, &a, &b, case_sym, def_sym, case_reg, 0); ++ gjmp_addr(st, c); + gsym(a); + gsym_addr(b, c); + } else + if (tok == TOK_DO) { +- next(); ++ next(st); + a = 0; + b = 0; + d = ind; +- block(&a, &b, case_sym, def_sym, case_reg, 0); +- skip(TOK_WHILE); +- skip('('); ++ block(st, &a, &b, case_sym, def_sym, case_reg, 0); ++ skip(st, TOK_WHILE); ++ skip(st, '('); + gsym(b); +- gexpr(); +- c = gtst(0, 0); ++ gexpr(st); ++ c = gtst(st, 0, 0); + gsym_addr(c, d); +- skip(')'); ++ skip(st, ')'); + gsym(a); +- skip(';'); ++ skip(st, ';'); + } else + if (tok == TOK_SWITCH) { +- next(); +- skip('('); +- gexpr(); ++ next(st); ++ skip(st, '('); ++ gexpr(st); + /* XXX: other types than integer */ +- case_reg = gv(RC_INT); +- vpop(); +- skip(')'); ++ case_reg = gv(st, RC_INT); ++ vpop(st); ++ skip(st, ')'); + a = 0; +- b = gjmp(0); /* jump to first case */ ++ b = gjmp(st, 0); /* jump to first case */ + c = 0; +- block(&a, csym, &b, &c, case_reg, 0); ++ block(st, &a, csym, &b, &c, case_reg, 0); + /* if no default, jmp after switch */ + if (c == 0) + c = ind; +@@ -8044,113 +7350,118 @@ + if (tok == TOK_CASE) { + int v1, v2; + if (!case_sym) +- expect("switch"); +- next(); +- v1 = expr_const(); ++ expect(st, "switch"); ++ /* since a case is like a label, we must skip it with a jmp */ ++ b = gjmp(st, 0); ++ next_case: ++ next(st); ++ v1 = expr_const(st); + v2 = v1; + if (gnu_ext && tok == TOK_DOTS) { +- next(); +- v2 = expr_const(); ++ next(st); ++ v2 = expr_const(st); + if (v2 < v1) +- warning("empty case range"); ++ warning(st, "empty case range"); + } +- /* since a case is like a label, we must skip it with a jmp */ +- b = gjmp(0); + gsym(*case_sym); +- vseti(case_reg, 0); +- vpushi(v1); ++ vseti(st, case_reg, 0); ++ vpushi(st, v1); + if (v1 == v2) { +- gen_op(TOK_EQ); +- *case_sym = gtst(1, 0); ++ gen_op(st, TOK_EQ); ++ *case_sym = 0; + } else { +- gen_op(TOK_GE); +- *case_sym = gtst(1, 0); +- vseti(case_reg, 0); +- vpushi(v2); +- gen_op(TOK_LE); +- *case_sym = gtst(1, *case_sym); ++ gen_op(st, TOK_GE); ++ *case_sym = gtst(st, 1, 0); ++ vseti(st, case_reg, 0); ++ vpushi(st, v2); ++ gen_op(st, TOK_LE); + } ++ skip(st, ':'); ++ if (tok == TOK_CASE) { ++ b = gtst(st, 0, b); ++ goto next_case; ++ } ++ *case_sym = gtst(st, 1, *case_sym); + gsym(b); +- skip(':'); + is_expr = 0; + goto block_after_label; + } else + if (tok == TOK_DEFAULT) { +- next(); +- skip(':'); ++ next(st); ++ skip(st, ':'); + if (!def_sym) +- expect("switch"); ++ expect(st, "switch"); + if (*def_sym) +- error("too many 'default'"); ++ tcc_error(st, "too many 'default'"); + *def_sym = ind; + is_expr = 0; + goto block_after_label; + } else + if (tok == TOK_GOTO) { +- next(); ++ next(st); + if (tok == '*' && gnu_ext) { + /* computed goto */ +- next(); +- gexpr(); ++ next(st); ++ gexpr(st); + if ((vtop->type.t & VT_BTYPE) != VT_PTR) +- expect("pointer"); +- ggoto(); ++ expect(st, "pointer"); ++ ggoto(st); + } else if (tok >= TOK_UIDENT) { +- s = label_find(tok); ++ s = label_find(st, tok); + /* put forward definition if needed */ + if (!s) { +- s = label_push(&global_label_stack, tok, LABEL_FORWARD); ++ s = label_push(st, &global_label_stack, tok, LABEL_FORWARD); + } else { + if (s->r == LABEL_DECLARED) + s->r = LABEL_FORWARD; + } + /* label already defined */ + if (s->r & LABEL_FORWARD) +- s->next = (void *)gjmp((long)s->next); ++ s->next = (void *)gjmp(st, (long)s->next); + else +- gjmp_addr((long)s->next); +- next(); ++ gjmp_addr(st, (long)s->next); ++ next(st); + } else { +- expect("label identifier"); ++ expect(st, "label identifier"); + } +- skip(';'); ++ skip(st, ';'); + } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) { +- asm_instr(); ++ asm_instr(st); + } else { +- b = is_label(); ++ b = is_label(st); + if (b) { + /* label case */ +- s = label_find(b); ++ s = label_find(st, b); + if (s) { + if (s->r == LABEL_DEFINED) +- error("duplicate label '%s'", get_tok_str(s->v, NULL)); ++ tcc_error(st, "duplicate label '%s'", get_tok_str(st, s->v, NULL)); + gsym((long)s->next); + s->r = LABEL_DEFINED; + } else { +- s = label_push(&global_label_stack, b, LABEL_DEFINED); ++ s = label_push(st, &global_label_stack, b, LABEL_DEFINED); + } + s->next = (void *)ind; + /* we accept this, but it is a mistake */ + block_after_label: + if (tok == '}') { +- warning("deprecated use of label at end of compound statement"); ++ warning(st, "deprecated use of label at end of compound statement"); + } else { + if (is_expr) +- vpop(); +- block(bsym, csym, case_sym, def_sym, case_reg, is_expr); ++ vpop(st); ++ block(st, bsym, csym, case_sym, def_sym, case_reg, is_expr); + } + } else { + /* expression case */ + if (tok != ';') { + if (is_expr) { +- vpop(); +- gexpr(); ++ vpop(st); ++ gexpr(st); + } else { +- gexpr(); +- vpop(); ++ gexpr(st); ++ vpop(st); + } + } +- skip(';'); ++ skip(st, ';'); + } + } + } +@@ -8159,7 +7470,7 @@ + address. cur_index/cur_field is the pointer to the current + value. 'size_only' is true if only size info is needed (only used + in arrays) */ +-static void decl_designator(CType *type, Section *sec, unsigned long c, ++static void decl_designator(TCCState *st, CType *type, Section *sec, unsigned long c, + int *cur_index, Sym **cur_field, + int size_only) + { +@@ -8170,32 +7481,32 @@ + notfirst = 0; + elem_size = 0; + nb_elems = 1; +- if (gnu_ext && (l = is_label()) != 0) ++ if (gnu_ext && (l = is_label(st)) != 0) + goto struct_field; + while (tok == '[' || tok == '.') { + if (tok == '[') { + if (!(type->t & VT_ARRAY)) +- expect("array type"); ++ expect(st, "array type"); + s = type->ref; +- next(); +- index = expr_const(); ++ next(st); ++ index = expr_const(st); + if (index < 0 || (s->c >= 0 && index >= s->c)) +- expect("invalid index"); ++ expect(st, "invalid index"); + if (tok == TOK_DOTS && gnu_ext) { +- next(); +- index_last = expr_const(); ++ next(st); ++ index_last = expr_const(st); + if (index_last < 0 || + (s->c >= 0 && index_last >= s->c) || + index_last < index) +- expect("invalid index"); ++ expect(st, "invalid index"); + } else { + index_last = index; + } +- skip(']'); ++ skip(st, ']'); + if (!notfirst) + *cur_index = index_last; +- type = pointed_type(type); +- elem_size = type_size(type, &align); ++ type = pointed_type(st, type); ++ elem_size = type_size(st, type, &align); + c += index * elem_size; + /* NOTE: we only support ranges for last designator */ + nb_elems = index_last - index + 1; +@@ -8204,12 +7515,12 @@ + break; + } + } else { +- next(); ++ next(st); + l = tok; +- next(); ++ next(st); + struct_field: + if ((type->t & VT_BTYPE) != VT_STRUCT) +- expect("struct/union type"); ++ expect(st, "struct/union type"); + s = type->ref; + l |= SYM_FIELD; + f = s->next; +@@ -8219,7 +7530,7 @@ + f = f->next; + } + if (!f) +- expect("field"); ++ expect(st, "field"); + if (!notfirst) + *cur_field = f; + /* XXX: fix this mess by using explicit storage field */ +@@ -8232,20 +7543,20 @@ + } + if (notfirst) { + if (tok == '=') { +- next(); ++ next(st); + } else { + if (!gnu_ext) +- expect("="); ++ expect(st, "="); + } + } else { + if (type->t & VT_ARRAY) { + index = *cur_index; +- type = pointed_type(type); +- c += index * type_size(type, &align); ++ type = pointed_type(st, type); ++ c += index * type_size(st, type, &align); + } else { + f = *cur_field; + if (!f) +- error("too many field init"); ++ tcc_error(st, "too many field init"); + /* XXX: fix this mess by using explicit storage field */ + type1 = f->type; + type1.t |= (type->t & ~VT_TYPE); +@@ -8253,7 +7564,7 @@ + c += f->c; + } + } +- decl_initializer(type, sec, c, 0, size_only); ++ decl_initializer(st, type, sec, c, 0, size_only); + + /* XXX: make it more general */ + if (!size_only && nb_elems > 1) { +@@ -8262,10 +7573,10 @@ + int i; + + if (!sec) +- error("range init not supported yet for dynamic storage"); ++ tcc_error(st, "range init not supported yet for dynamic storage"); + c_end = c + nb_elems * elem_size; + if (c_end > sec->data_allocated) +- section_realloc(sec, c_end); ++ section_realloc(st, sec, c_end); + src = sec->data + c; + dst = src; + for(i = 1; i < nb_elems; i++) { +@@ -8280,7 +7591,7 @@ + #define EXPR_ANY 2 + + /* store a value or an expression directly in global data or in local array */ +-static void init_putv(CType *type, Section *sec, unsigned long c, ++static void init_putv(TCCState *st, CType *type, Section *sec, unsigned long c, + int v, int expr_type) + { + int saved_global_expr, bt, bit_pos, bit_size; +@@ -8290,20 +7601,20 @@ + + switch(expr_type) { + case EXPR_VAL: +- vpushi(v); ++ vpushi(st, v); + break; + case EXPR_CONST: + /* compound literals must be allocated globally in this case */ + saved_global_expr = global_expr; + global_expr = 1; +- expr_const1(); ++ expr_const1(st); + global_expr = saved_global_expr; + /* NOTE: symbols are accepted */ + if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST) +- error("initializer element is not constant"); ++ tcc_error(st, "initializer element is not constant"); + break; + case EXPR_ANY: +- expr_eq(); ++ expr_eq(st); + break; + } + +@@ -8313,7 +7624,7 @@ + if (sec) { + /* XXX: not portable */ + /* XXX: generate error if incorrect relocation */ +- gen_assign_cast(&dtype); ++ gen_assign_cast(st, &dtype); + bt = type->t & VT_BTYPE; + ptr = sec->data + c; + /* XXX: make code faster ? */ +@@ -8333,7 +7644,7 @@ + bt == VT_LDOUBLE || + bt == VT_LLONG || + (bt == VT_INT && bit_size != 32))) +- error("initializer element is not computable at load time"); ++ tcc_error(st, "initializer element is not computable at load time"); + switch(bt) { + case VT_BYTE: + *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos; +@@ -8352,31 +7663,31 @@ + break; + default: + if (vtop->r & VT_SYM) { +- greloc(sec, vtop->sym, c, R_DATA_32); ++ greloc(st, sec, vtop->sym, c, R_DATA_32); + } + *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos; + break; + } + vtop--; + } else { +- vset(&dtype, VT_LOCAL, c); +- vswap(); +- vstore(); +- vpop(); ++ vset(st, &dtype, VT_LOCAL|VT_LVAL, c); ++ vswap(st); ++ vstore(st); ++ vpop(st); + } + } + + /* put zeros for variable based init */ +-static void init_putz(CType *t, Section *sec, unsigned long c, int size) ++static void init_putz(TCCState *st, CType *t, Section *sec, unsigned long c, int size) + { + if (sec) { + /* nothing to do because globals are already set to zero */ + } else { +- vpush_global_sym(&func_old_type, TOK_memset); +- vseti(VT_LOCAL, c); +- vpushi(0); +- vpushi(size); +- gfunc_call(3); ++ vpush_global_sym(st, &func_old_type, TOK_memset); ++ vseti(st, VT_LOCAL, c); ++ vpushi(st, 0); ++ vpushi(st, size); ++ gfunc_call(st, 3); + } + } + +@@ -8385,7 +7696,7 @@ + allocation. 'first' is true if array '{' must be read (multi + dimension implicit array init handling). 'size_only' is true if + size only evaluation is wanted (only for arrays). */ +-static void decl_initializer(CType *type, Section *sec, unsigned long c, ++static void decl_initializer(TCCState *st, CType *type, Section *sec, unsigned long c, + int first, int size_only) + { + int index, array_length, n, no_oblock, nb, parlevel, i; +@@ -8397,20 +7708,24 @@ + s = type->ref; + n = s->c; + array_length = 0; +- t1 = pointed_type(type); +- size1 = type_size(t1, &align1); ++ t1 = pointed_type(st, type); ++ size1 = type_size(st, t1, &align1); + + no_oblock = 1; + if ((first && tok != TOK_LSTR && tok != TOK_STR) || + tok == '{') { +- skip('{'); ++ skip(st, '{'); + no_oblock = 0; + } + + /* only parse strings here if correct type (otherwise: handle + them as ((w)char *) expressions */ + if ((tok == TOK_LSTR && ++#ifdef WIN32 ++ (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)) || ++#else + (t1->t & VT_BTYPE) == VT_INT) || ++#endif + (tok == TOK_STR && + (t1->t & VT_BTYPE) == VT_BYTE)) { + while (tok == TOK_STR || tok == TOK_LSTR) { +@@ -8422,14 +7737,14 @@ + if (tok == TOK_STR) + cstr_len = cstr->size; + else +- cstr_len = cstr->size / sizeof(int); ++ cstr_len = cstr->size / sizeof(nwchar_t); + cstr_len--; + nb = cstr_len; + if (n >= 0 && nb > (n - array_length)) + nb = n - array_length; + if (!size_only) { + if (cstr_len > nb) +- warning("initializer-string for array is too long"); ++ warning(st, "initializer-string for array is too long"); + /* in order to go faster for common case (char + string in global variable, we handle it + specifically */ +@@ -8440,33 +7755,33 @@ + if (tok == TOK_STR) + ch = ((unsigned char *)cstr->data)[i]; + else +- ch = ((int *)cstr->data)[i]; +- init_putv(t1, sec, c + (array_length + i) * size1, ++ ch = ((nwchar_t *)cstr->data)[i]; ++ init_putv(st, t1, sec, c + (array_length + i) * size1, + ch, EXPR_VAL); + } + } + } + array_length += nb; +- next(); ++ next(st); + } + /* only add trailing zero if enough storage (no + warning in this case since it is standard) */ + if (n < 0 || array_length < n) { + if (!size_only) { +- init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL); ++ init_putv(st, t1, sec, c + (array_length * size1), 0, EXPR_VAL); + } + array_length++; + } + } else { + index = 0; + while (tok != '}') { +- decl_designator(type, sec, c, &index, NULL, size_only); ++ decl_designator(st, type, sec, c, &index, NULL, size_only); + if (n >= 0 && index >= n) +- error("index too large"); ++ tcc_error(st, "index too large"); + /* must put zero in holes (note that doing it that way + ensures that it even works with designators) */ + if (!size_only && array_length < index) { +- init_putz(t1, sec, c + array_length * size1, ++ init_putz(st, t1, sec, c + array_length * size1, + (index - array_length) * size1); + } + index++; +@@ -8479,14 +7794,14 @@ + break; + if (tok == '}') + break; +- skip(','); ++ skip(st, ','); + } + } + if (!no_oblock) +- skip('}'); ++ skip(st, '}'); + /* put zeros at the end */ + if (!size_only && n >= 0 && array_length < n) { +- init_putz(t1, sec, c + array_length * size1, ++ init_putz(st, t1, sec, c + array_length * size1, + (n - array_length) * size1); + } + /* patch type size if needed */ +@@ -8508,23 +7823,23 @@ + if (tok == '(') { + AttributeDef ad1; + CType type1; +- next(); ++ next(st); + while (tok == '(') { + par_count++; +- next(); ++ next(st); + } +- if (!parse_btype(&type1, &ad1)) +- expect("cast"); +- type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); ++ if (!parse_btype(st, &type1, &ad1)) ++ expect(st, "cast"); ++ type_decl(st, &type1, &ad1, &n, TYPE_ABSTRACT); + #if 0 + if (!is_assignable_types(type, &type1)) +- error("invalid type for cast"); ++ tcc_error(st, "invalid type for cast"); + #endif +- skip(')'); ++ skip(st, ')'); + } + no_oblock = 1; + if (first || tok == '{') { +- skip('{'); ++ skip(st, '{'); + no_oblock = 0; + } + s = type->ref; +@@ -8533,13 +7848,13 @@ + index = 0; + n = s->c; + while (tok != '}') { +- decl_designator(type, sec, c, NULL, &f, size_only); ++ decl_designator(st, type, sec, c, NULL, &f, size_only); + index = f->c; + if (!size_only && array_length < index) { +- init_putz(type, sec, c + array_length, ++ init_putz(st, type, sec, c + array_length, + index - array_length); + } +- index = index + type_size(&f->type, &align1); ++ index = index + type_size(st, &f->type, &align1); + if (index > array_length) + array_length = index; + f = f->next; +@@ -8547,23 +7862,23 @@ + break; + if (tok == '}') + break; +- skip(','); ++ skip(st, ','); + } + /* put zeros at the end */ + if (!size_only && array_length < n) { +- init_putz(type, sec, c + array_length, ++ init_putz(st, type, sec, c + array_length, + n - array_length); + } + if (!no_oblock) +- skip('}'); ++ skip(st, '}'); + while (par_count) { +- skip(')'); ++ skip(st, ')'); + par_count--; + } + } else if (tok == '{') { +- next(); +- decl_initializer(type, sec, c, first, size_only); +- skip('}'); ++ next(st); ++ decl_initializer(st, type, sec, c, first, size_only); ++ skip(st, '}'); + } else if (size_only) { + /* just skip expression */ + parlevel = 0; +@@ -8573,7 +7888,7 @@ + parlevel++; + else if (tok == ')') + parlevel--; +- next(); ++ next(st); + } + } else { + /* currently, we always use constant expression for globals +@@ -8581,7 +7896,7 @@ + expr_type = EXPR_CONST; + if (!sec) + expr_type = EXPR_ANY; +- init_putv(type, sec, c, 0, expr_type); ++ init_putv(st, type, sec, c, 0, expr_type); + } + } + +@@ -8592,7 +7907,7 @@ + parsed. If 'v' is zero, then a reference to the new object is put + in the value stack. If 'has_init' is 2, a special parsing is done + to handle string constants. */ +-static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, ++static void decl_initializer_alloc(TCCState *st, CType *type, AttributeDef *ad, int r, + int has_init, int v, int scope) + { + int size, align, addr, data_offset; +@@ -8601,30 +7916,30 @@ + TokenString init_str; + Section *sec; + +- size = type_size(type, &align); ++ size = type_size(st, type, &align); + /* If unknown size, we must evaluate it before + evaluating initializers because + initializers can generate global data too + (e.g. string pointers or ISOC99 compound + literals). It also simplifies local + initializers handling */ +- tok_str_new(&init_str); ++ tok_str_new(st, &init_str); + if (size < 0) { + if (!has_init) +- error("unknown type size"); ++ tcc_error(st, "unknown type size"); + /* get all init string */ + if (has_init == 2) { + /* only get strings */ + while (tok == TOK_STR || tok == TOK_LSTR) { +- tok_str_add_tok(&init_str); +- next(); ++ tok_str_add_tok(st, &init_str); ++ next(st); + } + } else { + level = 0; + while (level > 0 || (tok != ',' && tok != ';')) { + if (tok < 0) +- error("unexpected end of file in initializer"); +- tok_str_add_tok(&init_str); ++ tcc_error(st, "unexpected end of file in initializer"); ++ tok_str_add_tok(st, &init_str); + if (tok == '{') + level++; + else if (tok == '}') { +@@ -8632,26 +7947,26 @@ + break; + level--; + } +- next(); ++ next(st); + } + } +- tok_str_add(&init_str, -1); +- tok_str_add(&init_str, 0); ++ tok_str_add(st, &init_str, -1, 0); ++ tok_str_add(st, &init_str, 0, 0); + + /* compute size */ +- save_parse_state(&saved_parse_state); ++ save_parse_state(st, &saved_parse_state); + + macro_ptr = init_str.str; +- next(); +- decl_initializer(type, NULL, 0, 1, 1); ++ next(st); ++ decl_initializer(st, type, NULL, 0, 1, 1); + /* prepare second initializer parsing */ + macro_ptr = init_str.str; +- next(); ++ next(st); + + /* if still unknown size, error */ +- size = type_size(type, &align); ++ size = type_size(st, type, &align); + if (size < 0) +- error("unknown type size"); ++ tcc_error(st, "unknown type size"); + } + /* take into account specified alignment if bigger */ + if (ad->aligned) { +@@ -8674,16 +7989,16 @@ + /* add padding between regions */ + loc--; + /* then add local bound info */ +- bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long)); ++ bounds_ptr = section_ptr_add(st, lbounds_section, 2 * sizeof(unsigned long)); + bounds_ptr[0] = addr; + bounds_ptr[1] = size; + } + if (v) { + /* local variable */ +- sym_push(v, type, r, addr); ++ sym_push(st, v, type, r, addr); + } else { + /* push local reference */ +- vset(type, r, addr); ++ vset(st, type, r, addr); + } + } else { + Sym *sym; +@@ -8691,11 +8006,11 @@ + sym = NULL; + if (v && scope == VT_CONST) { + /* see if the symbol was already defined */ +- sym = sym_find(v); ++ sym = sym_find(st, v); + if (sym) { +- if (!is_compatible_types(&sym->type, type)) +- error("incompatible types for redefinition of '%s'", +- get_tok_str(v, NULL)); ++ if (!is_compatible_types(st, &sym->type, type)) ++ tcc_error(st, "incompatible types for redefinition of '%s'", ++ get_tok_str(st, v, NULL)); + if (sym->type.t & VT_EXTERN) { + /* if the variable is extern, it was not allocated */ + sym->type.t &= ~VT_EXTERN; +@@ -8724,7 +8039,7 @@ + if (!sec) { + if (has_init) + sec = data_section; +- else if (tcc_state->nocommon) ++ else if (st->nocommon) + sec = bss_section; + } + if (sec) { +@@ -8741,7 +8056,7 @@ + /* allocate section space to put the data */ + if (sec->sh_type != SHT_NOBITS && + data_offset > sec->data_allocated) +- section_realloc(sec, data_offset); ++ section_realloc(st, sec, data_offset); + /* align section if needed */ + if (align > sec->sh_addralign) + sec->sh_addralign = align; +@@ -8750,20 +8065,16 @@ + } + + if (v) { +- if (scope == VT_CONST) { +- if (!sym) +- goto do_def; +- } else { +- do_def: +- sym = sym_push(v, type, r | VT_SYM, 0); ++ if (scope != VT_CONST || !sym) { ++ sym = sym_push(st, v, type, r | VT_SYM, 0); + } + /* update symbol definition */ + if (sec) { +- put_extern_sym(sym, sec, addr, size); ++ put_extern_sym(st, sym, sec, addr, size); + } else { + Elf32_Sym *esym; + /* put a common area */ +- put_extern_sym(sym, NULL, align, size); ++ put_extern_sym(st, sym, NULL, align, size); + /* XXX: find a nicer way */ + esym = &((Elf32_Sym *)symtab_section->data)[sym->c]; + esym->st_shndx = SHN_COMMON; +@@ -8772,9 +8083,9 @@ + CValue cval; + + /* push global reference */ +- sym = get_sym_ref(type, sec, addr, size); ++ sym = get_sym_ref(st, type, sec, addr, size); + cval.ul = 0; +- vsetc(type, VT_CONST | VT_SYM, &cval); ++ vsetc(st, type, VT_CONST | VT_SYM, &cval); + vtop->sym = sym; + } + +@@ -8783,25 +8094,25 @@ + if (do_bounds_check) { + unsigned long *bounds_ptr; + +- greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32); ++ greloc(st, bounds_section, sym, bounds_section->data_offset, R_DATA_32); + /* then add global bound info */ +- bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long)); ++ bounds_ptr = section_ptr_add(st, bounds_section, 2 * sizeof(long)); + bounds_ptr[0] = 0; /* relocated */ + bounds_ptr[1] = size; + } + } + if (has_init) { +- decl_initializer(type, sec, addr, 1, 0); ++ decl_initializer(st, type, sec, addr, 1, 0); + /* restore parse state if needed */ + if (init_str.str) { +- tok_str_free(init_str.str); +- restore_parse_state(&saved_parse_state); ++ tok_str_free(st, init_str.str); ++ restore_parse_state(st, &saved_parse_state); + } + } + no_alloc: ; + } + +-void put_func_debug(Sym *sym) ++void put_func_debug(TCCState *st, Sym *sym) + { + char buf[512]; + +@@ -8809,7 +8120,7 @@ + /* XXX: we put here a dummy type */ + snprintf(buf, sizeof(buf), "%s:%c1", + funcname, sym->type.t & VT_STATIC ? 'f' : 'F'); +- put_stabs_r(buf, N_FUN, 0, file->line_num, 0, ++ put_stabs_r(st, buf, N_FUN, 0, file->line_num, 0, + cur_text_section, sym->c); + last_ind = 0; + last_line_num = 0; +@@ -8817,7 +8128,7 @@ + + /* parse an old style function declaration list */ + /* XXX: check multiple parameter */ +-static void func_decl_list(Sym *func_sym) ++static void func_decl_list(TCCState *st, Sym *func_sym) + { + AttributeDef ad; + int v; +@@ -8826,8 +8137,8 @@ + + /* parse each declaration */ + while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) { +- if (!parse_btype(&btype, &ad)) +- expect("declaration list"); ++ if (!parse_btype(st, &btype, &ad)) ++ expect(st, "declaration list"); + if (((btype.t & VT_BTYPE) == VT_ENUM || + (btype.t & VT_BTYPE) == VT_STRUCT) && + tok == ';') { +@@ -8835,7 +8146,7 @@ + } else { + for(;;) { + type = btype; +- type_decl(&type, &ad, &v, TYPE_DIRECT); ++ type_decl(st, &type, &ad, &v, TYPE_DIRECT); + /* find parameter in function parameter list */ + s = func_sym->next; + while (s != NULL) { +@@ -8843,61 +8154,61 @@ + goto found; + s = s->next; + } +- error("declaration for parameter '%s' but no such parameter", +- get_tok_str(v, NULL)); ++ tcc_error(st, "declaration for parameter '%s' but no such parameter", ++ get_tok_str(st, v, NULL)); + found: + /* check that no storage specifier except 'register' was given */ + if (type.t & VT_STORAGE) +- error("storage class specified for '%s'", get_tok_str(v, NULL)); +- convert_parameter_type(&type); ++ tcc_error(st, "storage class specified for '%s'", get_tok_str(st, v, NULL)); ++ convert_parameter_type(st, &type); + /* we can add the type (NOTE: it could be local to the function) */ + s->type = type; + /* accept other parameters */ + if (tok == ',') +- next(); ++ next(st); + else + break; + } + } +- skip(';'); ++ skip(st, ';'); + } + } + + /* parse a function defined by symbol 'sym' and generate its code in + 'cur_text_section' */ +-static void gen_function(Sym *sym) ++static void gen_function(TCCState *st, Sym *sym) + { + ind = cur_text_section->data_offset; + /* NOTE: we patch the symbol size later */ +- put_extern_sym(sym, cur_text_section, ind, 0); +- funcname = get_tok_str(sym->v, NULL); ++ put_extern_sym(st, sym, cur_text_section, ind, 0); ++ funcname = get_tok_str(st, sym->v, NULL); + func_ind = ind; + /* put debug symbol */ + if (do_debug) +- put_func_debug(sym); ++ put_func_debug(st, sym); + /* push a dummy symbol to enable local sym storage */ +- sym_push2(&local_stack, SYM_FIELD, 0, 0); +- gfunc_prolog(&sym->type); ++ sym_push2(st, &local_stack, SYM_FIELD, 0, 0); ++ gfunc_prolog(st, &sym->type); + rsym = 0; +- block(NULL, NULL, NULL, NULL, 0, 0); ++ block(st, NULL, NULL, NULL, NULL, 0, 0); + gsym(rsym); +- gfunc_epilog(); ++ gfunc_epilog(st); + cur_text_section->data_offset = ind; +- label_pop(&global_label_stack, NULL); +- sym_pop(&local_stack, NULL); /* reset local stack */ ++ label_pop(st, &global_label_stack, NULL); ++ sym_pop(st, &local_stack, NULL); /* reset local stack */ + /* end of function */ + /* patch symbol size */ + ((Elf32_Sym *)symtab_section->data)[sym->c].st_size = + ind - func_ind; + if (do_debug) { +- put_stabn(N_FUN, 0, 0, ind - func_ind); ++ put_stabn(st, N_FUN, 0, 0, ind - func_ind); + } + funcname = ""; /* for safety */ + func_vt.t = VT_VOID; /* for safety */ + ind = 0; /* for safety */ + } + +-static void gen_inline_functions(void) ++static void gen_inline_functions(TCCState *st) + { + Sym *sym; + CType *type; +@@ -8919,12 +8230,12 @@ + type->t &= ~VT_INLINE; + + macro_ptr = str; +- next(); ++ next(st); + cur_text_section = text_section; +- gen_function(sym); ++ gen_function(st, sym); + macro_ptr = NULL; /* fail safe */ + +- tok_str_free(str); ++ tok_str_free(st, str); + inline_generated = 1; + } + } +@@ -8939,14 +8250,14 @@ + (type->t & (VT_STATIC | VT_INLINE)) == + (VT_STATIC | VT_INLINE)) { + str = (int *)sym->r; +- tok_str_free(str); ++ tok_str_free(st, str); + sym->r = 0; /* fail safe */ + } + } + } + + /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ +-static void decl(int l) ++static void decl(TCCState *st, int l) + { + int v, has_init, r; + CType type, btype; +@@ -8954,17 +8265,17 @@ + AttributeDef ad; + + while (1) { +- if (!parse_btype(&btype, &ad)) { ++ if (!parse_btype(st, &btype, &ad)) { + /* skip redundant ';' */ + /* XXX: find more elegant solution */ + if (tok == ';') { +- next(); ++ next(st); + continue; + } + if (l == VT_CONST && + (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) { + /* global asm block */ +- asm_global_instr(); ++ asm_global_instr(st); + continue; + } + /* special test for old K&R protos without explicit int +@@ -8977,16 +8288,16 @@ + (btype.t & VT_BTYPE) == VT_STRUCT) && + tok == ';') { + /* we accept no variable after */ +- next(); ++ next(st); + continue; + } + while (1) { /* iterate thru each declaration */ + type = btype; +- type_decl(&type, &ad, &v, TYPE_DIRECT); ++ type_decl(st, &type, &ad, &v, TYPE_DIRECT); + #if 0 + { + char buf[500]; +- type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL)); ++ type_to_str(st, buf, sizeof(buf), &type, get_tok_str(st, v, NULL)); + printf("type = '%s'\n", buf); + } + #endif +@@ -8995,26 +8306,28 @@ + declaration list */ + sym = type.ref; + if (sym->c == FUNC_OLD) +- func_decl_list(sym); ++ func_decl_list(st, sym); + } + ++ /* Open curly bracket here can only be a function body, because ++ struct and union contents are handled by parse_btype(st) above. */ + if (tok == '{') { + if (l == VT_LOCAL) +- error("cannot use local functions"); +- if (!(type.t & VT_FUNC)) +- expect("function definition"); ++ tcc_error(st, "cannot use local functions"); ++ if ((type.t & VT_BTYPE) != VT_FUNC) ++ expect(st, "function definition"); + + /* reject abstract declarators in function definition */ + sym = type.ref; + while ((sym = sym->next) != NULL) + if (!(sym->v & ~SYM_FIELD)) +- expect("identifier"); ++ expect(st, "identifier"); + +- /* XXX: cannot do better now: convert extern line to static inline */ ++ /* XXX: cannot do better now: convert extern inline to static inline */ + if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE)) + type.t = (type.t & ~VT_EXTERN) | VT_STATIC; + +- sym = sym_find(v); ++ sym = sym_find(st, v); + if (sym) { + if ((sym->type.t & VT_BTYPE) != VT_FUNC) + goto func_error1; +@@ -9024,16 +8337,16 @@ + if (sym->type.ref->r != FUNC_CDECL && + type.ref->r == FUNC_CDECL) + type.ref->r = sym->type.ref->r; +- if (!is_compatible_types(&sym->type, &type)) { ++ if (!is_compatible_types(st, &sym->type, &type)) { + func_error1: +- error("incompatible types for redefinition of '%s'", +- get_tok_str(v, NULL)); ++ tcc_error(st, "incompatible types for redefinition of '%s'", ++ get_tok_str(st, v, NULL)); + } + /* if symbol is already defined, then put complete type */ + sym->type = type; + } else { + /* put function symbol */ +- sym = global_identifier_push(v, type.t, 0); ++ sym = global_identifier_push(st, v, type.t, 0); + sym->type.ref = type.ref; + } + +@@ -9045,16 +8358,16 @@ + TokenString func_str; + int block_level; + +- tok_str_new(&func_str); ++ tok_str_new(st, &func_str); + + block_level = 0; + for(;;) { + int t; + if (tok == TOK_EOF) +- error("unexpected end of file"); +- tok_str_add_tok(&func_str); ++ tcc_error(st, "unexpected end of file"); ++ tok_str_add_tok(st, &func_str); + t = tok; +- next(); ++ next(st); + if (t == '{') { + block_level++; + } else if (t == '}') { +@@ -9063,8 +8376,8 @@ + break; + } + } +- tok_str_add(&func_str, -1); +- tok_str_add(&func_str, 0); ++ tok_str_add(st, &func_str, -1, 0); ++ tok_str_add(st, &func_str, 0, 0); + sym->r = (int)func_str.str; + } else { + /* compute text section */ +@@ -9072,31 +8385,33 @@ + if (!cur_text_section) + cur_text_section = text_section; + sym->r = VT_SYM | VT_CONST; +- gen_function(sym); +-#ifdef TCC_TARGET_PE ++ gen_function(st, sym); ++#ifdef WIN32 + if (ad.dllexport) { + ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1; + } + #endif + } + break; ++ ++ /* If there was no function body, it must be a varaible. */ + } else { + if (btype.t & VT_TYPEDEF) { + /* save typedefed type */ + /* XXX: test storage specifiers ? */ +- sym = sym_push(v, &type, 0, 0); ++ sym = sym_push(st, v, &type, 0, 0); + sym->type.t |= VT_TYPEDEF; + } else if ((type.t & VT_BTYPE) == VT_FUNC) { + /* external function definition */ + /* specific case for func_call attribute */ + if (ad.func_call) + type.ref->r = ad.func_call; +- external_sym(v, &type, 0); ++ external_sym(st, v, &type, 0); + } else { + /* not lvalue if array */ + r = 0; + if (!(type.t & VT_ARRAY)) +- r |= lvalue_type(type.t); ++ r |= lvalue_type(st, type.t); + has_init = (tok == '='); + if ((btype.t & VT_EXTERN) || + ((type.t & VT_ARRAY) && (type.t & VT_STATIC) && +@@ -9105,23 +8420,24 @@ + /* NOTE: as GCC, uninitialized global static + arrays of null size are considered as + extern */ +- external_sym(v, &type, r); ++ external_sym(st, v, &type, r); + } else { ++ type.t |= (btype.t & VT_STATIC); /* Retain "static". */ + if (type.t & VT_STATIC) + r |= VT_CONST; + else + r |= l; + if (has_init) +- next(); +- decl_initializer_alloc(&type, &ad, r, ++ next(st); ++ decl_initializer_alloc(st, &type, &ad, r, + has_init, v, l); + } + } + if (tok != ',') { +- skip(';'); ++ skip(st, ';'); + break; + } +- next(); ++ next(st); + } + } + } +@@ -9129,22 +8445,21 @@ + + /* better than nothing, but needs extension to handle '-E' option + correctly too */ +-static void preprocess_init(TCCState *s1) ++static void preprocess_init(TCCState *st) + { +- s1->include_stack_ptr = s1->include_stack; ++ st->include_stack_ptr = st->include_stack; + /* XXX: move that before to avoid having to initialize + file->ifdef_stack_ptr ? */ +- s1->ifdef_stack_ptr = s1->ifdef_stack; +- file->ifdef_stack_ptr = s1->ifdef_stack_ptr; ++ st->ifdef_stack_ptr = st->ifdef_stack; ++ file->ifdef_stack_ptr = st->ifdef_stack_ptr; + +- /* XXX: not ANSI compliant: bound checking says error */ +- vtop = vstack - 1; +- s1->pack_stack[0] = 0; +- s1->pack_stack_ptr = s1->pack_stack; ++ vtop = vstack; ++ st->pack_stack[0] = 0; ++ st->pack_stack_ptr = st->pack_stack; + } + + /* compile the C file opened in 'file'. Return non zero if errors. */ +-static int tcc_compile(TCCState *s1) ++static int tcc_compile(TCCState *st) + { + Sym *define_start; + char buf[512]; +@@ -9153,7 +8468,7 @@ + #ifdef INC_DEBUG + printf("%s: **** new file\n", file->filename); + #endif +- preprocess_init(s1); ++ preprocess_init(st); + + funcname = ""; + anon_sym = SYM_FIRST_ANOM; +@@ -9161,19 +8476,19 @@ + /* file info: full path + filename */ + section_sym = 0; /* avoid warning */ + if (do_debug) { +- section_sym = put_elf_sym(symtab_section, 0, 0, ++ section_sym = put_elf_sym(st, symtab_section, 0, 0, + ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0, + text_section->sh_num, NULL); + getcwd(buf, sizeof(buf)); +- pstrcat(buf, sizeof(buf), "/"); +- put_stabs_r(buf, N_SO, 0, 0, ++ pstrcat(st, buf, sizeof(buf), "/"); ++ put_stabs_r(st, buf, N_SO, 0, 0, + text_section->data_offset, text_section, section_sym); +- put_stabs_r(file->filename, N_SO, 0, 0, ++ put_stabs_r(st, file->filename, N_SO, 0, 0, + text_section->data_offset, text_section, section_sym); + } + /* an elf symbol of type STT_FILE must be put so that STB_LOCAL + symbols can be safely used */ +- put_elf_sym(symtab_section, 0, 0, ++ put_elf_sym(st, symtab_section, 0, 0, + ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0, + SHN_ABS, file->filename); + +@@ -9181,56 +8496,106 @@ + int_type.t = VT_INT; + + char_pointer_type.t = VT_BYTE; +- mk_pointer(&char_pointer_type); ++ mk_pointer(st, &char_pointer_type); + + func_old_type.t = VT_FUNC; +- func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); ++ func_old_type.ref = sym_push(st, SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); ++ ++#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) ++ float_type.t = VT_FLOAT; ++ double_type.t = VT_DOUBLE; ++ ++ func_float_type.t = VT_FUNC; ++ func_float_type.ref = sym_push(st, SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); ++ func_double_type.t = VT_FUNC; ++ func_double_type.ref = sym_push(st, SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); ++#endif + + #if 0 + /* define 'void *alloca(unsigned int)' builtin function */ + { +- Sym *s1; ++ Sym *st; + + p = anon_sym++; +- sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW); +- s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); +- s1->next = NULL; +- sym->next = s1; +- sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); ++ sym = sym_push(st, p, mk_pointer(st, VT_VOID), FUNC_CDECL, FUNC_NEW); ++ st = sym_push(st, SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); ++ st->next = NULL; ++ sym->next = st; ++ sym_push(st, TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); + } + #endif + + define_start = define_stack; + +- if (setjmp(s1->error_jmp_buf) == 0) { +- s1->nb_errors = 0; +- s1->error_set_jmp_enabled = 1; ++ if (setjmp(st->error_jmp_buf) == 0) { ++ st->nb_errors = 0; ++ st->error_set_jmp_enabled = 1; + +- ch = file->buf_ptr[0]; +- tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; ++ fch = file->buf_ptr[0]; ++ next_tok_flags = TOK_FLAG_BOW | TOK_FLAG_BOL | TOK_FLAG_BOF; + parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM; +- next(); +- decl(VT_CONST); +- if (tok != TOK_EOF) +- expect("declaration"); ++ next(st); ++ decl(st, VT_CONST); ++ if (tok != TOK_EOF) expect(st, "declaration"); + + /* end of translation unit info */ + if (do_debug) { +- put_stabs_r(NULL, N_SO, 0, 0, +- text_section->data_offset, text_section, section_sym); ++ put_stabs_r(st, NULL, N_SO, 0, 0, text_section->data_offset, ++ text_section, section_sym); + } + } +- s1->error_set_jmp_enabled = 0; ++ st->error_set_jmp_enabled = 0; + + /* reset define stack, but leave -Dsymbols (may be incorrect if + they are undefined) */ +- free_defines(define_start); ++ free_defines(st, define_start); ++ ++ gen_inline_functions(st); + +- gen_inline_functions(); ++ sym_pop(st, &global_stack, NULL); + +- sym_pop(&global_stack, NULL); ++ return st->nb_errors != 0 ? -1 : 0; ++} ++ ++/* Preprocess the current file */ ++/* XXX: add line and file infos, add options to preserve spaces */ ++static int tcc_preprocess(TCCState *st) ++{ ++ Sym *define_start; ++ int last_is_space; ++ ++ preprocess_init(st); + +- return s1->nb_errors != 0 ? -1 : 0; ++ define_start = define_stack; ++ ++ fch = file->buf_ptr[0]; ++ tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; ++ parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS | ++ PARSE_FLAG_LINEFEED; ++ last_is_space = 1; ++ next(st); ++ for(;;) { ++ if (tok == TOK_EOF) ++ break; ++ if (!last_is_space) { ++ fputc(' ', st->outfile); ++ } ++ fputs(get_tok_str(st, tok, &tokc), st->outfile); ++ if (tok == TOK_LINEFEED) { ++ last_is_space = 1; ++ /* XXX: suppress that hack */ ++ parse_flags &= ~PARSE_FLAG_LINEFEED; ++ next(st); ++ parse_flags |= PARSE_FLAG_LINEFEED; ++ } else { ++ last_is_space = 0; ++ next(st); ++ } ++ } ++ ++ free_defines(st, define_start); ++ ++ return 0; + } + + #ifdef LIBTCC +@@ -9241,23 +8606,23 @@ + char *buf; + + /* init file structure */ +- bf->fd = -1; ++ bf->fd = NULL; + /* XXX: avoid copying */ + len = strlen(str); +- buf = tcc_malloc(len + 1); ++ buf = tcc_malloc(s, len + 1); + if (!buf) + return -1; + memcpy(buf, str, len); + buf[len] = CH_EOB; + bf->buf_ptr = buf; + bf->buf_end = buf + len; +- pstrcpy(bf->filename, sizeof(bf->filename), ""); ++ pstrcpy(s, bf->filename, sizeof(bf->filename), ""); + bf->line_num = 1; + file = bf; + + ret = tcc_compile(s); + +- tcc_free(buf); ++ ckfree((char *)buf); + + /* currently, no need to close */ + return ret; +@@ -9265,19 +8630,19 @@ + #endif + + /* define a preprocessor symbol. A value can also be provided with the '=' operator */ +-void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) ++void tcc_define_symbol(TCCState *st, const char *sym, const char *value) + { + BufferedFile bf1, *bf = &bf1; + +- pstrcpy(bf->buffer, IO_BUF_SIZE, sym); +- pstrcat(bf->buffer, IO_BUF_SIZE, " "); ++ pstrcpy(st, bf->buffer, IO_BUF_SIZE, sym); ++ pstrcat(st, bf->buffer, IO_BUF_SIZE, " "); + /* default value */ + if (!value) + value = "1"; +- pstrcat(bf->buffer, IO_BUF_SIZE, value); ++ pstrcat(st, bf->buffer, IO_BUF_SIZE, value); + + /* init file structure */ +- bf->fd = -1; ++ bf->fd = NULL; + bf->buf_ptr = bf->buffer; + bf->buf_end = bf->buffer + strlen(bf->buffer); + *bf->buf_end = CH_EOB; +@@ -9285,22 +8650,22 @@ + bf->line_num = 1; + file = bf; + +- s1->include_stack_ptr = s1->include_stack; ++ st->include_stack_ptr = st->include_stack; + + /* parse with define parser */ +- ch = file->buf_ptr[0]; +- next_nomacro(); +- parse_define(); ++ fch = file->buf_ptr[0]; ++ next_nomacro(st); ++ parse_define(st); + file = NULL; + } + + /* undefine a preprocessor symbol */ +-void tcc_undefine_symbol(TCCState *s1, const char *sym) ++void tcc_undefine_symbol(TCCState *st, const char *sym) + { + TokenSym *ts; + Sym *s; +- ts = tok_alloc(sym, strlen(sym)); +- s = define_find(ts->tok); ++ ts = tok_alloc(st, sym, strlen(sym)); ++ s = define_find(st, ts->tok); + /* undefine symbol by putting an invalid name */ + if (s) + define_undef(s); +@@ -9309,18 +8674,18 @@ + #ifdef CONFIG_TCC_ASM + + #ifdef TCC_TARGET_I386 +-#include "i386-asm.c" ++#include "i386/i386-asm.c" + #endif + #include "tccasm.c" + + #else +-static void asm_instr(void) ++static void asm_instr(TCCState *st) + { +- error("inline asm() not supported"); ++ tcc_error(st, "inline asm() not supported"); + } +-static void asm_global_instr(void) ++static void asm_global_instr(TCCState *st) + { +- error("inline asm() not supported"); ++ tcc_error(st, "inline asm() not supported"); + } + #endif + +@@ -9330,354 +8695,121 @@ + #include "tcccoff.c" + #endif + +-#ifdef TCC_TARGET_PE +-#include "tccpe.c" +-#endif +- +-/* print the position in the source file of PC value 'pc' by reading +- the stabs debug information */ +-static void rt_printline(unsigned long wanted_pc) +-{ +- Stab_Sym *sym, *sym_end; +- char func_name[128], last_func_name[128]; +- unsigned long func_addr, last_pc, pc; +- const char *incl_files[INCLUDE_STACK_SIZE]; +- int incl_index, len, last_line_num, i; +- const char *str, *p; +- +- fprintf(stderr, "0x%08lx:", wanted_pc); +- +- func_name[0] = '\0'; +- func_addr = 0; +- incl_index = 0; +- last_func_name[0] = '\0'; +- last_pc = 0xffffffff; +- last_line_num = 1; +- sym = (Stab_Sym *)stab_section->data + 1; +- sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset); +- while (sym < sym_end) { +- switch(sym->n_type) { +- /* function start or end */ +- case N_FUN: +- if (sym->n_strx == 0) { +- /* we test if between last line and end of function */ +- pc = sym->n_value + func_addr; +- if (wanted_pc >= last_pc && wanted_pc < pc) +- goto found; +- func_name[0] = '\0'; +- func_addr = 0; +- } else { +- str = stabstr_section->data + sym->n_strx; +- p = strchr(str, ':'); +- if (!p) { +- pstrcpy(func_name, sizeof(func_name), str); +- } else { +- len = p - str; +- if (len > sizeof(func_name) - 1) +- len = sizeof(func_name) - 1; +- memcpy(func_name, str, len); +- func_name[len] = '\0'; +- } +- func_addr = sym->n_value; +- } +- break; +- /* line number info */ +- case N_SLINE: +- pc = sym->n_value + func_addr; +- if (wanted_pc >= last_pc && wanted_pc < pc) +- goto found; +- last_pc = pc; +- last_line_num = sym->n_desc; +- /* XXX: slow! */ +- strcpy(last_func_name, func_name); +- break; +- /* include files */ +- case N_BINCL: +- str = stabstr_section->data + sym->n_strx; +- add_incl: +- if (incl_index < INCLUDE_STACK_SIZE) { +- incl_files[incl_index++] = str; +- } +- break; +- case N_EINCL: +- if (incl_index > 1) +- incl_index--; +- break; +- case N_SO: +- if (sym->n_strx == 0) { +- incl_index = 0; /* end of translation unit */ +- } else { +- str = stabstr_section->data + sym->n_strx; +- /* do not add path */ +- len = strlen(str); +- if (len > 0 && str[len - 1] != '/') +- goto add_incl; +- } +- break; +- } +- sym++; +- } +- +- /* second pass: we try symtab symbols (no line number info) */ +- incl_index = 0; +- { +- Elf32_Sym *sym, *sym_end; +- int type; +- +- sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset); +- for(sym = (Elf32_Sym *)symtab_section->data + 1; +- sym < sym_end; +- sym++) { +- type = ELF32_ST_TYPE(sym->st_info); +- if (type == STT_FUNC) { +- if (wanted_pc >= sym->st_value && +- wanted_pc < sym->st_value + sym->st_size) { +- pstrcpy(last_func_name, sizeof(last_func_name), +- strtab_section->data + sym->st_name); +- goto found; +- } +- } +- } +- } +- /* did not find any info: */ +- fprintf(stderr, " ???\n"); +- return; +- found: +- if (last_func_name[0] != '\0') { +- fprintf(stderr, " %s()", last_func_name); +- } +- if (incl_index > 0) { +- fprintf(stderr, " (%s:%d", +- incl_files[incl_index - 1], last_line_num); +- for(i = incl_index - 2; i >= 0; i--) +- fprintf(stderr, ", included from %s", incl_files[i]); +- fprintf(stderr, ")"); +- } +- fprintf(stderr, "\n"); +-} +- +-#if !defined(WIN32) && !defined(CONFIG_TCCBOOT) +- +-#ifdef __i386__ +- +-/* fix for glibc 2.1 */ +-#ifndef REG_EIP +-#define REG_EIP EIP +-#define REG_EBP EBP +-#endif +- +-/* return the PC at frame level 'level'. Return non zero if not found */ +-static int rt_get_caller_pc(unsigned long *paddr, +- ucontext_t *uc, int level) +-{ +- unsigned long fp; +- int i; +- +- if (level == 0) { +-#if defined(__FreeBSD__) +- *paddr = uc->uc_mcontext.mc_eip; +-#elif defined(__dietlibc__) +- *paddr = uc->uc_mcontext.eip; +-#else +- *paddr = uc->uc_mcontext.gregs[REG_EIP]; +-#endif +- return 0; +- } else { +-#if defined(__FreeBSD__) +- fp = uc->uc_mcontext.mc_ebp; +-#elif defined(__dietlibc__) +- fp = uc->uc_mcontext.ebp; +-#else +- fp = uc->uc_mcontext.gregs[REG_EBP]; +-#endif +- for(i=1;i= 0xc0000000) +- return -1; +- fp = ((unsigned long *)fp)[0]; +- } +- *paddr = ((unsigned long *)fp)[1]; +- return 0; +- } +-} +-#else +- +-#warning add arch specific rt_get_caller_pc() +- +-static int rt_get_caller_pc(unsigned long *paddr, +- ucontext_t *uc, int level) +-{ +- return -1; +-} +-#endif +- +-/* emit a run time error at position 'pc' */ +-void rt_error(ucontext_t *uc, const char *fmt, ...) +-{ +- va_list ap; +- unsigned long pc; +- int i; +- +- va_start(ap, fmt); +- fprintf(stderr, "Runtime error: "); +- vfprintf(stderr, fmt, ap); +- fprintf(stderr, "\n"); +- for(i=0;isi_code) { +- case FPE_INTDIV: +- case FPE_FLTDIV: +- rt_error(uc, "division by zero"); +- break; +- default: +- rt_error(uc, "floating point exception"); +- break; +- } +- break; +- case SIGBUS: +- case SIGSEGV: +- if (rt_bound_error_msg && *rt_bound_error_msg) +- rt_error(uc, *rt_bound_error_msg); +- else +- rt_error(uc, "dereferencing invalid pointer"); +- break; +- case SIGILL: +- rt_error(uc, "illegal instruction"); +- break; +- case SIGABRT: +- rt_error(uc, "abort() called"); +- break; +- default: +- rt_error(uc, "caught signal %d", signum); +- break; +- } +- exit(255); +-} ++#ifdef WIN32 ++#include "win32/tccpe.c" + #endif + +-/* do all relocations (needed before using tcc_get_symbol()) */ +-int tcc_relocate(TCCState *s1) ++/* do all relocations (needed before using tcc_get_symbol(st)) */ ++int tcc_relocate(TCCState *st) + { + Section *s; + int i; + +- s1->nb_errors = 0; ++ st->nb_errors = 0; + +-#ifdef TCC_TARGET_PE +- pe_add_runtime(s1); ++#ifdef WIN32 ++ pe_add_runtime(st); + #else +- tcc_add_runtime(s1); ++ tcc_add_runtime(st); + #endif + + relocate_common_syms(); +- +- tcc_add_linker_symbols(s1); +- +- build_got_entries(s1); ++ tcc_add_linker_symbols(st); ++ build_got_entries(st); + + /* compute relocation address : section are relocated in place. We + also alloc the bss space */ +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; + if (s->sh_flags & SHF_ALLOC) { + if (s->sh_type == SHT_NOBITS) +- s->data = tcc_mallocz(s->data_offset); ++ s->data = tcc_mallocz(st, s->data_offset); + s->sh_addr = (unsigned long)s->data; + } + } + +- relocate_syms(s1, 1); ++ relocate_syms(st, 1); + +- if (s1->nb_errors != 0) ++ if (st->nb_errors != 0) + return -1; + + /* relocate each section */ +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; + if (s->reloc) +- relocate_section(s1, s); ++ relocate_section(st, s); ++ } ++ ++ /* mark executable sections as executable in memory */ ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; ++ if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) == ++ (SHF_ALLOC | SHF_EXECINSTR)) { ++#ifdef WIN32 ++ { ++ int old_protect; ++ VirtualProtect(s->data, s->data_offset, ++ PAGE_EXECUTE_READWRITE, &old_protect); ++ } ++#else ++ { ++ unsigned long start, end; ++ start = (unsigned long)(s->data) & ~(PAGESIZE - 1); ++ end = (unsigned long)(s->data + s->data_offset); ++ end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1); ++ mprotect((void *)start, end - start, ++ PROT_READ | PROT_WRITE | PROT_EXEC); ++ } ++#endif ++ } + } + return 0; + } + + /* launch the compiled program with the given arguments */ +-int tcc_run(TCCState *s1, int argc, char **argv) ++int tcc_run(TCCState *st, int argc, char **argv) + { + int (*prog_main)(int, char **); + +- if (tcc_relocate(s1) < 0) ++ if (tcc_relocate(st) < 0) + return -1; + +- prog_main = tcc_get_symbol_err(s1, "main"); ++ prog_main = tcc_get_symbol_err(st, "main"); + +- if (do_debug) { +-#if defined(WIN32) || defined(CONFIG_TCCBOOT) +- error("debug mode currently not available for Windows"); +-#else +- struct sigaction sigact; +- /* install TCC signal handlers to print debug info on fatal +- runtime errors */ +- sigact.sa_flags = SA_SIGINFO | SA_RESETHAND; +- sigact.sa_sigaction = sig_error; +- sigemptyset(&sigact.sa_mask); +- sigaction(SIGFPE, &sigact, NULL); +- sigaction(SIGILL, &sigact, NULL); +- sigaction(SIGSEGV, &sigact, NULL); +- sigaction(SIGBUS, &sigact, NULL); +- sigaction(SIGABRT, &sigact, NULL); +-#endif +- } +- +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + if (do_bounds_check) { + void (*bound_init)(void); + + /* set error function */ +- rt_bound_error_msg = (void *)tcc_get_symbol_err(s1, ++ rt_bound_error_msg = (void *)tcc_get_symbol_err(st, + "__bound_error_msg"); + + /* XXX: use .init section so that it also work in binary ? */ +- bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init"); +- bound_init(); ++ bound_init = (void *)tcc_get_symbol_err(st, "__bound_init"); ++ bound_init(st); + } + #endif + return (*prog_main)(argc, argv); + } + +-TCCState *tcc_new(void) ++TCCState *tcc_new(Tcl_Obj * libpath) + { + const char *p, *r; + TCCState *s; + TokenSym *ts; + int i, c; + +- s = tcc_mallocz(sizeof(TCCState)); ++ s = tcc_mallocz(NULL, sizeof(TCCState)); + if (!s) + return NULL; +- tcc_state = s; + s->output_type = TCC_OUTPUT_MEMORY; + ++ Tcl_IncrRefCount(libpath); ++ s->tcc_lib_path = libpath ; ++ + /* init isid table */ + for(i=0;i<256;i++) +- isidnum_table[i] = isid(i) || isnum(i); ++ isidnum_table[i] = isid(s, i) || isnum(s, i); + + /* add all tokens */ + table_ident = NULL; +@@ -9692,19 +8824,20 @@ + if (c == '\0') + break; + } +- ts = tok_alloc(p, r - p - 1); ++ ts = tok_alloc(s, p, r - p - 1); + p = r; + } + + /* we add dummy defines for some special macros to speed up tests + and to have working defined() */ +- define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL); +- define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); +- define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); +- define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); ++ define_push(s, TOK___LINE__, MACRO_OBJ, NULL, NULL); ++ define_push(s, TOK___FILE__, MACRO_OBJ, NULL, NULL); ++ define_push(s, TOK___DATE__, MACRO_OBJ, NULL, NULL); ++ define_push(s, TOK___TIME__, MACRO_OBJ, NULL, NULL); + + /* standard defines */ + tcc_define_symbol(s, "__STDC__", NULL); ++ tcc_define_symbol(s, "__STDC_VERSION__", "199901L"); + #if defined(TCC_TARGET_I386) + tcc_define_symbol(s, "__i386__", NULL); + #endif +@@ -9728,23 +8861,27 @@ + /* tiny C & gcc defines */ + tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); + tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); ++#ifdef WIN32 ++ tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short"); ++#else + tcc_define_symbol(s, "__WCHAR_TYPE__", "int"); ++#endif + + /* default library paths */ +-#ifdef TCC_TARGET_PE + { + char buf[1024]; +- snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path); ++ snprintf(buf, sizeof(buf), "%s/lib", Tcl_GetString(s->tcc_lib_path)); ++ /* printf("default libraries %s\n",buf); */ + tcc_add_library_path(s, buf); + } +-#else ++#ifndef WIN32 + tcc_add_library_path(s, "/usr/local/lib"); + tcc_add_library_path(s, "/usr/lib"); + tcc_add_library_path(s, "/lib"); + #endif + + /* no section zero */ +- dynarray_add((void ***)&s->sections, &s->nb_sections, NULL); ++ dynarray_add(s, (void ***)&s->sections, &s->nb_sections, NULL); + + /* create standard sections */ + text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); +@@ -9766,87 +8903,92 @@ + #ifdef CHAR_IS_UNSIGNED + s->char_is_unsigned = 1; + #endif +-#if defined(TCC_TARGET_PE) && 0 ++#if defined(WIN32) && 0 + /* XXX: currently the PE linker is not ready to support that */ + s->leading_underscore = 1; + #endif + return s; + } + +-void tcc_delete(TCCState *s1) ++void tcc_delete(TCCState *st) + { ++ /* this leaks but allows you to reuse handles without crashing the process */ + int i, n; + + /* free -D defines */ +- free_defines(NULL); ++ free_defines(st, NULL); + + /* free tokens */ ++ if(0) { + n = tok_ident - TOK_IDENT; + for(i = 0; i < n; i++) +- tcc_free(table_ident[i]); +- tcc_free(table_ident); ++ ckfree((char *)(table_ident[i])); ++ ckfree((char *)table_ident); + + /* free all sections */ + +- free_section(symtab_section->hash); + +- free_section(s1->dynsymtab_section->hash); +- free_section(s1->dynsymtab_section->link); +- free_section(s1->dynsymtab_section); +- +- for(i = 1; i < s1->nb_sections; i++) +- free_section(s1->sections[i]); +- tcc_free(s1->sections); ++ free_section(st, symtab_section->hash); ++ ++ free_section(st, st->dynsymtab_section->hash); ++ free_section(st, st->dynsymtab_section->link); ++ free_section(st, st->dynsymtab_section); ++ ++ for(i = 1; i < st->nb_sections; i++) ++ free_section(st, st->sections[i]); ++ ckfree((char *)(st->sections)); ++ } + + /* free loaded dlls array */ +- for(i = 0; i < s1->nb_loaded_dlls; i++) +- tcc_free(s1->loaded_dlls[i]); +- tcc_free(s1->loaded_dlls); ++ for(i = 0; i < st->nb_loaded_dlls; i++) ++ ckfree((char *)(st->loaded_dlls[i])); ++ ckfree((char *)(st->loaded_dlls)); + + /* library paths */ +- for(i = 0; i < s1->nb_library_paths; i++) +- tcc_free(s1->library_paths[i]); +- tcc_free(s1->library_paths); ++ for(i = 0; i < st->nb_library_paths; i++) ++ ckfree((char *)(st->library_paths[i])); ++ ckfree((char *)(st->library_paths)); + + /* cached includes */ +- for(i = 0; i < s1->nb_cached_includes; i++) +- tcc_free(s1->cached_includes[i]); +- tcc_free(s1->cached_includes); ++ for(i = 0; i < st->nb_cached_includes; i++) ++ ckfree((char *)(st->cached_includes[i])); ++ ckfree((char *)(st->cached_includes)); + +- for(i = 0; i < s1->nb_include_paths; i++) +- tcc_free(s1->include_paths[i]); +- tcc_free(s1->include_paths); ++ for(i = 0; i < st->nb_include_paths; i++) ++ ckfree((char *)(st->include_paths[i])); ++ ckfree((char *)(st->include_paths)); + +- for(i = 0; i < s1->nb_sysinclude_paths; i++) +- tcc_free(s1->sysinclude_paths[i]); +- tcc_free(s1->sysinclude_paths); ++ for(i = 0; i < st->nb_sysinclude_paths; i++) ++ ckfree((char *)(st->sysinclude_paths[i])); ++ ckfree((char *)(st->sysinclude_paths)); + +- tcc_free(s1); ++ ckfree((char *)st); + } + +-int tcc_add_include_path(TCCState *s1, const char *pathname) ++int tcc_add_include_path(TCCState *st, const char *pathname) + { + char *pathname1; + +- pathname1 = tcc_strdup(pathname); +- dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1); ++ pathname1 = tcc_strdup(st, pathname); ++ dynarray_add(st, (void ***)&st->include_paths, &st->nb_include_paths, pathname1); + return 0; + } + +-int tcc_add_sysinclude_path(TCCState *s1, const char *pathname) ++int tcc_add_sysinclude_path(TCCState *st, const char *pathname) + { + char *pathname1; + +- pathname1 = tcc_strdup(pathname); +- dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1); ++ pathname1 = tcc_strdup(st, pathname); ++ dynarray_add(st, (void ***)&st->sysinclude_paths, &st->nb_sysinclude_paths, pathname1); + return 0; + } + +-static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) ++static int tcc_add_file_internal(TCCState *st, const char *filename, int flags) + { + const char *ext, *filename1; + Elf32_Ehdr ehdr; +- int fd, ret; ++ Tcl_Channel fd; ++ int ret; + BufferedFile *saved_file; + + /* find source file type with extension */ +@@ -9861,40 +9003,41 @@ + + /* open the file */ + saved_file = file; +- file = tcc_open(s1, filename); ++ file = tcc_open(st, filename); + if (!file) { + if (flags & AFF_PRINT_ERROR) { +- error_noabort("file '%s' not found", filename); ++ error_noabort(st, "file '%s' not found", filename); + } + ret = -1; + goto fail1; + } + +- if (!ext || !strcmp(ext, "c")) { ++ if (flags & AFF_PREPROCESS) ret = tcc_preprocess(st); ++ else if (!ext || !strcmp(ext, "c")) { + /* C file assumed */ +- ret = tcc_compile(s1); ++ ret = tcc_compile(st); + } else + #ifdef CONFIG_TCC_ASM + if (!strcmp(ext, "S")) { + /* preprocessed assembler */ +- ret = tcc_assemble(s1, 1); ++ ret = tcc_assemble(st, 1); + } else if (!strcmp(ext, "s")) { + /* non preprocessed assembler */ +- ret = tcc_assemble(s1, 0); ++ ret = tcc_assemble(st, 0); + } else + #endif +-#ifdef TCC_TARGET_PE ++#ifdef WIN32 + if (!strcmp(ext, "def")) { +- ret = pe_load_def_file(s1, fdopen(file->fd, "rb")); ++ ret = pe_load_def_file(st, file->fd); + } else + #endif + { + fd = file->fd; + /* assume executable format: auto guess file type */ +- ret = read(fd, &ehdr, sizeof(ehdr)); +- lseek(fd, 0, SEEK_SET); ++ ret = Tcl_Read(fd, (char *)&ehdr, sizeof(ehdr)); ++ Tcl_Seek(fd, 0, SEEK_SET); + if (ret <= 0) { +- error_noabort("could not read header"); ++ error_noabort(st, "could not read header"); + goto fail; + } else if (ret != sizeof(ehdr)) { + goto try_load_script; +@@ -9906,10 +9049,10 @@ + ehdr.e_ident[3] == ELFMAG3) { + file->line_num = 0; /* do not display line number if error */ + if (ehdr.e_type == ET_REL) { +- ret = tcc_load_object_file(s1, fd, 0); ++ ret = tcc_load_object_file(st, fd, 0); + } else if (ehdr.e_type == ET_DYN) { +- if (s1->output_type == TCC_OUTPUT_MEMORY) { +-#ifdef TCC_TARGET_PE ++ if (st->output_type == TCC_OUTPUT_MEMORY) { ++#ifdef WIN32 + ret = -1; + #else + void *h; +@@ -9920,28 +9063,28 @@ + ret = -1; + #endif + } else { +- ret = tcc_load_dll(s1, fd, filename, ++ ret = tcc_load_dll(st, fd, filename, + (flags & AFF_REFERENCED_DLL) != 0); + } + } else { +- error_noabort("unrecognized ELF file"); ++ error_noabort(st, "unrecognized ELF file"); + goto fail; + } + } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { + file->line_num = 0; /* do not display line number if error */ +- ret = tcc_load_archive(s1, fd); ++ ret = tcc_load_archive(st, fd); + } else + #ifdef TCC_TARGET_COFF + if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { +- ret = tcc_load_coff(s1, fd); ++ ret = tcc_load_coff(st, fd); + } else + #endif + { + /* as GNU ld, consider it is an ld script if not recognized */ + try_load_script: +- ret = tcc_load_ldscript(s1); ++ ret = tcc_load_ldscript(st); + if (ret < 0) { +- error_noabort("unrecognized file type"); ++ error_noabort(st, "unrecognized file type"); + goto fail; + } + } +@@ -9965,8 +9108,8 @@ + { + char *pathname1; + +- pathname1 = tcc_strdup(pathname); +- dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1); ++ pathname1 = tcc_strdup(s, pathname); ++ dynarray_add(s, (void ***)&s->library_paths, &s->nb_library_paths, pathname1); + return 0; + } + +@@ -9994,7 +9137,7 @@ + + /* first we look for the dynamic library if not static linking */ + if (!s->static_link) { +-#ifdef TCC_TARGET_PE ++#ifdef WIN32 + snprintf(buf, sizeof(buf), "%s.def", libraryname); + #else + snprintf(buf, sizeof(buf), "lib%s.so", libraryname); +@@ -10013,9 +9156,9 @@ + return -1; + } + +-int tcc_add_symbol(TCCState *s, const char *name, unsigned long val) ++int tcc_add_symbol(TCCState *st, const char *name, unsigned long val) + { +- add_elf_sym(symtab_section, val, 0, ++ add_elf_sym(st, symtab_section, val, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + SHN_ABS, name); + return 0; +@@ -10030,20 +9173,20 @@ + + /* default include paths */ + /* XXX: reverse order needed if -isystem support */ +-#ifndef TCC_TARGET_PE ++#ifndef WIN32 + tcc_add_sysinclude_path(s, "/usr/local/include"); + tcc_add_sysinclude_path(s, "/usr/include"); + #endif +- snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path); ++ snprintf(buf, sizeof(buf), "%s/include", Tcl_GetString(s->tcc_lib_path)); + tcc_add_sysinclude_path(s, buf); +-#ifdef TCC_TARGET_PE +- snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path); ++#ifdef WIN32 ++ snprintf(buf, sizeof(buf), "%s/include/winapi", Tcl_GetString(s->tcc_lib_path)); + tcc_add_sysinclude_path(s, buf); + #endif + } + + /* if bound checking, then add corresponding sections */ +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + if (do_bounds_check) { + /* define symbol */ + tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL); +@@ -10065,14 +9208,14 @@ + stab_section = new_section(s, ".stab", SHT_PROGBITS, 0); + stab_section->sh_entsize = sizeof(Stab_Sym); + stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0); +- put_elf_str(stabstr_section, ""); ++ put_elf_str(s, stabstr_section, ""); + stab_section->link = stabstr_section; + /* put first entry */ +- put_stabs("", 0, 0, 0, 0); ++ put_stabs(s, "", 0, 0, 0, 0); + } + + /* add libc crt1/crti objects */ +-#ifndef TCC_TARGET_PE ++#ifndef WIN32 + if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && + !s->nostdlib) { + if (output_type != TCC_OUTPUT_DLL) +@@ -10157,8 +9300,6 @@ + flag_name, value); + } + +-#if !defined(LIBTCC) +- + /* extract the basename of a file */ + static const char *tcc_basename(const char *name) + { +@@ -10175,516 +9316,4 @@ + return p; + } + +-static int64_t getclock_us(void) +-{ +-#ifdef WIN32 +- struct _timeb tb; +- _ftime(&tb); +- return (tb.time * 1000LL + tb.millitm) * 1000LL; +-#else +- struct timeval tv; +- gettimeofday(&tv, NULL); +- return tv.tv_sec * 1000000LL + tv.tv_usec; +-#endif +-} +- +-void help(void) +-{ +- printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n" +- "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n" +- " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n" +- " [infile1 infile2...] [-run infile args...]\n" +- "\n" +- "General options:\n" +- " -v display current version\n" +- " -c compile only - generate an object file\n" +- " -o outfile set output filename\n" +- " -Bdir set tcc internal library path\n" +- " -bench output compilation statistics\n" +- " -run run compiled source\n" +- " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n" +- " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n" +- " -w disable all warnings\n" +- "Preprocessor options:\n" +- " -Idir add include path 'dir'\n" +- " -Dsym[=val] define 'sym' with value 'val'\n" +- " -Usym undefine 'sym'\n" +- "Linker options:\n" +- " -Ldir add library path 'dir'\n" +- " -llib link with dynamic or static library 'lib'\n" +- " -shared generate a shared library\n" +- " -static static linking\n" +- " -rdynamic export all global symbols to dynamic linker\n" +- " -r relocatable output\n" +- "Debugger options:\n" +- " -g generate runtime debug info\n" +-#ifdef CONFIG_TCC_BCHECK +- " -b compile with built-in memory and bounds checker (implies -g)\n" +-#endif +- " -bt N show N callers in stack traces\n" +- ); +-} +- +-#define TCC_OPTION_HAS_ARG 0x0001 +-#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */ +- +-typedef struct TCCOption { +- const char *name; +- uint16_t index; +- uint16_t flags; +-} TCCOption; +- +-enum { +- TCC_OPTION_HELP, +- TCC_OPTION_I, +- TCC_OPTION_D, +- TCC_OPTION_U, +- TCC_OPTION_L, +- TCC_OPTION_B, +- TCC_OPTION_l, +- TCC_OPTION_bench, +- TCC_OPTION_bt, +- TCC_OPTION_b, +- TCC_OPTION_g, +- TCC_OPTION_c, +- TCC_OPTION_static, +- TCC_OPTION_shared, +- TCC_OPTION_o, +- TCC_OPTION_r, +- TCC_OPTION_Wl, +- TCC_OPTION_W, +- TCC_OPTION_O, +- TCC_OPTION_m, +- TCC_OPTION_f, +- TCC_OPTION_nostdinc, +- TCC_OPTION_nostdlib, +- TCC_OPTION_print_search_dirs, +- TCC_OPTION_rdynamic, +- TCC_OPTION_run, +- TCC_OPTION_v, +- TCC_OPTION_w, +- TCC_OPTION_pipe, +-}; +- +-static const TCCOption tcc_options[] = { +- { "h", TCC_OPTION_HELP, 0 }, +- { "?", TCC_OPTION_HELP, 0 }, +- { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, +- { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, +- { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, +- { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG }, +- { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG }, +- { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, +- { "bench", TCC_OPTION_bench, 0 }, +- { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG }, +-#ifdef CONFIG_TCC_BCHECK +- { "b", TCC_OPTION_b, 0 }, +-#endif +- { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, +- { "c", TCC_OPTION_c, 0 }, +- { "static", TCC_OPTION_static, 0 }, +- { "shared", TCC_OPTION_shared, 0 }, +- { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, +- { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, +- { "rdynamic", TCC_OPTION_rdynamic, 0 }, +- { "r", TCC_OPTION_r, 0 }, +- { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, +- { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, +- { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, +- { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG }, +- { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, +- { "nostdinc", TCC_OPTION_nostdinc, 0 }, +- { "nostdlib", TCC_OPTION_nostdlib, 0 }, +- { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, +- { "v", TCC_OPTION_v, 0 }, +- { "w", TCC_OPTION_w, 0 }, +- { "pipe", TCC_OPTION_pipe, 0}, +- { NULL }, +-}; +- +-/* convert 'str' into an array of space separated strings */ +-static int expand_args(char ***pargv, const char *str) +-{ +- const char *s1; +- char **argv, *arg; +- int argc, len; +- +- argc = 0; +- argv = NULL; +- for(;;) { +- while (is_space(*str)) +- str++; +- if (*str == '\0') +- break; +- s1 = str; +- while (*str != '\0' && !is_space(*str)) +- str++; +- len = str - s1; +- arg = tcc_malloc(len + 1); +- memcpy(arg, s1, len); +- arg[len] = '\0'; +- dynarray_add((void ***)&argv, &argc, arg); +- } +- *pargv = argv; +- return argc; +-} +- +-static char **files; +-static int nb_files, nb_libraries; +-static int multiple_files; +-static int print_search_dirs; +-static int output_type; +-static int reloc_output; +-static const char *outfile; +- +-int parse_args(TCCState *s, int argc, char **argv) +-{ +- int optind; +- const TCCOption *popt; +- const char *optarg, *p1, *r1; +- char *r; +- +- optind = 0; +- while (1) { +- if (optind >= argc) { +- if (nb_files == 0 && !print_search_dirs) +- goto show_help; +- else +- break; +- } +- r = argv[optind++]; +- if (r[0] != '-') { +- /* add a new file */ +- dynarray_add((void ***)&files, &nb_files, r); +- if (!multiple_files) { +- optind--; +- /* argv[0] will be this file */ +- break; +- } +- } else { +- /* find option in table (match only the first chars */ +- popt = tcc_options; +- for(;;) { +- p1 = popt->name; +- if (p1 == NULL) +- error("invalid option -- '%s'", r); +- r1 = r + 1; +- for(;;) { +- if (*p1 == '\0') +- goto option_found; +- if (*r1 != *p1) +- break; +- p1++; +- r1++; +- } +- popt++; +- } +- option_found: +- if (popt->flags & TCC_OPTION_HAS_ARG) { +- if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) { +- optarg = r1; +- } else { +- if (optind >= argc) +- error("argument to '%s' is missing", r); +- optarg = argv[optind++]; +- } +- } else { +- if (*r1 != '\0') +- goto show_help; +- optarg = NULL; +- } +- +- switch(popt->index) { +- case TCC_OPTION_HELP: +- show_help: +- help(); +- exit(1); +- case TCC_OPTION_I: +- if (tcc_add_include_path(s, optarg) < 0) +- error("too many include paths"); +- break; +- case TCC_OPTION_D: +- { +- char *sym, *value; +- sym = (char *)optarg; +- value = strchr(sym, '='); +- if (value) { +- *value = '\0'; +- value++; +- } +- tcc_define_symbol(s, sym, value); +- } +- break; +- case TCC_OPTION_U: +- tcc_undefine_symbol(s, optarg); +- break; +- case TCC_OPTION_L: +- tcc_add_library_path(s, optarg); +- break; +- case TCC_OPTION_B: +- /* set tcc utilities path (mainly for tcc development) */ +- tcc_lib_path = optarg; +- break; +- case TCC_OPTION_l: +- dynarray_add((void ***)&files, &nb_files, r); +- nb_libraries++; +- break; +- case TCC_OPTION_bench: +- do_bench = 1; +- break; +- case TCC_OPTION_bt: +- num_callers = atoi(optarg); +- break; +-#ifdef CONFIG_TCC_BCHECK +- case TCC_OPTION_b: +- do_bounds_check = 1; +- do_debug = 1; +- break; +-#endif +- case TCC_OPTION_g: +- do_debug = 1; +- break; +- case TCC_OPTION_c: +- multiple_files = 1; +- output_type = TCC_OUTPUT_OBJ; +- break; +- case TCC_OPTION_static: +- s->static_link = 1; +- break; +- case TCC_OPTION_shared: +- output_type = TCC_OUTPUT_DLL; +- break; +- case TCC_OPTION_o: +- multiple_files = 1; +- outfile = optarg; +- break; +- case TCC_OPTION_r: +- /* generate a .o merging several output files */ +- reloc_output = 1; +- output_type = TCC_OUTPUT_OBJ; +- break; +- case TCC_OPTION_nostdinc: +- s->nostdinc = 1; +- break; +- case TCC_OPTION_nostdlib: +- s->nostdlib = 1; +- break; +- case TCC_OPTION_print_search_dirs: +- print_search_dirs = 1; +- break; +- case TCC_OPTION_run: +- { +- int argc1; +- char **argv1; +- argc1 = expand_args(&argv1, optarg); +- if (argc1 > 0) { +- parse_args(s, argc1, argv1); +- } +- multiple_files = 0; +- output_type = TCC_OUTPUT_MEMORY; +- } +- break; +- case TCC_OPTION_v: +- printf("tcc version %s\n", TCC_VERSION); +- exit(0); +- case TCC_OPTION_f: +- if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported) +- goto unsupported_option; +- break; +- case TCC_OPTION_W: +- if (tcc_set_warning(s, optarg, 1) < 0 && +- s->warn_unsupported) +- goto unsupported_option; +- break; +- case TCC_OPTION_w: +- s->warn_none = 1; +- break; +- case TCC_OPTION_rdynamic: +- s->rdynamic = 1; +- break; +- case TCC_OPTION_Wl: +- { +- const char *p; +- if (strstart(optarg, "-Ttext,", &p)) { +- s->text_addr = strtoul(p, NULL, 16); +- s->has_text_addr = 1; +- } else if (strstart(optarg, "--oformat,", &p)) { +- if (strstart(p, "elf32-", NULL)) { +- s->output_format = TCC_OUTPUT_FORMAT_ELF; +- } else if (!strcmp(p, "binary")) { +- s->output_format = TCC_OUTPUT_FORMAT_BINARY; +- } else +-#ifdef TCC_TARGET_COFF +- if (!strcmp(p, "coff")) { +- s->output_format = TCC_OUTPUT_FORMAT_COFF; +- } else +-#endif +- { +- error("target %s not found", p); +- } +- } else { +- error("unsupported linker option '%s'", optarg); +- } +- } +- break; +- default: +- if (s->warn_unsupported) { +- unsupported_option: +- warning("unsupported option '%s'", r); +- } +- break; +- } +- } +- } +- return optind; +-} +- +-int main(int argc, char **argv) +-{ +- int i; +- TCCState *s; +- int nb_objfiles, ret, optind; +- char objfilename[1024]; +- int64_t start_time = 0; +- +-#ifdef WIN32 +- /* on win32, we suppose the lib and includes are at the location +- of 'tcc.exe' */ +- { +- static char path[1024]; +- char *p, *d; +- +- GetModuleFileNameA(NULL, path, sizeof path); +- p = d = strlwr(path); +- while (*d) +- { +- if (*d == '\\') *d = '/', p = d; +- ++d; +- } +- *p = '\0'; +- tcc_lib_path = path; +- } +-#endif +- +- s = tcc_new(); +- output_type = TCC_OUTPUT_EXE; +- outfile = NULL; +- multiple_files = 1; +- files = NULL; +- nb_files = 0; +- nb_libraries = 0; +- reloc_output = 0; +- print_search_dirs = 0; +- +- optind = parse_args(s, argc - 1, argv + 1) + 1; +- +- if (print_search_dirs) { +- /* enough for Linux kernel */ +- printf("install: %s/\n", tcc_lib_path); +- return 0; +- } +- +- nb_objfiles = nb_files - nb_libraries; +- +- /* if outfile provided without other options, we output an +- executable */ +- if (outfile && output_type == TCC_OUTPUT_MEMORY) +- output_type = TCC_OUTPUT_EXE; +- +- /* check -c consistency : only single file handled. XXX: checks file type */ +- if (output_type == TCC_OUTPUT_OBJ && !reloc_output) { +- /* accepts only a single input file */ +- if (nb_objfiles != 1) +- error("cannot specify multiple files with -c"); +- if (nb_libraries != 0) +- error("cannot specify libraries with -c"); +- } +- +- if (output_type != TCC_OUTPUT_MEMORY) { +- if (!outfile) { +- /* compute default outfile name */ +- pstrcpy(objfilename, sizeof(objfilename) - 1, +- /* strip path */ +- tcc_basename(files[0])); +-#ifdef TCC_TARGET_PE +- pe_guess_outfile(objfilename, output_type); +-#else +- if (output_type == TCC_OUTPUT_OBJ && !reloc_output) { +- char *ext = strrchr(objfilename, '.'); +- if (!ext) +- goto default_outfile; +- /* add .o extension */ +- strcpy(ext + 1, "o"); +- } else { +- default_outfile: +- pstrcpy(objfilename, sizeof(objfilename), "a.out"); +- } +-#endif +- outfile = objfilename; +- } +- } +- +- if (do_bench) { +- start_time = getclock_us(); +- } +- +- tcc_set_output_type(s, output_type); +- +- /* compile or add each files or library */ +- for(i = 0;i < nb_files; i++) { +- const char *filename; +- +- filename = files[i]; +- if (filename[0] == '-') { +- if (tcc_add_library(s, filename + 2) < 0) +- error("cannot find %s", filename); +- } else { +- if (tcc_add_file(s, filename) < 0) { +- ret = 1; +- goto the_end; +- } +- } +- } +- +- /* free all files */ +- tcc_free(files); +- +- if (do_bench) { +- double total_time; +- total_time = (double)(getclock_us() - start_time) / 1000000.0; +- if (total_time < 0.001) +- total_time = 0.001; +- if (total_bytes < 1) +- total_bytes = 1; +- printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", +- tok_ident - TOK_IDENT, total_lines, total_bytes, +- total_time, (int)(total_lines / total_time), +- total_bytes / total_time / 1000000.0); +- } +- +- if (s->output_type == TCC_OUTPUT_MEMORY) { +- ret = tcc_run(s, argc - optind, argv + optind); +- } else +-#ifdef TCC_TARGET_PE +- if (s->output_type != TCC_OUTPUT_OBJ) { +- ret = tcc_output_pe(s, outfile); +- } else +-#endif +- { +- tcc_output_file(s, outfile); +- ret = 0; +- } +- the_end: +- /* XXX: cannot do it with bound checking because of the malloc hooks */ +- if (!do_bounds_check) +- tcc_delete(s); +- +-#ifdef MEM_DEBUG +- if (do_bench) { +- printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size); +- } +-#endif +- return ret; +-} +- +-#endif ++#include "tcltcc.c" +--- tcc-0.9.24/tcccoff.c 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/tcccoff.c 2007-11-07 10:04:32.000000000 -0500 +@@ -1,5 +1,5 @@ + /* +- * COFF file handling for TCC ++ * COFF file handling for TCC (Needed for c67 target) + * + * Copyright (c) 2003, 2004 TK + * Copyright (c) 2004 Fabrice Bellard +@@ -107,7 +107,7 @@ + o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ + + +- // create all the section headers ++ /* create all the section headers */ + + file_pointer = FILHSZ + sizeof(AOUTHDR); + +@@ -121,7 +121,7 @@ + NSectionsToOutput++; + + if (CoffTextSectionNo == -1 && tcc_sect == stext) +- CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is ++ CoffTextSectionNo = NSectionsToOutput; /* rem which coff sect number the .text sect is */ + + strcpy(coff_sec->s_name, tcc_sect->name); /* section name */ + +@@ -142,8 +142,8 @@ + + file_hdr.f_nscns = NSectionsToOutput; /* number of sections */ + +- // now loop through and determine file pointer locations +- // for the raw data ++ /* now loop through and determine file pointer locations */ ++ /* for the raw data */ + + + for (i = 1; i < s1->nb_sections; i++) { +@@ -151,21 +151,21 @@ + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { +- // put raw data ++ /* put raw data */ + coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */ + file_pointer += coff_sec->s_size; + } + } + +- // now loop through and determine file pointer locations +- // for the relocation data ++ /* now loop through and determine file pointer locations */ ++ /* for the relocation data */ + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { +- // put relocations data ++ /* put relocations data */ + if (coff_sec->s_nreloc > 0) { + coff_sec->s_relptr = file_pointer; /* file ptr to relocation */ + file_pointer += coff_sec->s_nreloc * sizeof(struct reloc); +@@ -173,8 +173,8 @@ + } + } + +- // now loop through and determine file pointer locations +- // for the line number data ++ /* now loop through and determine file pointer locations */ ++ /* for the line number data */ + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; +@@ -184,10 +184,10 @@ + coff_sec->s_lnnoptr = 0; + + if (do_debug && tcc_sect == stext) { +- // count how many line nos data ++ /* count how many line nos data */ + +- // also find association between source file name and function +- // so we can sort the symbol table ++ /* also find association between source file name and function */ ++ /* so we can sort the symbol table */ + + + Stab_Sym *sym, *sym_end; +@@ -218,7 +218,7 @@ + /* function start or end */ + case N_FUN: + if (sym->n_strx == 0) { +- // end of function ++ /* end of function */ + + coff_sec->s_nlnno++; + file_pointer += LINESZ; +@@ -232,7 +232,7 @@ + LineNoFilePtr[nFuncs]) / LINESZ - 1; + LastLineNo[nFuncs++] = last_line_num + 1; + } else { +- // beginning of function ++ /* beginning of function */ + + LineNoFilePtr[nFuncs] = file_pointer; + coff_sec->s_nlnno++; +@@ -255,7 +255,7 @@ + func_name[len] = '\0'; + } + +- // save the file that it came in so we can sort later ++ /* save the file that it came in so we can sort later */ + pstrcpy(AssociatedFile[nFuncs], sizeof(func_name), + incl_files[incl_index - 1]); + +@@ -318,13 +318,13 @@ + + file_pointer += file_hdr.f_nsyms * SYMNMLEN; + +- // OK now we are all set to write the file ++ /* OK now we are all set to write the file */ + + + fwrite(&file_hdr, FILHSZ, 1, f); + fwrite(&o_filehdr, sizeof(o_filehdr), 1, f); + +- // write section headers ++ /* write section headers */ + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; +@@ -334,7 +334,7 @@ + } + } + +- // write raw data ++ /* write raw data */ + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; +@@ -344,13 +344,13 @@ + } + } + +- // write relocation data ++ /* write relocation data */ + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (OutputTheSection(tcc_sect)) { +- // put relocations data ++ /* put relocations data */ + if (coff_sec->s_nreloc > 0) { + fwrite(tcc_sect->reloc, + coff_sec->s_nreloc * sizeof(struct reloc), 1, f); +@@ -359,20 +359,20 @@ + } + + +- // group the symbols in order of filename, func1, func2, etc +- // finally global symbols ++ /* group the symbols in order of filename, func1, func2, etc */ ++ /* finally global symbols */ + + if (do_debug) + SortSymbolTable(); + +- // write line no data ++ /* write line no data */ + + for (i = 1; i < s1->nb_sections; i++) { + coff_sec = §ion_header[i]; + tcc_sect = s1->sections[i]; + + if (do_debug && tcc_sect == stext) { +- // count how many line nos data ++ /* count how many line nos data */ + + + Stab_Sym *sym, *sym_end; +@@ -400,7 +400,7 @@ + /* function start or end */ + case N_FUN: + if (sym->n_strx == 0) { +- // end of function ++ /* end of function */ + + CoffLineNo.l_addr.l_paddr = last_pc; + CoffLineNo.l_lnno = last_line_num + 1; +@@ -410,7 +410,7 @@ + func_name[0] = '\0'; + func_addr = 0; + } else { +- // beginning of function ++ /* beginning of function */ + + str = + (const char *) stabstr_section->data + +@@ -431,7 +431,7 @@ + last_pc = func_addr; + last_line_num = -1; + +- // output a function begin ++ /* output a function begin */ + + CoffLineNo.l_addr.l_symndx = + FindCoffSymbolIndex(func_name); +@@ -449,7 +449,7 @@ + /* XXX: slow! */ + strcpy(last_func_name, func_name); + +- // output a line reference ++ /* output a line reference */ + + CoffLineNo.l_addr.l_paddr = last_pc; + +@@ -498,7 +498,7 @@ + } + } + +- // write symbol table ++ /* write symbol table */ + if (do_debug) { + int k; + struct syment csym; +@@ -537,13 +537,13 @@ + pCoff_str_table - Coff_str_table + 4; + + strcpy(pCoff_str_table, name); +- pCoff_str_table += strlen(name) + 1; // skip over null ++ pCoff_str_table += strlen(name) + 1; /* skip over null */ + nstr++; + } + + if (p->st_info == 4) { +- // put a filename symbol +- csym.n_value = 33; // ????? ++ /* put a filename symbol */ ++ csym.n_value = 33; /* ????? */ + csym.n_scnum = N_DEBUG; + csym.n_type = 0; + csym.n_sclass = C_FILE; +@@ -552,7 +552,7 @@ + n++; + + } else if (p->st_info == 0x12) { +- // find the function data ++ /* find the function data */ + + for (k = 0; k < nFuncs; k++) { + if (strcmp(name, Func[k]) == 0) +@@ -566,35 +566,35 @@ + + error(s); + } +- // put a Function Name ++ /* put a Function Name */ + +- csym.n_value = p->st_value; // physical address ++ csym.n_value = p->st_value; /* physical address */ + csym.n_scnum = CoffTextSectionNo; + csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0); + csym.n_sclass = C_EXT; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + +- // now put aux info ++ /* now put aux info */ + + auxfunc.tag = 0; + auxfunc.size = EndAddress[k] - p->st_value; + auxfunc.fileptr = LineNoFilePtr[k]; +- auxfunc.nextsym = n + 6; // tktk ++ auxfunc.nextsym = n + 6; /* tktk */ + auxfunc.dummy = 0; + fwrite(&auxfunc, 18, 1, f); + +- // put a .bf ++ /* put a .bf */ + + strcpy(csym._n._n_name, ".bf"); +- csym.n_value = p->st_value; // physical address ++ csym.n_value = p->st_value; /* physical address */ + csym.n_scnum = CoffTextSectionNo; + csym.n_type = 0; + csym.n_sclass = C_FCN; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + +- // now put aux info ++ /* now put aux info */ + + auxbf.regmask = 0; + auxbf.lineno = 0; +@@ -604,17 +604,17 @@ + auxbf.dummy = 0; + fwrite(&auxbf, 18, 1, f); + +- // put a .ef ++ /* put a .ef */ + + strcpy(csym._n._n_name, ".ef"); +- csym.n_value = EndAddress[k]; // physical address ++ csym.n_value = EndAddress[k]; /* physical address */ + csym.n_scnum = CoffTextSectionNo; + csym.n_type = 0; + csym.n_sclass = C_FCN; + csym.n_numaux = 1; + fwrite(&csym, 18, 1, f); + +- // now put aux info ++ /* now put aux info */ + + auxef.dummy = 0; + auxef.lineno = LastLineNo[k]; +@@ -627,16 +627,16 @@ + n += 6; + + } else { +- // try an put some type info ++ /* try an put some type info */ + + if ((p->st_other & VT_BTYPE) == VT_DOUBLE) { +- csym.n_type = T_DOUBLE; // int ++ csym.n_type = T_DOUBLE; /* int */ + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) { + csym.n_type = T_FLOAT; + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_INT) { +- csym.n_type = T_INT; // int ++ csym.n_type = T_INT; /* int */ + csym.n_sclass = C_EXT; + } else if ((p->st_other & VT_BTYPE) == VT_SHORT) { + csym.n_type = T_SHORT; +@@ -645,7 +645,7 @@ + csym.n_type = T_CHAR; + csym.n_sclass = C_EXT; + } else { +- csym.n_type = T_INT; // just mark as a label ++ csym.n_type = T_INT; /* just mark as a label */ + csym.n_sclass = C_LABEL; + } + +@@ -671,16 +671,16 @@ + } + + if (do_debug) { +- // write string table ++ /* write string table */ + +- // first write the size ++ /* first write the size */ + i = pCoff_str_table - Coff_str_table; + fwrite(&i, 4, 1, f); + +- // then write the strings ++ /* then write the strings */ + fwrite(Coff_str_table, i, 1, f); + +- tcc_free(Coff_str_table); ++ free(Coff_str_table); + } + + return 0; +@@ -688,8 +688,8 @@ + + + +-// group the symbols in order of filename, func1, func2, etc +-// finally global symbols ++/* group the symbols in order of filename, func1, func2, etc */ ++/* finally global symbols */ + + void SortSymbolTable(void) + { +@@ -702,15 +702,15 @@ + p = (Elf32_Sym *) symtab_section->data; + + +- // find a file symbol, copy it over +- // then scan the whole symbol list and copy any function +- // symbols that match the file association ++ /* find a file symbol, copy it over */ ++ /* then scan the whole symbol list and copy any function */ ++ /* symbols that match the file association */ + + for (i = 0; i < nb_syms; i++) { + if (p->st_info == 4) { + name = (char *) symtab_section->link->data + p->st_name; + +- // this is a file symbol, copy it over ++ /* this is a file symbol, copy it over */ + + NewTable[n++] = *p; + +@@ -718,12 +718,12 @@ + + for (j = 0; j < nb_syms; j++) { + if (p2->st_info == 0x12) { +- // this is a func symbol ++ /* this is a func symbol */ + + name2 = + (char *) symtab_section->link->data + p2->st_name; + +- // find the function data index ++ /* find the function data index */ + + for (k = 0; k < nFuncs; k++) { + if (strcmp(name2, Func[k]) == 0) +@@ -741,7 +741,7 @@ + } + + if (strcmp(AssociatedFile[k], name) == 0) { +- // yes they match copy it over ++ /* yes they match copy it over */ + + NewTable[n++] = *p2; + } +@@ -752,8 +752,8 @@ + p++; + } + +- // now all the filename and func symbols should have been copied over +- // copy all the rest over (all except file and funcs) ++ /* now all the filename and func symbols should have been copied over */ ++ /* copy all the rest over (all except file and funcs) */ + + p = (Elf32_Sym *) symtab_section->data; + for (i = 0; i < nb_syms; i++) { +@@ -766,14 +766,14 @@ + if (n != nb_syms) + error("Internal Compiler error, debug info"); + +- // copy it all back ++ /* copy it all back */ + + p = (Elf32_Sym *) symtab_section->data; + for (i = 0; i < nb_syms; i++) { + *p++ = NewTable[i]; + } + +- tcc_free(NewTable); ++ free(NewTable); + } + + +@@ -790,7 +790,7 @@ + name = (char *) symtab_section->link->data + p->st_name; + + if (p->st_info == 4) { +- // put a filename symbol ++ /* put a filename symbol */ + n++; + } else if (p->st_info == 0x12) { + +@@ -799,17 +799,17 @@ + + n += 6; + +- // put a Function Name ++ /* put a Function Name */ + +- // now put aux info ++ /* now put aux info */ + +- // put a .bf ++ /* put a .bf */ + +- // now put aux info ++ /* now put aux info */ + +- // put a .ef ++ /* put a .ef */ + +- // now put aux info ++ /* now put aux info */ + + } else { + n += 2; +@@ -818,7 +818,7 @@ + p++; + } + +- return n; // total number of symbols ++ return n; /* total number of symbols */ + } + + BOOL OutputTheSection(Section * sect) +@@ -867,7 +867,7 @@ + + int tcc_load_coff(TCCState * s1, int fd) + { +-// tktk TokenSym *ts; ++/* tktk TokenSym *ts; */ + + FILE *f; + unsigned int str_size; +@@ -888,7 +888,7 @@ + if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1) + error("error reading .out file for input"); + +- // first read the string table ++ /* first read the string table */ + + if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET)) + error("error reading .out file for input"); +@@ -902,9 +902,9 @@ + if (fread(Coff_str_table, str_size - 4, 1, f) != 1) + error("error reading .out file for input"); + +- // read/process all the symbols ++ /* read/process all the symbols */ + +- // seek back to symbols ++ /* seek back to symbols */ + + if (fseek(f, file_hdr.f_symptr, SEEK_SET)) + error("error reading .out file for input"); +@@ -927,22 +927,22 @@ + name = name2; + } + } +-// if (strcmp("_DAC_Buffer",name)==0) // tktk +-// name[0]=0; ++/* if (strcmp("_DAC_Buffer",name)==0) // tktk */ ++/* name[0]=0; */ + +- if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures +- (csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure +- (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles +- (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats ++ if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || /* structures */ ++ (csym.n_type == 0x18 && csym.n_sclass == 0x2) || /* pointer to structure */ ++ (csym.n_type == 0x7 && csym.n_sclass == 0x2) || /* doubles */ ++ (csym.n_type == 0x6 && csym.n_sclass == 0x2)) /* floats */ + { +- // strip off any leading underscore (except for other main routine) ++ /* strip off any leading underscore (except for other main routine) */ + + if (name[0] == '_' && strcmp(name, "_main") != 0) + name++; + + tcc_add_symbol(s1, name, csym.n_value); + } +- // skip any aux records ++ /* skip any aux records */ + + if (csym.n_numaux == 1) { + if (fread(&csym, SYMESZ, 1, f) != 1) +--- tcc-0.9.23/tcc-doc.texi 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/tcc-doc.texi 2007-11-07 10:04:32.000000000 -0500 +@@ -123,10 +123,10 @@ + Scripting: + + TCC can be invoked from @emph{scripts}, just as shell scripts. You just +-need to add @code{#!/usr/local/bin/tcc -run} at the start of your C source: ++need to add @code{#!/usr/bin/tcc -run} at the start of your C source: + + @example +-#!/usr/local/bin/tcc -run ++#!/usr/bin/tcc -run + #include + + int main() +@@ -173,7 +173,7 @@ + In a script, it gives the following header: + + @example +-#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 ++#!/usr/bin/tcc -run -L/usr/X11R6/lib -lX11 + #include + int main(int argc, char **argv) + @{ +--- tcc-0.9.24/tccelf.c 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/tccelf.c 2007-11-07 10:04:32.000000000 -0500 +@@ -18,14 +18,16 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +-static int put_elf_str(Section *s, const char *sym) ++#include ++ ++static int put_elf_str(TCCState *st, Section *s, const char *sym) + { + int offset, len; + char *ptr; + + len = strlen(sym) + 1; + offset = s->data_offset; +- ptr = section_ptr_add(s, len); ++ ptr = section_ptr_add(st, s, len); + memcpy(ptr, sym, len); + return offset; + } +@@ -47,7 +49,7 @@ + + /* rebuild hash table of section s */ + /* NOTE: we do factorize the hash table code to go faster */ +-static void rebuild_hash(Section *s, unsigned int nb_buckets) ++static void rebuild_hash(TCCState *st, Section *s, unsigned int nb_buckets) + { + Elf32_Sym *sym; + int *ptr, *hash, nb_syms, sym_index, h; +@@ -57,7 +59,7 @@ + nb_syms = s->data_offset / sizeof(Elf32_Sym); + + s->hash->data_offset = 0; +- ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int)); ++ ptr = section_ptr_add(st, s->hash, (2 + nb_buckets + nb_syms) * sizeof(int)); + ptr[0] = nb_buckets; + ptr[1] = nb_syms; + ptr += 2; +@@ -80,7 +82,8 @@ + } + + /* return the symbol number */ +-static int put_elf_sym(Section *s, ++static int put_elf_sym(TCCState *st, ++ Section *s, + unsigned long value, unsigned long size, + int info, int other, int shndx, const char *name) + { +@@ -89,9 +92,9 @@ + Elf32_Sym *sym; + Section *hs; + +- sym = section_ptr_add(s, sizeof(Elf32_Sym)); ++ sym = section_ptr_add(st, s, sizeof(Elf32_Sym)); + if (name) +- name_offset = put_elf_str(s->link, name); ++ name_offset = put_elf_str(st, s->link, name); + else + name_offset = 0; + /* XXX: endianness */ +@@ -105,7 +108,7 @@ + hs = s->hash; + if (hs) { + int *ptr, *base; +- ptr = section_ptr_add(hs, sizeof(int)); ++ ptr = section_ptr_add(st, hs, sizeof(int)); + base = (int *)hs->data; + /* only add global or weak symbols */ + if (ELF32_ST_BIND(info) != STB_LOCAL) { +@@ -118,7 +121,7 @@ + /* we resize the hash table */ + hs->nb_hashed_syms++; + if (hs->nb_hashed_syms > 2 * nbuckets) { +- rebuild_hash(s, 2 * nbuckets); ++ rebuild_hash(st, s, 2 * nbuckets); + } + } else { + *ptr = 0; +@@ -154,7 +157,7 @@ + } + + /* return elf symbol value or error */ +-int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name) ++int tcc_get_symbol(TCCState *st, unsigned long *pval, const char *name) + { + int sym_index; + Elf32_Sym *sym; +@@ -167,17 +170,17 @@ + return 0; + } + +-void *tcc_get_symbol_err(TCCState *s, const char *name) ++void *tcc_get_symbol_err(TCCState *st, const char *name) + { + unsigned long val; +- if (tcc_get_symbol(s, &val, name) < 0) +- error("%s not defined", name); ++ if (tcc_get_symbol(st, &val, name) < 0) ++ tcc_error(st, "%s not defined", name); + return (void *)val; + } + + /* add an elf symbol : check if it is already defined and patch + it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ +-static int add_elf_sym(Section *s, unsigned long value, unsigned long size, ++static int add_elf_sym(TCCState *st, Section *s, unsigned long value, unsigned long size, + int info, int other, int sh_num, const char *name) + { + Elf32_Sym *esym; +@@ -206,7 +209,7 @@ + } else { + new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis; + } +- esym->st_other = (esym->st_other & ~ELF32_ST_VISIBILITY(-1)) ++ esym->st_other = (esym->st_other & ~ELF32_ST_VISIBILITY(UCHAR_MAX)) + | new_vis; + other = esym->st_other; /* in case we have to patch esym */ + if (sh_num == SHN_UNDEF) { +@@ -219,18 +222,14 @@ + /* weak is ignored if already global */ + } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) { + /* ignore hidden symbols after */ +- } else if (esym->st_shndx == SHN_COMMON && sh_num < SHN_LORESERVE) { +- /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01 +- No idea if this is the correct solution ... */ +- goto do_patch; +- } else if (s == tcc_state->dynsymtab_section) { +- /* we accept that two DLL define the same symbol */ + } else { +-#if 1 +- printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n", +- sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis); ++#if 0 ++ printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n", ++ sym_bind, sh_num, esym_bind, esym->st_shndx); + #endif +- error_noabort("'%s' defined twice", name); ++ /* NOTE: we accept that two DLL define the same symbol */ ++ if (s != st->dynsymtab_section) ++ error_noabort(st, "'%s' defined twice", name); + } + } else { + do_patch: +@@ -242,7 +241,7 @@ + } + } else { + do_def: +- sym_index = put_elf_sym(s, value, size, ++ sym_index = put_elf_sym(st, s, value, size, + ELF32_ST_INFO(sym_bind, sym_type), other, + sh_num, name); + } +@@ -250,7 +249,7 @@ + } + + /* put relocation */ +-static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, ++static void put_elf_reloc(TCCState * st, Section *symtab, Section *s, unsigned long offset, + int type, int symbol) + { + char buf[256]; +@@ -263,13 +262,13 @@ + snprintf(buf, sizeof(buf), ".rel%s", s->name); + /* if the symtab is allocated, then we consider the relocation + are also */ +- sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags); ++ sr = new_section(st, buf, SHT_REL, symtab->sh_flags); + sr->sh_entsize = sizeof(Elf32_Rel); + sr->link = symtab; + sr->sh_info = s->sh_num; + s->reloc = sr; + } +- rel = section_ptr_add(sr, sizeof(Elf32_Rel)); ++ rel = section_ptr_add(st, sr, sizeof(Elf32_Rel)); + rel->r_offset = offset; + rel->r_info = ELF32_R_INFO(symbol, type); + } +@@ -284,14 +283,15 @@ + unsigned long n_value; /* value of symbol */ + } Stab_Sym; + +-static void put_stabs(const char *str, int type, int other, int desc, ++static void put_stabs(TCCState *st, ++ const char *str, int type, int other, int desc, + unsigned long value) + { + Stab_Sym *sym; + +- sym = section_ptr_add(stab_section, sizeof(Stab_Sym)); ++ sym = section_ptr_add(st, stab_section, sizeof(Stab_Sym)); + if (str) { +- sym->n_strx = put_elf_str(stabstr_section, str); ++ sym->n_strx = put_elf_str(st, stabstr_section, str); + } else { + sym->n_strx = 0; + } +@@ -301,30 +301,31 @@ + sym->n_value = value; + } + +-static void put_stabs_r(const char *str, int type, int other, int desc, ++static void put_stabs_r(TCCState *st, ++ const char *str, int type, int other, int desc, + unsigned long value, Section *sec, int sym_index) + { +- put_stabs(str, type, other, desc, value); +- put_elf_reloc(symtab_section, stab_section, ++ put_stabs(st, str, type, other, desc, value); ++ put_elf_reloc(st, symtab_section, stab_section, + stab_section->data_offset - sizeof(unsigned long), + R_DATA_32, sym_index); + } + +-static void put_stabn(int type, int other, int desc, int value) ++static void put_stabn(TCCState *st, int type, int other, int desc, int value) + { +- put_stabs(NULL, type, other, desc, value); ++ put_stabs(st, NULL, type, other, desc, value); + } + +-static void put_stabd(int type, int other, int desc) ++static void put_stabd(TCCState *st, int type, int other, int desc) + { +- put_stabs(NULL, type, other, desc, 0); ++ put_stabs(st, NULL, type, other, desc, 0); + } + + /* In an ELF file symbol table, the local symbols must appear below + the global and weak ones. Since TCC cannot sort it while generating + the code, we must do it after. All the relocation tables are also + modified to take into account the symbol table sorting */ +-static void sort_syms(TCCState *s1, Section *s) ++static void sort_syms(TCCState *st, Section *s) + { + int *old_to_new_syms; + Elf32_Sym *new_syms; +@@ -335,8 +336,8 @@ + int type, sym_index; + + nb_syms = s->data_offset / sizeof(Elf32_Sym); +- new_syms = tcc_malloc(nb_syms * sizeof(Elf32_Sym)); +- old_to_new_syms = tcc_malloc(nb_syms * sizeof(int)); ++ new_syms = tcc_malloc(st, nb_syms * sizeof(Elf32_Sym)); ++ old_to_new_syms = tcc_malloc(st, nb_syms * sizeof(int)); + + /* first pass for local symbols */ + p = (Elf32_Sym *)s->data; +@@ -363,11 +364,11 @@ + + /* we copy the new symbols to the old */ + memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym)); +- tcc_free(new_syms); ++ ckfree((char *)new_syms); + + /* now we modify all the relocations */ +- for(i = 1; i < s1->nb_sections; i++) { +- sr = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ sr = st->sections[i]; + if (sr->sh_type == SHT_REL && sr->link == s) { + rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); + for(rel = (Elf32_Rel *)sr->data; +@@ -381,7 +382,7 @@ + } + } + +- tcc_free(old_to_new_syms); ++ ckfree((char *)old_to_new_syms); + } + + /* relocate common symbols in the .bss section */ +@@ -409,7 +410,7 @@ + + /* relocate symbol table, resolve undefined symbols if do_resolve is + true and output error if undefined symbol. */ +-static void relocate_syms(TCCState *s1, int do_resolve) ++static void relocate_syms(TCCState *st, int do_resolve) + { + Elf32_Sym *sym, *esym, *sym_end; + int sym_bind, sh_num, sym_index; +@@ -425,16 +426,16 @@ + name = strtab_section->data + sym->st_name; + if (do_resolve) { + name = symtab_section->link->data + sym->st_name; +- addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info)); ++ addr = (unsigned long)resolve_sym(st, name, ELF32_ST_TYPE(sym->st_info)); + if (addr) { + sym->st_value = addr; + goto found; + } +- } else if (s1->dynsym) { ++ } else if (st->dynsym) { + /* if dynamic symbol exist, then use it */ +- sym_index = find_elf_sym(s1->dynsym, name); ++ sym_index = find_elf_sym(st->dynsym, name); + if (sym_index) { +- esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index]; ++ esym = &((Elf32_Sym *)st->dynsym->data)[sym_index]; + sym->st_value = esym->st_value; + goto found; + } +@@ -449,18 +450,18 @@ + if (sym_bind == STB_WEAK) { + sym->st_value = 0; + } else { +- error_noabort("undefined symbol '%s'", name); ++ error_noabort(st, "undefined symbol '%s'", name); + } + } else if (sh_num < SHN_LORESERVE) { + /* add section base */ +- sym->st_value += s1->sections[sym->st_shndx]->sh_addr; ++ sym->st_value += st->sections[sym->st_shndx]->sh_addr; + } + found: ; + } + } + + /* relocate a given section (CPU dependent) */ +-static void relocate_section(TCCState *s1, Section *s) ++static void relocate_section(TCCState *st, Section *s) + { + Section *sr; + Elf32_Rel *rel, *rel_end, *qrel; +@@ -490,8 +491,8 @@ + switch(type) { + #if defined(TCC_TARGET_I386) + case R_386_32: +- if (s1->output_type == TCC_OUTPUT_DLL) { +- esym_index = s1->symtab_to_dynsym[sym_index]; ++ if (st->output_type == TCC_OUTPUT_DLL) { ++ esym_index = st->symtab_to_dynsym[sym_index]; + qrel->r_offset = rel->r_offset; + if (esym_index) { + qrel->r_info = ELF32_R_INFO(esym_index, R_386_32); +@@ -505,9 +506,9 @@ + *(int *)ptr += val; + break; + case R_386_PC32: +- if (s1->output_type == TCC_OUTPUT_DLL) { ++ if (st->output_type == TCC_OUTPUT_DLL) { + /* DLL relocation */ +- esym_index = s1->symtab_to_dynsym[sym_index]; ++ esym_index = st->symtab_to_dynsym[sym_index]; + if (esym_index) { + qrel->r_offset = rel->r_offset; + qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32); +@@ -525,14 +526,14 @@ + *(int *)ptr = val; + break; + case R_386_GOTPC: +- *(int *)ptr += s1->got->sh_addr - addr; ++ *(int *)ptr += st->got->sh_addr - addr; + break; + case R_386_GOTOFF: +- *(int *)ptr += val - s1->got->sh_addr; ++ *(int *)ptr += val - st->got->sh_addr; + break; + case R_386_GOT32: + /* we load the got offset */ +- *(int *)ptr += s1->got_offsets[sym_index]; ++ *(int *)ptr += st->got_offsets[sym_index]; + break; + #elif defined(TCC_TARGET_ARM) + case R_ARM_PC24: +@@ -548,7 +549,7 @@ + x *= 4; + x += val - addr; + if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) +- error("can't relocate value at %x",addr); ++ tcc_error(st, "can't relocate value at %x",addr); + x >>= 2; + x &= 0xffffff; + (*(int *)ptr) |= x; +@@ -562,21 +563,21 @@ + x = (x * 2) / 2; + x += val - addr; + if((x^(x>>1))&0x40000000) +- error("can't relocate value at %x",addr); ++ tcc_error(st, "can't relocate value at %x",addr); + (*(int *)ptr) |= x & 0x7fffffff; + } + case R_ARM_ABS32: + *(int *)ptr += val; + break; + case R_ARM_BASE_PREL: +- *(int *)ptr += s1->got->sh_addr - addr; ++ *(int *)ptr += st->got->sh_addr - addr; + break; + case R_ARM_GOTOFF32: +- *(int *)ptr += val - s1->got->sh_addr; ++ *(int *)ptr += val - st->got->sh_addr; + break; + case R_ARM_GOT_BREL: + /* we load the got offset */ +- *(int *)ptr += s1->got_offsets[sym_index]; ++ *(int *)ptr += st->got_offsets[sym_index]; + break; + case R_ARM_COPY: + break; +@@ -593,12 +594,12 @@ + uint32_t orig; + + /* put the low 16 bits of the absolute address */ +- // add to what is already there ++ /* add to what is already there */ + + orig = ((*(int *)(ptr )) >> 7) & 0xffff; + orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16; + +- //patch both at once - assumes always in pairs Low - High ++ /*patch both at once - assumes always in pairs Low - High */ + + *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7); + *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7); +@@ -617,16 +618,16 @@ + } + /* if the relocation is allocated, we change its symbol table */ + if (sr->sh_flags & SHF_ALLOC) +- sr->link = s1->dynsym; ++ sr->link = st->dynsym; + } + + /* relocate relocation table in 'sr' */ +-static void relocate_rel(TCCState *s1, Section *sr) ++static void relocate_rel(TCCState *st, Section *sr) + { + Section *s; + Elf32_Rel *rel, *rel_end; + +- s = s1->sections[sr->sh_info]; ++ s = st->sections[sr->sh_info]; + rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); + for(rel = (Elf32_Rel *)sr->data; + rel < rel_end; +@@ -637,7 +638,7 @@ + + /* count the number of dynamic relocations so that we can reserve + their space */ +-static int prepare_dynamic_rel(TCCState *s1, Section *sr) ++static int prepare_dynamic_rel(TCCState *st, Section *sr) + { + Elf32_Rel *rel, *rel_end; + int sym_index, esym_index, type, count; +@@ -652,7 +653,7 @@ + count++; + break; + case R_386_PC32: +- esym_index = s1->symtab_to_dynsym[sym_index]; ++ esym_index = st->symtab_to_dynsym[sym_index]; + if (esym_index) + count++; + break; +@@ -668,25 +669,25 @@ + return count; + } + +-static void put_got_offset(TCCState *s1, int index, unsigned long val) ++static void put_got_offset(TCCState *st, int index, unsigned long val) + { + int n; + unsigned long *tab; + +- if (index >= s1->nb_got_offsets) { ++ if (index >= st->nb_got_offsets) { + /* find immediately bigger power of 2 and reallocate array */ + n = 1; + while (index >= n) + n *= 2; +- tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long)); ++ tab = tcc_realloc(st, st->got_offsets, n * sizeof(unsigned long)); + if (!tab) +- error("memory full"); +- s1->got_offsets = tab; +- memset(s1->got_offsets + s1->nb_got_offsets, 0, +- (n - s1->nb_got_offsets) * sizeof(unsigned long)); +- s1->nb_got_offsets = n; ++ tcc_error(st, "memory full"); ++ st->got_offsets = tab; ++ memset(st->got_offsets + st->nb_got_offsets, 0, ++ (n - st->nb_got_offsets) * sizeof(unsigned long)); ++ st->nb_got_offsets = n; + } +- s1->got_offsets[index] = val; ++ st->got_offsets[index] = val; + } + + /* XXX: suppress that */ +@@ -705,16 +706,16 @@ + } + #endif + +-static void build_got(TCCState *s1) ++static void build_got(TCCState *st) + { + unsigned char *ptr; + + /* if no got, then create it */ +- s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); +- s1->got->sh_entsize = 4; +- add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), +- 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_"); +- ptr = section_ptr_add(s1->got, 3 * sizeof(int)); ++ st->got = new_section(st, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); ++ st->got->sh_entsize = 4; ++ add_elf_sym(st, symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), ++ 0, st->got->sh_num, "_GLOBAL_OFFSET_TABLE_"); ++ ptr = section_ptr_add(st, st->got, 3 * sizeof(int)); + /* keep space for _DYNAMIC pointer, if present */ + put32(ptr, 0); + /* two dummy got entries */ +@@ -724,7 +725,7 @@ + + /* put a got entry corresponding to a symbol in symtab_section. 'size' + and 'info' can be modifed if more precise info comes from the DLL */ +-static void put_got_entry(TCCState *s1, ++static void put_got_entry(TCCState *st, + int reloc_type, unsigned long size, int info, + int sym_index) + { +@@ -734,17 +735,17 @@ + unsigned long offset; + int *ptr; + +- if (!s1->got) +- build_got(s1); ++ if (!st->got) ++ build_got(st); + + /* if a got entry already exists for that symbol, no need to add one */ +- if (sym_index < s1->nb_got_offsets && +- s1->got_offsets[sym_index] != 0) ++ if (sym_index < st->nb_got_offsets && ++ st->got_offsets[sym_index] != 0) + return; + +- put_got_offset(s1, sym_index, s1->got->data_offset); ++ put_got_offset(st, sym_index, st->got->data_offset); + +- if (s1->dynsym) { ++ if (st->dynsym) { + sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; + name = symtab_section->link->data + sym->st_name; + offset = sym->st_value; +@@ -755,16 +756,16 @@ + int modrm; + + /* if we build a DLL, we add a %ebx offset */ +- if (s1->output_type == TCC_OUTPUT_DLL) ++ if (st->output_type == TCC_OUTPUT_DLL) + modrm = 0xa3; + else + modrm = 0x25; + + /* add a PLT entry */ +- plt = s1->plt; ++ plt = st->plt; + if (plt->data_offset == 0) { + /* first plt entry */ +- p = section_ptr_add(plt, 16); ++ p = section_ptr_add(st, plt, 16); + p[0] = 0xff; /* pushl got + 4 */ + p[1] = modrm + 0x10; + put32(p + 2, 4); +@@ -773,10 +774,10 @@ + put32(p + 8, 8); + } + +- p = section_ptr_add(plt, 16); ++ p = section_ptr_add(st, plt, 16); + p[0] = 0xff; /* jmp *(got + x) */ + p[1] = modrm; +- put32(p + 2, s1->got->data_offset); ++ put32(p + 2, st->got->data_offset); + p[6] = 0x68; /* push $xxx */ + put32(p + 7, (plt->data_offset - 32) >> 1); + p[11] = 0xe9; /* jmp plt_start */ +@@ -784,7 +785,7 @@ + + /* the symbol is modified so that it will be relocated to + the PLT */ +- if (s1->output_type == TCC_OUTPUT_EXE) ++ if (st->output_type == TCC_OUTPUT_EXE) + offset = plt->data_offset - 16; + } + #elif defined(TCC_TARGET_ARM) +@@ -793,57 +794,57 @@ + uint8_t *p; + + /* if we build a DLL, we add a %ebx offset */ +- if (s1->output_type == TCC_OUTPUT_DLL) +- error("DLLs unimplemented!"); ++ if (st->output_type == TCC_OUTPUT_DLL) ++ tcc_error(st, "DLLs unimplemented!"); + + /* add a PLT entry */ +- plt = s1->plt; ++ plt = st->plt; + if (plt->data_offset == 0) { + /* first plt entry */ +- p = section_ptr_add(plt, 16); ++ p = section_ptr_add(st, plt, 16); + put32(p , 0xe52de004); + put32(p + 4, 0xe59fe010); + put32(p + 8, 0xe08fe00e); + put32(p + 12, 0xe5bef008); + } + +- p = section_ptr_add(plt, 16); ++ p = section_ptr_add(st, plt, 16); + put32(p , 0xe59fc004); + put32(p+4, 0xe08fc00c); + put32(p+8, 0xe59cf000); +- put32(p+12, s1->got->data_offset); ++ put32(p+12, st->got->data_offset); + + /* the symbol is modified so that it will be relocated to + the PLT */ +- if (s1->output_type == TCC_OUTPUT_EXE) ++ if (st->output_type == TCC_OUTPUT_EXE) + offset = plt->data_offset - 16; + } + #elif defined(TCC_TARGET_C67) +- error("C67 got not implemented"); ++ tcc_error(st, "C67 got not implemented"); + #else + #error unsupported CPU + #endif +- index = put_elf_sym(s1->dynsym, offset, ++ index = put_elf_sym(st, st->dynsym, offset, + size, info, 0, sym->st_shndx, name); + /* put a got entry */ +- put_elf_reloc(s1->dynsym, s1->got, +- s1->got->data_offset, ++ put_elf_reloc(st, st->dynsym, st->got, ++ st->got->data_offset, + reloc_type, index); + } +- ptr = section_ptr_add(s1->got, sizeof(int)); ++ ptr = section_ptr_add(st, st->got, sizeof(int)); + *ptr = 0; + } + + /* build GOT and PLT entries */ +-static void build_got_entries(TCCState *s1) ++static void build_got_entries(TCCState *st) + { + Section *s, *symtab; + Elf32_Rel *rel, *rel_end; + Elf32_Sym *sym; + int i, type, reloc_type, sym_index; + +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; + if (s->sh_type != SHT_REL) + continue; + /* no need to handle got relocations */ +@@ -861,8 +862,8 @@ + case R_386_GOTOFF: + case R_386_GOTPC: + case R_386_PLT32: +- if (!s1->got) +- build_got(s1); ++ if (!st->got) ++ build_got(st); + if (type == R_386_GOT32 || type == R_386_PLT32) { + sym_index = ELF32_R_SYM(rel->r_info); + sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; +@@ -871,7 +872,7 @@ + reloc_type = R_386_GLOB_DAT; + else + reloc_type = R_386_JMP_SLOT; +- put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, ++ put_got_entry(st, reloc_type, sym->st_size, sym->st_info, + sym_index); + } + break; +@@ -880,8 +881,8 @@ + case R_ARM_GOTOFF32: + case R_ARM_BASE_PREL: + case R_ARM_PLT32: +- if (!s1->got) +- build_got(s1); ++ if (!st->got) ++ build_got(st); + if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) { + sym_index = ELF32_R_SYM(rel->r_info); + sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; +@@ -890,7 +891,7 @@ + reloc_type = R_ARM_GLOB_DAT; + else + reloc_type = R_ARM_JUMP_SLOT; +- put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, ++ put_got_entry(st, reloc_type, sym->st_size, sym->st_info, + sym_index); + } + break; +@@ -899,8 +900,8 @@ + case R_C60_GOTOFF: + case R_C60_GOTPC: + case R_C60_PLT32: +- if (!s1->got) +- build_got(s1); ++ if (!st->got) ++ build_got(st); + if (type == R_C60_GOT32 || type == R_C60_PLT32) { + sym_index = ELF32_R_SYM(rel->r_info); + sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; +@@ -909,7 +910,7 @@ + reloc_type = R_C60_GLOB_DAT; + else + reloc_type = R_C60_JMP_SLOT; +- put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, ++ put_got_entry(st, reloc_type, sym->st_size, sym->st_info, + sym_index); + } + break; +@@ -923,7 +924,7 @@ + } + } + +-static Section *new_symtab(TCCState *s1, ++static Section *new_symtab(TCCState *st, + const char *symtab_name, int sh_type, int sh_flags, + const char *strtab_name, + const char *hash_name, int hash_sh_flags) +@@ -931,21 +932,21 @@ + Section *symtab, *strtab, *hash; + int *ptr, nb_buckets; + +- symtab = new_section(s1, symtab_name, sh_type, sh_flags); ++ symtab = new_section(st, symtab_name, sh_type, sh_flags); + symtab->sh_entsize = sizeof(Elf32_Sym); +- strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags); +- put_elf_str(strtab, ""); ++ strtab = new_section(st, strtab_name, SHT_STRTAB, sh_flags); ++ put_elf_str(st, strtab, ""); + symtab->link = strtab; +- put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL); ++ put_elf_sym(st, symtab, 0, 0, 0, 0, 0, NULL); + + nb_buckets = 1; + +- hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags); ++ hash = new_section(st, hash_name, SHT_HASH, hash_sh_flags); + hash->sh_entsize = sizeof(int); + symtab->hash = hash; + hash->link = symtab; + +- ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int)); ++ ptr = section_ptr_add(st, hash, (2 + nb_buckets + 1) * sizeof(int)); + ptr[0] = nb_buckets; + ptr[1] = 1; + memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); +@@ -953,15 +954,15 @@ + } + + /* put dynamic tag */ +-static void put_dt(Section *dynamic, int dt, unsigned long val) ++static void put_dt(TCCState *st, Section *dynamic, int dt, unsigned long val) + { + Elf32_Dyn *dyn; +- dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn)); ++ dyn = section_ptr_add(st, dynamic, sizeof(Elf32_Dyn)); + dyn->d_tag = dt; + dyn->d_un.d_val = val; + } + +-static void add_init_array_defines(TCCState *s1, const char *section_name) ++static void add_init_array_defines(TCCState *st, const char *section_name) + { + Section *s; + long end_offset; +@@ -971,7 +972,7 @@ + snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1); + snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1); + +- s = find_section(s1, section_name); ++ s = find_section(st, section_name); + if (!s) { + end_offset = 0; + s = data_section; +@@ -979,22 +980,22 @@ + end_offset = s->data_offset; + } + +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + 0, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + s->sh_num, sym_start); +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + end_offset, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + s->sh_num, sym_end); + } + + /* add tcc runtime libraries */ +-static void tcc_add_runtime(TCCState *s1) ++static void tcc_add_runtime(TCCState *st) + { + char buf[1024]; + +-#ifdef CONFIG_TCC_BCHECK ++#if 0 + if (do_bounds_check) { + unsigned long *ptr; + Section *init_section; +@@ -1002,71 +1003,71 @@ + int sym_index; + + /* XXX: add an object file to do that */ +- ptr = section_ptr_add(bounds_section, sizeof(unsigned long)); ++ ptr = section_ptr_add(st, bounds_section, sizeof(unsigned long)); + *ptr = 0; +- add_elf_sym(symtab_section, 0, 0, ++ add_elf_sym(st, symtab_section, 0, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + bounds_section->sh_num, "__bounds_start"); + /* add bound check code */ +- snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o"); +- tcc_add_file(s1, buf); ++ snprintf(buf, sizeof(buf), "%s/%s", Tcl_GetString(tcc_lib_path), "bcheck.o"); ++ tcc_add_file(st, buf); + #ifdef TCC_TARGET_I386 +- if (s1->output_type != TCC_OUTPUT_MEMORY) { ++ if (st->output_type != TCC_OUTPUT_MEMORY) { + /* add 'call __bound_init()' in .init section */ +- init_section = find_section(s1, ".init"); +- pinit = section_ptr_add(init_section, 5); ++ init_section = find_section(st, ".init"); ++ pinit = section_ptr_add(st, init_section, 5); + pinit[0] = 0xe8; + put32(pinit + 1, -4); + sym_index = find_elf_sym(symtab_section, "__bound_init"); +- put_elf_reloc(symtab_section, init_section, ++ put_elf_reloc(st, symtab_section, init_section, + init_section->data_offset - 4, R_386_PC32, sym_index); + } + #endif + } + #endif + /* add libc */ +- if (!s1->nostdlib) { +- tcc_add_library(s1, "c"); ++ if (!st->nostdlib) { ++ tcc_add_library(st, "c"); + +- snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a"); +- tcc_add_file(s1, buf); ++ snprintf(buf, sizeof(buf), "%s/lib/%s", Tcl_GetString(st->tcc_lib_path), "libtcc1.a"); ++ tcc_add_file(st, buf); + } + /* add crt end if not memory output */ +- if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) { +- tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o"); ++ if (st->output_type != TCC_OUTPUT_MEMORY && !st->nostdlib) { ++ tcc_add_file(st, CONFIG_TCC_CRT_PREFIX "/crtn.o"); + } + } + + /* add various standard linker symbols (must be done after the + sections are filled (for example after allocating common + symbols)) */ +-static void tcc_add_linker_symbols(TCCState *s1) ++static void tcc_add_linker_symbols(TCCState *st) + { + char buf[1024]; + int i; + Section *s; + +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + text_section->data_offset, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + text_section->sh_num, "_etext"); +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + data_section->data_offset, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + data_section->sh_num, "_edata"); +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + bss_section->data_offset, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + bss_section->sh_num, "_end"); + /* horrible new standard ldscript defines */ +- add_init_array_defines(s1, ".preinit_array"); +- add_init_array_defines(s1, ".init_array"); +- add_init_array_defines(s1, ".fini_array"); ++ add_init_array_defines(st, ".preinit_array"); ++ add_init_array_defines(st, ".init_array"); ++ add_init_array_defines(st, ".fini_array"); + + /* add start and stop symbols for sections whose name can be + expressed in C */ +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; + if (s->sh_type == SHT_PROGBITS && + (s->sh_flags & SHF_ALLOC)) { + const char *p; +@@ -1078,17 +1079,17 @@ + ch = *p; + if (!ch) + break; +- if (!isid(ch) && !isnum(ch)) ++ if (!isid(st, ch) && !isnum(st, ch)) + goto next_sec; + p++; + } + snprintf(buf, sizeof(buf), "__start_%s", s->name); +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + 0, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + s->sh_num, buf); + snprintf(buf, sizeof(buf), "__stop_%s", s->name); +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + s->data_offset, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + s->sh_num, buf); +@@ -1108,15 +1109,15 @@ + #endif + #endif + +-static void tcc_output_binary(TCCState *s1, FILE *f, ++static void tcc_output_binary(TCCState *st, FILE *f, + const int *section_order) + { + Section *s; + int i, offset, size; + + offset = 0; +- for(i=1;inb_sections;i++) { +- s = s1->sections[section_order[i]]; ++ for(i=1;inb_sections;i++) { ++ s = st->sections[section_order[i]]; + if (s->sh_type != SHT_NOBITS && + (s->sh_flags & SHF_ALLOC)) { + while (offset < s->sh_offset) { +@@ -1132,7 +1133,7 @@ + + /* output an ELF file */ + /* XXX: suppress unneeded sections */ +-int tcc_output_file(TCCState *s1, const char *filename) ++int tcc_output_file(TCCState *st, const char *filename) + { + Elf32_Ehdr ehdr; + FILE *f; +@@ -1149,11 +1150,11 @@ + int type, file_type; + unsigned long rel_addr, rel_size; + +- file_type = s1->output_type; +- s1->nb_errors = 0; ++ file_type = st->output_type; ++ st->nb_errors = 0; + + if (file_type != TCC_OUTPUT_OBJ) { +- tcc_add_runtime(s1); ++ tcc_add_runtime(st); + } + + phdr = NULL; +@@ -1166,9 +1167,9 @@ + if (file_type != TCC_OUTPUT_OBJ) { + relocate_common_syms(); + +- tcc_add_linker_symbols(s1); ++ tcc_add_linker_symbols(st); + +- if (!s1->static_link) { ++ if (!st->static_link) { + const char *name; + int sym_index, index; + Elf32_Sym *esym, *sym_end; +@@ -1176,30 +1177,30 @@ + if (file_type == TCC_OUTPUT_EXE) { + char *ptr; + /* add interpreter section only if executable */ +- interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC); ++ interp = new_section(st, ".interp", SHT_PROGBITS, SHF_ALLOC); + interp->sh_addralign = 1; +- ptr = section_ptr_add(interp, sizeof(elf_interp)); ++ ptr = section_ptr_add(st, interp, sizeof(elf_interp)); + strcpy(ptr, elf_interp); + } + + /* add dynamic symbol table */ +- s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC, ++ st->dynsym = new_symtab(st, ".dynsym", SHT_DYNSYM, SHF_ALLOC, + ".dynstr", + ".hash", SHF_ALLOC); +- dynstr = s1->dynsym->link; ++ dynstr = st->dynsym->link; + + /* add dynamic section */ +- dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, ++ dynamic = new_section(st, ".dynamic", SHT_DYNAMIC, + SHF_ALLOC | SHF_WRITE); + dynamic->link = dynstr; + dynamic->sh_entsize = sizeof(Elf32_Dyn); + + /* add PLT */ +- s1->plt = new_section(s1, ".plt", SHT_PROGBITS, ++ st->plt = new_section(st, ".plt", SHT_PROGBITS, + SHF_ALLOC | SHF_EXECINSTR); +- s1->plt->sh_entsize = 4; ++ st->plt->sh_entsize = 4; + +- build_got(s1); ++ build_got(st); + + /* scan for undefined symbols and see if they are in the + dynamic symbols. If a symbol STT_FUNC is found, then we +@@ -1213,12 +1214,12 @@ + sym++) { + if (sym->st_shndx == SHN_UNDEF) { + name = symtab_section->link->data + sym->st_name; +- sym_index = find_elf_sym(s1->dynsymtab_section, name); ++ sym_index = find_elf_sym(st->dynsymtab_section, name); + if (sym_index) { +- esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index]; ++ esym = &((Elf32_Sym *)st->dynsymtab_section->data)[sym_index]; + type = ELF32_ST_TYPE(esym->st_info); + if (type == STT_FUNC) { +- put_got_entry(s1, R_JMP_SLOT, esym->st_size, ++ put_got_entry(st, R_JMP_SLOT, esym->st_size, + esym->st_info, + sym - (Elf32_Sym *)symtab_section->data); + } else if (type == STT_OBJECT) { +@@ -1226,10 +1227,10 @@ + offset = bss_section->data_offset; + /* XXX: which alignment ? */ + offset = (offset + 16 - 1) & -16; +- index = put_elf_sym(s1->dynsym, offset, esym->st_size, ++ index = put_elf_sym(st, st->dynsym, offset, esym->st_size, + esym->st_info, 0, + bss_section->sh_num, name); +- put_elf_reloc(s1->dynsym, bss_section, ++ put_elf_reloc(st, st->dynsym, bss_section, + offset, R_COPY, index); + offset += esym->st_size; + bss_section->data_offset = offset; +@@ -1241,45 +1242,45 @@ + if (ELF32_ST_BIND(sym->st_info) == STB_WEAK || + !strcmp(name, "_fp_hw")) { + } else { +- error_noabort("undefined symbol '%s'", name); ++ error_noabort(st, "undefined symbol '%s'", name); + } + } +- } else if (s1->rdynamic && ++ } else if (st->rdynamic && + ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { + /* if -rdynamic option, then export all non + local symbols */ + name = symtab_section->link->data + sym->st_name; +- put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, ++ put_elf_sym(st, st->dynsym, sym->st_value, sym->st_size, + sym->st_info, 0, + sym->st_shndx, name); + } + } + +- if (s1->nb_errors) ++ if (st->nb_errors) + goto fail; + + /* now look at unresolved dynamic symbols and export + corresponding symbol */ +- sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data + +- s1->dynsymtab_section->data_offset); +- for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1; ++ sym_end = (Elf32_Sym *)(st->dynsymtab_section->data + ++ st->dynsymtab_section->data_offset); ++ for(esym = (Elf32_Sym *)st->dynsymtab_section->data + 1; + esym < sym_end; + esym++) { + if (esym->st_shndx == SHN_UNDEF) { +- name = s1->dynsymtab_section->link->data + esym->st_name; ++ name = st->dynsymtab_section->link->data + esym->st_name; + sym_index = find_elf_sym(symtab_section, name); + if (sym_index) { + /* XXX: avoid adding a symbol if already + present because of -rdynamic ? */ + sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; +- put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, ++ put_elf_sym(st, st->dynsym, sym->st_value, sym->st_size, + sym->st_info, 0, + sym->st_shndx, name); + } else { + if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) { + /* weak symbols can stay undefined */ + } else { +- warning("undefined dynamic symbol '%s'", name); ++ warning(st, "undefined dynamic symbol '%s'", name); + } + } + } +@@ -1288,58 +1289,55 @@ + int nb_syms; + /* shared library case : we simply export all the global symbols */ + nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); +- s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); ++ st->symtab_to_dynsym = tcc_mallocz(st, sizeof(int) * nb_syms); + for(sym = (Elf32_Sym *)symtab_section->data + 1; + sym < sym_end; + sym++) { + if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { + name = symtab_section->link->data + sym->st_name; +- index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, ++ index = put_elf_sym(st, st->dynsym, sym->st_value, sym->st_size, + sym->st_info, 0, + sym->st_shndx, name); +- s1->symtab_to_dynsym[sym - ++ st->symtab_to_dynsym[sym - + (Elf32_Sym *)symtab_section->data] = + index; + } + } + } + +- build_got_entries(s1); ++ build_got_entries(st); + + /* add a list of needed dlls */ +- for(i = 0; i < s1->nb_loaded_dlls; i++) { +- DLLReference *dllref = s1->loaded_dlls[i]; ++ for(i = 0; i < st->nb_loaded_dlls; i++) { ++ DLLReference *dllref = st->loaded_dlls[i]; + if (dllref->level == 0) +- put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); ++ put_dt(st, dynamic, DT_NEEDED, put_elf_str(st, dynstr, dllref->name)); + } + /* XXX: currently, since we do not handle PIC code, we + must relocate the readonly segments */ +- if (file_type == TCC_OUTPUT_DLL) { +- if (s1->soname) +- put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); +- put_dt(dynamic, DT_TEXTREL, 0); +- } ++ if (file_type == TCC_OUTPUT_DLL) ++ put_dt(st, dynamic, DT_TEXTREL, 0); + + /* add necessary space for other entries */ + saved_dynamic_data_offset = dynamic->data_offset; + dynamic->data_offset += 8 * 9; + } else { + /* still need to build got entries in case of static link */ +- build_got_entries(s1); ++ build_got_entries(st); + } + } + + memset(&ehdr, 0, sizeof(ehdr)); + + /* we add a section for symbols */ +- strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); +- put_elf_str(strsec, ""); ++ strsec = new_section(st, ".shstrtab", SHT_STRTAB, 0); ++ put_elf_str(st, strsec, ""); + + /* compute number of sections */ +- shnum = s1->nb_sections; ++ shnum = st->nb_sections; + + /* this array is used to reorder sections in the output file */ +- section_order = tcc_malloc(sizeof(int) * shnum); ++ section_order = tcc_malloc(st, sizeof(int) * shnum); + section_order[0] = 0; + sh_order_index = 1; + +@@ -1350,7 +1348,7 @@ + phnum = 0; + break; + case TCC_OUTPUT_EXE: +- if (!s1->static_link) ++ if (!st->static_link) + phnum = 4; + else + phnum = 2; +@@ -1364,37 +1362,37 @@ + section should be output */ + /* NOTE: the strsec section comes last, so its size is also + correct ! */ +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; +- s->sh_name = put_elf_str(strsec, s->name); ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; ++ s->sh_name = put_elf_str(st, strsec, s->name); + /* when generating a DLL, we include relocations but we may + patch them */ + if (file_type == TCC_OUTPUT_DLL && + s->sh_type == SHT_REL && + !(s->sh_flags & SHF_ALLOC)) { +- prepare_dynamic_rel(s1, s); ++ prepare_dynamic_rel(st, s); + } else if (do_debug || + file_type == TCC_OUTPUT_OBJ || + (s->sh_flags & SHF_ALLOC) || +- i == (s1->nb_sections - 1)) { ++ i == (st->nb_sections - 1)) { + /* we output all sections if debug or object file */ + s->sh_size = s->data_offset; + } + } + + /* allocate program segment headers */ +- phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr)); ++ phdr = tcc_mallocz(st, phnum * sizeof(Elf32_Phdr)); + +- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { ++ if (st->output_format == TCC_OUTPUT_FORMAT_ELF) { + file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); + } else { + file_offset = 0; + } + if (phnum > 0) { + /* compute section to program header mapping */ +- if (s1->has_text_addr) { ++ if (st->has_text_addr) { + int a_offset, p_offset; +- addr = s1->text_addr; ++ addr = st->text_addr; + /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset % + ELF_PAGE_SIZE */ + a_offset = addr & (ELF_PAGE_SIZE - 1); +@@ -1432,8 +1430,8 @@ + relocations, progbits, nobits */ + /* XXX: do faster and simpler sorting */ + for(k = 0; k < 5; k++) { +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; + /* compute if section should be included */ + if (j == 0) { + if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != +@@ -1493,7 +1491,7 @@ + ph->p_memsz = addr - ph->p_vaddr; + ph++; + if (j == 0) { +- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { ++ if (st->output_format == TCC_OUTPUT_FORMAT_ELF) { + /* if in the middle of a page, we duplicate the page in + memory so that one copy is RX and the other is RW */ + if ((addr & (ELF_PAGE_SIZE - 1)) != 0) +@@ -1536,29 +1534,29 @@ + ph->p_align = dynamic->sh_addralign; + + /* put GOT dynamic section address */ +- put32(s1->got->data, dynamic->sh_addr); ++ put32(st->got->data, dynamic->sh_addr); + + /* relocate the PLT */ + if (file_type == TCC_OUTPUT_EXE) { + uint8_t *p, *p_end; + +- p = s1->plt->data; +- p_end = p + s1->plt->data_offset; ++ p = st->plt->data; ++ p_end = p + st->plt->data_offset; + if (p < p_end) { + #if defined(TCC_TARGET_I386) +- put32(p + 2, get32(p + 2) + s1->got->sh_addr); +- put32(p + 8, get32(p + 8) + s1->got->sh_addr); ++ put32(p + 2, get32(p + 2) + st->got->sh_addr); ++ put32(p + 8, get32(p + 8) + st->got->sh_addr); + p += 16; + while (p < p_end) { +- put32(p + 2, get32(p + 2) + s1->got->sh_addr); ++ put32(p + 2, get32(p + 2) + st->got->sh_addr); + p += 16; + } + #elif defined(TCC_TARGET_ARM) + int x; +- x=s1->got->sh_addr - s1->plt->sh_addr - 12; ++ x=st->got->sh_addr - st->plt->sh_addr - 12; + p +=16; + while (p < p_end) { +- put32(p + 12, x + get32(p + 12) + s1->plt->data - p); ++ put32(p + 12, x + get32(p + 12) + st->plt->data - p); + p += 16; + } + #elif defined(TCC_TARGET_C67) +@@ -1570,32 +1568,32 @@ + } + + /* relocate symbols in .dynsym */ +- sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset); +- for(sym = (Elf32_Sym *)s1->dynsym->data + 1; ++ sym_end = (Elf32_Sym *)(st->dynsym->data + st->dynsym->data_offset); ++ for(sym = (Elf32_Sym *)st->dynsym->data + 1; + sym < sym_end; + sym++) { + if (sym->st_shndx == SHN_UNDEF) { + /* relocate to the PLT if the symbol corresponds + to a PLT entry */ + if (sym->st_value) +- sym->st_value += s1->plt->sh_addr; ++ sym->st_value += st->plt->sh_addr; + } else if (sym->st_shndx < SHN_LORESERVE) { + /* do symbol relocation */ +- sym->st_value += s1->sections[sym->st_shndx]->sh_addr; ++ sym->st_value += st->sections[sym->st_shndx]->sh_addr; + } + } + + /* put dynamic section entries */ + dynamic->data_offset = saved_dynamic_data_offset; +- put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr); +- put_dt(dynamic, DT_STRTAB, dynstr->sh_addr); +- put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr); +- put_dt(dynamic, DT_STRSZ, dynstr->data_offset); +- put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym)); +- put_dt(dynamic, DT_REL, rel_addr); +- put_dt(dynamic, DT_RELSZ, rel_size); +- put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel)); +- put_dt(dynamic, DT_NULL, 0); ++ put_dt(st, dynamic, DT_HASH, st->dynsym->hash->sh_addr); ++ put_dt(st, dynamic, DT_STRTAB, dynstr->sh_addr); ++ put_dt(st, dynamic, DT_SYMTAB, st->dynsym->sh_addr); ++ put_dt(st, dynamic, DT_STRSZ, dynstr->data_offset); ++ put_dt(st, dynamic, DT_SYMENT, sizeof(Elf32_Sym)); ++ put_dt(st, dynamic, DT_REL, rel_addr); ++ put_dt(st, dynamic, DT_RELSZ, rel_size); ++ put_dt(st, dynamic, DT_RELENT, sizeof(Elf32_Rel)); ++ put_dt(st, dynamic, DT_NULL, 0); + } + + ehdr.e_phentsize = sizeof(Elf32_Phdr); +@@ -1604,8 +1602,8 @@ + } + + /* all other sections come after */ +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; + if (phnum > 0 && (s->sh_flags & SHF_ALLOC)) + continue; + section_order[sh_order_index++] = i; +@@ -1620,9 +1618,9 @@ + /* if building executable or DLL, then relocate each section + except the GOT which is already relocated */ + if (file_type != TCC_OUTPUT_OBJ) { +- relocate_syms(s1, 0); ++ relocate_syms(st, 0); + +- if (s1->nb_errors != 0) { ++ if (st->nb_errors != 0) { + fail: + ret = -1; + goto the_end; +@@ -1630,25 +1628,25 @@ + + /* relocate sections */ + /* XXX: ignore sections with allocated relocations ? */ +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; +- if (s->reloc && s != s1->got) +- relocate_section(s1, s); ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; ++ if (s->reloc && s != st->got) ++ relocate_section(st, s); + } + + /* relocate relocation entries if the relocation tables are + allocated in the executable */ +- for(i = 1; i < s1->nb_sections; i++) { +- s = s1->sections[i]; ++ for(i = 1; i < st->nb_sections; i++) { ++ s = st->sections[i]; + if ((s->sh_flags & SHF_ALLOC) && + s->sh_type == SHT_REL) { +- relocate_rel(s1, s); ++ relocate_rel(st, s); + } + } + + /* get entry point address */ + if (file_type == TCC_OUTPUT_EXE) +- ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start"); ++ ehdr.e_entry = (unsigned long)tcc_get_symbol_err(st, "_start"); + else + ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */ + } +@@ -1660,20 +1658,18 @@ + mode = 0777; + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); + if (fd < 0) { +- error_noabort("could not write '%s'", filename); ++ error_noabort(st, "could not write '%s'", filename); + goto fail; + } + f = fdopen(fd, "wb"); +- if (verbose) +- printf("<- %s\n", filename); + + #ifdef TCC_TARGET_COFF +- if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) { +- tcc_output_coff(s1, f); ++ if (st->output_format == TCC_OUTPUT_FORMAT_COFF) { ++ tcc_output_coff(st, f); + } else + #endif +- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { +- sort_syms(s1, symtab_section); ++ if (st->output_format == TCC_OUTPUT_FORMAT_ELF) { ++ sort_syms(st, symtab_section); + + /* align to 4 */ + file_offset = (file_offset + 3) & -4; +@@ -1721,8 +1717,8 @@ + fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f); + offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); + +- for(i=1;inb_sections;i++) { +- s = s1->sections[section_order[i]]; ++ for(i=1;inb_sections;i++) { ++ s = st->sections[section_order[i]]; + if (s->sh_type != SHT_NOBITS) { + while (offset < s->sh_offset) { + fputc(0, f); +@@ -1740,10 +1736,10 @@ + offset++; + } + +- for(i=0;inb_sections;i++) { ++ for(i=0;inb_sections;i++) { + sh = &shdr; + memset(sh, 0, sizeof(Elf32_Shdr)); +- s = s1->sections[i]; ++ s = st->sections[i]; + if (s) { + sh->sh_name = s->sh_name; + sh->sh_type = s->sh_type; +@@ -1760,26 +1756,26 @@ + fwrite(sh, 1, sizeof(Elf32_Shdr), f); + } + } else { +- tcc_output_binary(s1, f, section_order); ++ tcc_output_binary(st, f, section_order); + } + fclose(f); + + ret = 0; + the_end: +- tcc_free(s1->symtab_to_dynsym); +- tcc_free(section_order); +- tcc_free(phdr); +- tcc_free(s1->got_offsets); ++ ckfree((char *)st->symtab_to_dynsym); ++ ckfree((char *)section_order); ++ ckfree((char *)phdr); ++ ckfree((char *)st->got_offsets); + return ret; + } + +-static void *load_data(int fd, unsigned long file_offset, unsigned long size) ++static void *load_data(TCCState *st, Tcl_Channel fd, unsigned long file_offset, unsigned long size) + { + void *data; + +- data = tcc_malloc(size); +- lseek(fd, file_offset, SEEK_SET); +- read(fd, data, size); ++ data = tcc_malloc(st, size); ++ Tcl_Seek(fd, file_offset, SEEK_SET); ++ Tcl_Read(fd, data, size); + return data; + } + +@@ -1792,8 +1788,8 @@ + + /* load an object file and merge it with current files */ + /* XXX: handle correctly stab (debug) info */ +-static int tcc_load_object_file(TCCState *s1, +- int fd, unsigned long file_offset) ++static int tcc_load_object_file(TCCState *st, ++ Tcl_Channel fd, unsigned long file_offset) + { + Elf32_Ehdr ehdr; + Elf32_Shdr *shdr, *sh; +@@ -1806,7 +1802,7 @@ + Elf32_Rel *rel, *rel_end; + Section *s; + +- if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) ++ if (Tcl_Read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) + goto fail1; + if (ehdr.e_ident[0] != ELFMAG0 || + ehdr.e_ident[1] != ELFMAG1 || +@@ -1820,17 +1816,17 @@ + if (ehdr.e_ident[5] != ELFDATA2LSB || + ehdr.e_machine != EM_TCC_TARGET) { + fail1: +- error_noabort("invalid object file"); ++ error_noabort(st, "invalid object file"); + return -1; + } + /* read sections */ +- shdr = load_data(fd, file_offset + ehdr.e_shoff, ++ shdr = load_data(st, fd, file_offset + ehdr.e_shoff, + sizeof(Elf32_Shdr) * ehdr.e_shnum); +- sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum); ++ sm_table = tcc_mallocz(st, sizeof(SectionMergeInfo) * ehdr.e_shnum); + + /* load section names */ + sh = &shdr[ehdr.e_shstrndx]; +- strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); ++ strsec = load_data(st, fd, file_offset + sh->sh_offset, sh->sh_size); + + /* load symtab and strtab */ + old_to_new_syms = NULL; +@@ -1841,18 +1837,18 @@ + sh = &shdr[i]; + if (sh->sh_type == SHT_SYMTAB) { + if (symtab) { +- error_noabort("object must contain only one symtab"); ++ error_noabort(st, "object must contain only one symtab"); + fail: + ret = -1; + goto the_end; + } + nb_syms = sh->sh_size / sizeof(Elf32_Sym); +- symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); ++ symtab = load_data(st, fd, file_offset + sh->sh_offset, sh->sh_size); + sm_table[i].s = symtab_section; + + /* now load strtab */ + sh = &shdr[sh->sh_link]; +- strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); ++ strtab = load_data(st, fd, file_offset + sh->sh_offset, sh->sh_size); + } + } + +@@ -1875,8 +1871,8 @@ + if (sh->sh_addralign < 1) + sh->sh_addralign = 1; + /* find corresponding section, if any */ +- for(j = 1; j < s1->nb_sections;j++) { +- s = s1->sections[j]; ++ for(j = 1; j < st->nb_sections;j++) { ++ s = st->sections[j]; + if (!strcmp(s->name, sh_name)) { + if (!strncmp(sh_name, ".gnu.linkonce", + sizeof(".gnu.linkonce") - 1)) { +@@ -1892,7 +1888,7 @@ + } + } + /* not found: create new section */ +- s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags); ++ s = new_section(st, sh_name, sh->sh_type, sh->sh_flags); + /* take as much info as possible from the section. sh_link and + sh_info will be updated later */ + s->sh_addralign = sh->sh_addralign; +@@ -1900,7 +1896,7 @@ + sm_table[i].new_section = 1; + found: + if (sh->sh_type != s->sh_type) { +- error_noabort("invalid section type"); ++ error_noabort(st, "invalid section type"); + goto fail; + } + +@@ -1917,9 +1913,9 @@ + size = sh->sh_size; + if (sh->sh_type != SHT_NOBITS) { + unsigned char *ptr; +- lseek(fd, file_offset + sh->sh_offset, SEEK_SET); +- ptr = section_ptr_add(s, size); +- read(fd, ptr, size); ++ Tcl_Seek(fd, file_offset + sh->sh_offset, SEEK_SET); ++ ptr = section_ptr_add(st, s, size); ++ Tcl_Read(fd, ptr, size); + } else { + s->data_offset += size; + } +@@ -1938,13 +1934,13 @@ + if (sh->sh_type == SHT_REL) { + s->sh_info = sm_table[sh->sh_info].s->sh_num; + /* update backward link */ +- s1->sections[s->sh_info]->reloc = s; ++ st->sections[s->sh_info]->reloc = s; + } + } + sm = sm_table; + + /* resolve symbols */ +- old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int)); ++ old_to_new_syms = tcc_mallocz(st, nb_syms * sizeof(int)); + + sym = symtab + 1; + for(i = 1; i < nb_syms; i++, sym++) { +@@ -1973,7 +1969,7 @@ + } + /* add symbol */ + name = strtab + sym->st_name; +- sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size, ++ sym_index = add_elf_sym(st, symtab_section, sym->st_value, sym->st_size, + sym->st_info, sym->st_other, + sym->st_shndx, name); + old_to_new_syms[i] = sym_index; +@@ -2006,7 +2002,7 @@ + /* ignore link_once in rel section. */ + if (!sym_index && !sm->link_once) { + invalid_reloc: +- error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x", ++ error_noabort(st, "Invalid relocation entry [%2d] '%s' @ %.8x", + i, strsec + sh->sh_name, rel->r_offset); + goto fail; + } +@@ -2022,12 +2018,12 @@ + + ret = 0; + the_end: +- tcc_free(symtab); +- tcc_free(strtab); +- tcc_free(old_to_new_syms); +- tcc_free(sm_table); +- tcc_free(strsec); +- tcc_free(shdr); ++ ckfree((char *)symtab); ++ ckfree((char *)strtab); ++ ckfree((char *)old_to_new_syms); ++ ckfree((char *)sm_table); ++ ckfree((char *)strsec); ++ ckfree((char *)shdr); + return ret; + } + +@@ -2049,7 +2045,7 @@ + } + + /* load only the objects which resolve undefined symbols */ +-static int tcc_load_alacarte(TCCState *s1, int fd, int size) ++static int tcc_load_alacarte(TCCState *st, Tcl_Channel fd, int size) + { + int i, bound, nsyms, sym_index, off, ret; + uint8_t *data; +@@ -2057,8 +2053,8 @@ + const uint8_t *ar_index; + Elf32_Sym *sym; + +- data = tcc_malloc(size); +- if (read(fd, data, size) != size) ++ data = tcc_malloc(st, size); ++ if (Tcl_Read(fd, data, size) != size) + goto fail; + nsyms = get_be32(data); + ar_index = data + 4; +@@ -2076,8 +2072,8 @@ + printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx); + #endif + ++bound; +- lseek(fd, off, SEEK_SET); +- if(tcc_load_object_file(s1, fd, off) < 0) { ++ Tcl_Seek(fd, off, SEEK_SET); ++ if(tcc_load_object_file(st, fd, off) < 0) { + fail: + ret = -1; + goto the_end; +@@ -2088,12 +2084,12 @@ + } while(bound); + ret = 0; + the_end: +- tcc_free(data); ++ ckfree((char *)data); + return ret; + } + + /* load a '.a' file */ +-static int tcc_load_archive(TCCState *s1, int fd) ++static int tcc_load_archive(TCCState *st, Tcl_Channel fd) + { + ArchiveHeader hdr; + char ar_size[11]; +@@ -2103,14 +2099,14 @@ + unsigned long file_offset; + + /* skip magic which was already checked */ +- read(fd, magic, sizeof(magic)); ++ Tcl_Read(fd, magic, sizeof(magic)); + + for(;;) { +- len = read(fd, &hdr, sizeof(hdr)); ++ len = Tcl_Read(fd, (char *)&hdr, sizeof(hdr)); + if (len == 0) + break; + if (len != sizeof(hdr)) { +- error_noabort("invalid archive"); ++ error_noabort(st, "invalid archive"); + return -1; + } + memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size)); +@@ -2122,24 +2118,24 @@ + break; + } + ar_name[i + 1] = '\0'; +- // printf("name='%s' size=%d %s\n", ar_name, size, ar_size); +- file_offset = lseek(fd, 0, SEEK_CUR); ++ /* printf("name='%s' size=%d %s\n", ar_name, size, ar_size); */ ++ file_offset = Tcl_Seek(fd, 0, SEEK_CUR); + /* align to even */ + size = (size + 1) & ~1; + if (!strcmp(ar_name, "/")) { + /* coff symbol table : we handle it */ +- if(s1->alacarte_link) +- return tcc_load_alacarte(s1, fd, size); +- } else if (!strcmp(ar_name, "//") || ++ if(st->alacarte_link) ++ return tcc_load_alacarte(st, fd, size); ++ } else if (!strcmp(ar_name, "/*") || + !strcmp(ar_name, "__.SYMDEF") || + !strcmp(ar_name, "__.SYMDEF/") || + !strcmp(ar_name, "ARFILENAMES/")) { + /* skip symbol table or archive names */ + } else { +- if (tcc_load_object_file(s1, fd, file_offset) < 0) ++ if (tcc_load_object_file(st, fd, file_offset) < 0) + return -1; + } +- lseek(fd, file_offset + size, SEEK_SET); ++ Tcl_Seek(fd, file_offset + size, SEEK_SET); + } + return 0; + } +@@ -2147,7 +2143,7 @@ + /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL + is referenced by the user (so it should be added as DT_NEEDED in + the generated ELF file) */ +-static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) ++static int tcc_load_dll(TCCState *st, Tcl_Channel fd, const char *filename, int level) + { + Elf32_Ehdr ehdr; + Elf32_Shdr *shdr, *sh, *sh1; +@@ -2155,20 +2151,20 @@ + Elf32_Sym *sym, *dynsym; + Elf32_Dyn *dt, *dynamic; + unsigned char *dynstr; +- const char *name, *soname; ++ const char *name, *soname, *p; + DLLReference *dllref; + +- read(fd, &ehdr, sizeof(ehdr)); ++ Tcl_Read(fd, (char *)&ehdr, sizeof(ehdr)); + + /* test CPU specific stuff */ + if (ehdr.e_ident[5] != ELFDATA2LSB || + ehdr.e_machine != EM_TCC_TARGET) { +- error_noabort("bad architecture"); ++ error_noabort(st, "bad architecture"); + return -1; + } + + /* read sections */ +- shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum); ++ shdr = load_data(st, fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum); + + /* load dynamic section and dynamic symbols */ + nb_syms = 0; +@@ -2180,13 +2176,13 @@ + switch(sh->sh_type) { + case SHT_DYNAMIC: + nb_dts = sh->sh_size / sizeof(Elf32_Dyn); +- dynamic = load_data(fd, sh->sh_offset, sh->sh_size); ++ dynamic = load_data(st, fd, sh->sh_offset, sh->sh_size); + break; + case SHT_DYNSYM: + nb_syms = sh->sh_size / sizeof(Elf32_Sym); +- dynsym = load_data(fd, sh->sh_offset, sh->sh_size); ++ dynsym = load_data(st, fd, sh->sh_offset, sh->sh_size); + sh1 = &shdr[sh->sh_link]; +- dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); ++ dynstr = load_data(st, fd, sh1->sh_offset, sh1->sh_size); + break; + default: + break; +@@ -2194,7 +2190,10 @@ + } + + /* compute the real library name */ +- soname = tcc_basename(filename); ++ soname = filename; ++ p = strrchr(soname, '/'); ++ if (p) ++ soname = p + 1; + + for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { + if (dt->d_tag == DT_SONAME) { +@@ -2203,8 +2202,8 @@ + } + + /* if the dll is already loaded, do not load it */ +- for(i = 0; i < s1->nb_loaded_dlls; i++) { +- dllref = s1->loaded_dlls[i]; ++ for(i = 0; i < st->nb_loaded_dlls; i++) { ++ dllref = st->loaded_dlls[i]; + if (!strcmp(soname, dllref->name)) { + /* but update level if needed */ + if (level < dllref->level) +@@ -2214,13 +2213,13 @@ + } + } + +- // printf("loading dll '%s'\n", soname); ++ /* printf("loading dll '%s'\n", soname); */ + + /* add the dll and its level */ +- dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname)); ++ dllref = tcc_malloc(st, sizeof(DLLReference) + strlen(soname)); + dllref->level = level; + strcpy(dllref->name, soname); +- dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); ++ dynarray_add(st, (void ***)&st->loaded_dlls, &st->nb_loaded_dlls, dllref); + + /* add dynamic symbols in dynsym_section */ + for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { +@@ -2228,7 +2227,7 @@ + if (sym_bind == STB_LOCAL) + continue; + name = dynstr + sym->st_name; +- add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, ++ add_elf_sym(st, st->dynsymtab_section, sym->st_value, sym->st_size, + sym->st_info, sym->st_other, sym->st_shndx, name); + } + +@@ -2237,13 +2236,13 @@ + switch(dt->d_tag) { + case DT_NEEDED: + name = dynstr + dt->d_un.d_val; +- for(j = 0; j < s1->nb_loaded_dlls; j++) { +- dllref = s1->loaded_dlls[j]; ++ for(j = 0; j < st->nb_loaded_dlls; j++) { ++ dllref = st->loaded_dlls[j]; + if (!strcmp(name, dllref->name)) + goto already_loaded; + } +- if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { +- error_noabort("referenced dll '%s' not found", name); ++ if (tcc_add_dll(st, name, AFF_REFERENCED_DLL) < 0) { ++ error_noabort(st, "referenced dll '%s' not found", name); + ret = -1; + goto the_end; + } +@@ -2253,10 +2252,10 @@ + } + ret = 0; + the_end: +- tcc_free(dynstr); +- tcc_free(dynsym); +- tcc_free(dynamic); +- tcc_free(shdr); ++ ckfree((char *)dynstr); ++ ckfree((char *)dynsym); ++ ckfree((char *)dynamic); ++ ckfree((char *)shdr); + return ret; + } + +@@ -2264,26 +2263,26 @@ + #define LD_TOK_EOF (-1) + + /* return next ld script token */ +-static int ld_next(TCCState *s1, char *name, int name_size) ++static int ld_next(TCCState *st, char *name, int name_size) + { + int c; + char *q; + + redo: +- switch(ch) { ++ switch(fch) { + case ' ': + case '\t': + case '\f': + case '\v': + case '\r': + case '\n': +- inp(); ++ inp(st); + goto redo; + case '/': +- minp(); +- if (ch == '*') { +- file->buf_ptr = parse_comment(file->buf_ptr); +- ch = file->buf_ptr[0]; ++ minp(st); ++ if (fch == '*') { ++ file->buf_ptr = parse_comment(st, file->buf_ptr); ++ fch = file->buf_ptr[0]; + goto redo; + } else { + q = name; +@@ -2291,60 +2290,8 @@ + goto parse_name; + } + break; +- /* case 'a' ... 'z': */ +- case 'a': +- case 'b': +- case 'c': +- case 'd': +- case 'e': +- case 'f': +- case 'g': +- case 'h': +- case 'i': +- case 'j': +- case 'k': +- case 'l': +- case 'm': +- case 'n': +- case 'o': +- case 'p': +- case 'q': +- case 'r': +- case 's': +- case 't': +- case 'u': +- case 'v': +- case 'w': +- case 'x': +- case 'y': +- case 'z': +- /* case 'A' ... 'z': */ +- case 'A': +- case 'B': +- case 'C': +- case 'D': +- case 'E': +- case 'F': +- case 'G': +- case 'H': +- case 'I': +- case 'J': +- case 'K': +- case 'L': +- case 'M': +- case 'N': +- case 'O': +- case 'P': +- case 'Q': +- case 'R': +- case 'S': +- case 'T': +- case 'U': +- case 'V': +- case 'W': +- case 'X': +- case 'Y': +- case 'Z': ++ case 'a' ... 'z': ++ case 'A' ... 'Z': + case '_': + case '\\': + case '.': +@@ -2353,15 +2300,15 @@ + q = name; + parse_name: + for(;;) { +- if (!((ch >= 'a' && ch <= 'z') || +- (ch >= 'A' && ch <= 'Z') || +- (ch >= '0' && ch <= '9') || +- strchr("/.-_+=$:\\,~", ch))) ++ if (!((fch >= 'a' && fch <= 'z') || ++ (fch >= 'A' && fch <= 'Z') || ++ (fch >= '0' && fch <= '9') || ++ strchr("/.-_+=$:\\,~", fch))) + break; + if ((q - name) < name_size - 1) { +- *q++ = ch; ++ *q++ = fch; + } +- minp(); ++ minp(st); + } + *q = '\0'; + c = LD_TOK_NAME; +@@ -2370,8 +2317,8 @@ + c = LD_TOK_EOF; + break; + default: +- c = ch; +- inp(); ++ c = fch; ++ inp(st); + break; + } + #if 0 +@@ -2382,37 +2329,37 @@ + return c; + } + +-static int ld_add_file_list(TCCState *s1, int as_needed) ++static int ld_add_file_list(TCCState *st, int as_needed) + { + char filename[1024]; + int t, ret; + +- t = ld_next(s1, filename, sizeof(filename)); ++ t = ld_next(st, filename, sizeof(filename)); + if (t != '(') +- expect("("); +- t = ld_next(s1, filename, sizeof(filename)); ++ expect(st, "("); ++ t = ld_next(st, filename, sizeof(filename)); + for(;;) { + if (t == LD_TOK_EOF) { +- error_noabort("unexpected end of file"); ++ error_noabort(st, "unexpected end of file"); + return -1; + } else if (t == ')') { + break; + } else if (t != LD_TOK_NAME) { +- error_noabort("filename expected"); ++ error_noabort(st, "filename expected"); + return -1; + } + if (!strcmp(filename, "AS_NEEDED")) { +- ret = ld_add_file_list(s1, 1); ++ ret = ld_add_file_list(st, 1); + if (ret) + return ret; + } else { + /* TODO: Implement AS_NEEDED support. Ignore it for now */ + if (!as_needed) +- tcc_add_file(s1, filename); ++ tcc_add_file(st, filename); + } +- t = ld_next(s1, filename, sizeof(filename)); ++ t = ld_next(st, filename, sizeof(filename)); + if (t == ',') { +- t = ld_next(s1, filename, sizeof(filename)); ++ t = ld_next(st, filename, sizeof(filename)); + } + } + return 0; +@@ -2420,35 +2367,35 @@ + + /* interpret a subset of GNU ldscripts to handle the dummy libc.so + files */ +-static int tcc_load_ldscript(TCCState *s1) ++static int tcc_load_ldscript(TCCState *st) + { + char cmd[64]; + char filename[1024]; + int t, ret; + +- ch = file->buf_ptr[0]; +- ch = handle_eob(); ++ /*fch = file->buf_ptr[0]; */ ++ fch = handle_eob(st); + for(;;) { +- t = ld_next(s1, cmd, sizeof(cmd)); ++ t = ld_next(st, cmd, sizeof(cmd)); + if (t == LD_TOK_EOF) + return 0; + else if (t != LD_TOK_NAME) + return -1; + if (!strcmp(cmd, "INPUT") || + !strcmp(cmd, "GROUP")) { +- ret = ld_add_file_list(s1, 0); ++ ret = ld_add_file_list(st, 0); + if (ret) + return ret; + } else if (!strcmp(cmd, "OUTPUT_FORMAT") || + !strcmp(cmd, "TARGET")) { + /* ignore some commands */ +- t = ld_next(s1, cmd, sizeof(cmd)); ++ t = ld_next(st, cmd, sizeof(cmd)); + if (t != '(') +- expect("("); ++ expect(st, "("); + for(;;) { +- t = ld_next(s1, filename, sizeof(filename)); ++ t = ld_next(st, filename, sizeof(filename)); + if (t == LD_TOK_EOF) { +- error_noabort("unexpected end of file"); ++ error_noabort(st, "unexpected end of file"); + return -1; + } else if (t == ')') { + break; +--- tcc-0.9.23/tccpe.c 2005-06-17 18:09:15.000000000 -0400 ++++ tcltcc-0.4/generic/win32/tccpe.c 2014-05-01 15:36:39.124555968 -0400 +@@ -155,7 +155,7 @@ + typedef struct _IMAGE_BASE_RELOCATION { + DWORD VirtualAddress; + DWORD SizeOfBlock; +-// WORD TypeOffset[1]; ++/* WORD TypeOffset[1]; */ + } IMAGE_BASE_RELOCATION; + + #define IMAGE_SIZEOF_BASE_RELOCATION 8 +@@ -365,13 +365,13 @@ + + /* ------------------------------------------------------------- */ + #define PE_MERGE_DATA +-// #define PE_PRINT_SECTIONS ++/* #define PE_PRINT_SECTIONS */ + + #ifndef MAX_PATH + #define MAX_PATH 260 + #endif + +-void error_noabort(const char *, ...); ++void error_noabort(TCCState *st, const char *, ...); + + ST char pe_type; + +@@ -397,7 +397,7 @@ + return sym_index; + } + +-#ifdef WIN32 ++#if defined(WIN32) && !defined(CONFIG_TCC_STATIC) + ST void **pe_imp; + ST int nb_pe_imp; + +@@ -420,8 +420,8 @@ + if (hm) { + a = GetProcAddress(hm, buffer); + if (a && STT_OBJECT == type) { +- // need to return a pointer to the address for data objects +- dynarray_add(&pe_imp, &nb_pe_imp, a); ++ /* need to return a pointer to the address for data objects */ ++ dynarray_add(s1, &pe_imp, &nb_pe_imp, a); + a = &pe_imp[nb_pe_imp - 1]; + } + } +@@ -445,8 +445,8 @@ + { + int i; + for (i = 0; i < *n; ++i) +- tcc_free((*pp)[i]); +- tcc_free(*pp); ++ ckfree((char *)(*pp)[i]); ++ ckfree((char *)*pp); + *pp = NULL; + *n = 0; + } +@@ -489,16 +489,16 @@ + return (n + (0x1000 - 1)) & ~(0x1000 - 1); + } + +-ST void pe_align_section(Section * s, int a) ++ST void pe_align_section(TCCState *st, Section * s, int a) + { + int i = s->data_offset & (a - 1); + if (i) +- section_ptr_add(s, a - i); ++ section_ptr_add(st, s, a - i); + } + + + /*----------------------------------------------------------------------------*/ +-ST int pe_write_pe(struct pe_info *pe) ++ST int pe_write_pe(TCCState * st, struct pe_info *pe) + { + int i; + FILE *op; +@@ -508,7 +508,7 @@ + + op = fopen(pe->filename, "wb"); + if (NULL == op) { +- error_noabort("could not create file: %s", pe->filename); ++ error_noabort(st, "could not create file: %s", pe->filename); + return 1; + } + +@@ -625,7 +625,7 @@ + } + + /*----------------------------------------------------------------------------*/ +-ST int pe_add_import(struct pe_info *pe, int sym_index, DWORD offset) ++ST int pe_add_import(TCCState *st, struct pe_info *pe, int sym_index, DWORD offset) + { + int i; + int dll_index; +@@ -640,25 +640,25 @@ + p = pe->imp_info[i]; + goto found_dll; + } +- p = tcc_mallocz(sizeof *p); ++ p = tcc_mallocz(st, sizeof *p); + p->dll_index = dll_index; +- dynarray_add((void ***) &pe->imp_info, &pe->imp_count, p); ++ dynarray_add(st, (void ***) &pe->imp_info, &pe->imp_count, p); + + found_dll: + i = dynarray_assoc((void **) p->symbols, p->sym_count, sym_index); + if (-1 != i) + goto found_sym; +- s = tcc_mallocz(sizeof *s); ++ s = tcc_mallocz(st, sizeof *s); + s->sym_index = sym_index; + s->offset = offset; +- dynarray_add((void ***) &p->symbols, &p->sym_count, s); ++ dynarray_add(st, (void ***) &p->symbols, &p->sym_count, s); + + found_sym: + return 1; + } + + /*----------------------------------------------------------------------------*/ +-ST void pe_build_imports(struct pe_info *pe) ++ST void pe_build_imports(TCCState *st, struct pe_info *pe) + { + int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i; + DWORD voffset = pe->thunk->sh_addr - pe->imagebase; +@@ -670,13 +670,13 @@ + if (0 == sym_cnt) + return; + +- pe_align_section(pe->thunk, 16); ++ pe_align_section(st, pe->thunk, 16); + + pe->imp_offs = dll_ptr = pe->thunk->data_offset; + pe->imp_size = (ndlls + 1) * sizeof(struct pe_import_header); + pe->iat_offs = dll_ptr + pe->imp_size; + pe->iat_size = (sym_cnt + ndlls) * sizeof(DWORD); +- section_ptr_add(pe->thunk, pe->imp_size + 2 * pe->iat_size); ++ section_ptr_add(st, pe->thunk, pe->imp_size + 2 * pe->iat_size); + + thk_ptr = pe->iat_offs; + ent_ptr = pe->iat_offs + pe->iat_size; +@@ -689,7 +689,7 @@ + /* put the dll name into the import header */ + if (0 == strncmp(name, "lib", 3)) + name += 3; +- v = put_elf_str(pe->thunk, name); ++ v = put_elf_str(st, pe->thunk, name); + + hdr = (struct pe_import_header *) (pe->thunk->data + dll_ptr); + hdr->first_thunk = thk_ptr + voffset; +@@ -717,18 +717,18 @@ + char buffer[100]; + sprintf(buffer, "IAT.%s", name); + sym_index = +- put_elf_sym(symtab_section, thk_ptr, sizeof(DWORD), ++ put_elf_sym(st, symtab_section, thk_ptr, sizeof(DWORD), + ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), + 0, pe->thunk->sh_num, buffer); + +- put_elf_reloc(symtab_section, text_section, offset, R_386_32, /*R_JMP_SLOT, */ ++ put_elf_reloc(st, symtab_section, text_section, offset, R_386_32, /*R_JMP_SLOT, */ + sym_index); + } + v = pe->thunk->data_offset + voffset; +- section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */ +- put_elf_str(pe->thunk, name); ++ section_ptr_add(st, pe->thunk, sizeof(WORD)); /* hint, not used */ ++ put_elf_str(st, pe->thunk, name); + } else { +- v = 0; // last entry is zero ++ v = 0; /* last entry is zero */ + } + *(DWORD *) (pe->thunk->data + thk_ptr) = + *(DWORD *) (pe->thunk->data + ent_ptr) = v; +@@ -751,7 +751,7 @@ + return strcmp(ca, cb); + } + +-ST void pe_build_exports(struct pe_info *pe) ++ST void pe_build_exports(TCCState *st, struct pe_info *pe) + { + Elf32_Sym *sym; + DWORD func_offset, voffset; +@@ -761,12 +761,12 @@ + voffset = pe->thunk->sh_addr - pe->imagebase; + sym_count = 0, n = 1, sorted = NULL; + +- // for simplicity only functions are exported ++ /* for simplicity only functions are exported */ + for_sym_in_symtab(sym) + { + if ((sym->st_other & 1) + && sym->st_shndx == text_section->sh_num) +- dynarray_add((void***)&sorted, &sym_count, (void*)n); ++ dynarray_add(st, (void***)&sorted, &sym_count, (void*)n); + ++n; + } + +@@ -774,10 +774,10 @@ + return; + + qsort (sorted, sym_count, sizeof sorted[0], sym_cmp); +- pe_align_section(pe->thunk, 16); ++ pe_align_section(st, pe->thunk, 16); + + pe->exp_offs = pe->thunk->data_offset; +- hdr = section_ptr_add(pe->thunk, ++ hdr = section_ptr_add(st, pe->thunk, + sizeof(struct pe_export_header) + + sym_count * (2 * sizeof(DWORD) + sizeof(WORD))); + +@@ -791,7 +791,7 @@ + hdr->AddressOfNames = hdr->AddressOfFunctions + sym_count * sizeof(DWORD); + hdr->AddressOfNameOrdinals = hdr->AddressOfNames + sym_count * sizeof(DWORD); + hdr->Name = pe->thunk->data_offset + voffset; +- put_elf_str(pe->thunk, tcc_basename(pe->filename)); ++ put_elf_str(st, pe->thunk, tcc_basename(pe->filename)); + + for (ord = 0; ord < sym_count; ++ord) + { +@@ -805,15 +805,15 @@ + *pfunc = sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - pe->imagebase; + *pname = pe->thunk->data_offset + voffset; + *pord = ord; +- put_elf_str(pe->thunk, name); ++ put_elf_str(st, pe->thunk, name); + /* printf("export: %s\n", name); */ + } + pe->exp_size = pe->thunk->data_offset - pe->exp_offs; +- tcc_free(sorted); ++ ckfree((char *)sorted); + } + + /* ------------------------------------------------------------- */ +-ST void pe_build_reloc(struct pe_info *pe, int *section_order, ++ST void pe_build_reloc(TCCState *st, struct pe_info *pe, int *section_order, + int section_count) + { + DWORD offset, block_ptr, addr; +@@ -831,11 +831,11 @@ + continue; + if (count == 0) { /* new block */ + block_ptr = pe->reloc->data_offset; +- section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header)); ++ section_ptr_add(st, pe->reloc, sizeof(struct pe_reloc_header)); + offset = addr & 0xFFFFFFFF << 12; + } + if ((addr -= offset) < (1 << 12)) { /* one block spans 4k addresses */ +- WORD *wp = section_ptr_add(pe->reloc, sizeof(WORD)); ++ WORD *wp = section_ptr_add(st, pe->reloc, sizeof(WORD)); + *wp = addr | IMAGE_REL_BASED_HIGHLOW << 12; + ++count; + continue; +@@ -853,7 +853,7 @@ + if (count) { /* store the last block and ready for a new one */ + struct pe_reloc_header *hdr; + if (count & 1) +- section_ptr_add(pe->reloc, 2), ++count; ++ section_ptr_add(st, pe->reloc, 2), ++count; + hdr = (struct pe_reloc_header *) (pe->reloc->data + block_ptr); + hdr->offset = offset - pe->imagebase; + hdr->size = +@@ -866,7 +866,7 @@ + } + + /* ------------------------------------------------------------- */ +-ST int pe_assign_addresses(struct pe_info *pe) ++ST int pe_assign_addresses(TCCState *st, struct pe_info *pe) + { + int i, k, n; + DWORD addr; +@@ -900,10 +900,10 @@ + if (n == sec_data) { + pe->thunk = s; + si_data = si; +- pe_build_imports(pe); +- pe_build_exports(pe); ++ pe_build_imports(st, pe); ++ pe_build_exports(st, pe); + } else if (n == sec_reloc) { +- pe_build_reloc(pe, section_order, k); ++ pe_build_reloc(st, pe, section_order, k); + } + + if (s->data_offset) { +@@ -916,7 +916,7 @@ + si->sh_size = s->data_offset; + ++pe->sec_count; + } +- //printf("Section %08X %04X %s\n", si->sh_addr, si->data_size, s->name); ++ /*printf("Section %08X %04X %s\n", si->sh_addr, si->data_size, s->name); */ + } + section_order[k] = i, ++k; + } +@@ -926,12 +926,12 @@ + } + + /*----------------------------------------------------------------------------*/ +-ST int pe_check_symbols(struct pe_info *pe) ++ST int pe_check_symbols(TCCState *st, struct pe_info *pe) + { + Elf32_Sym *sym; + int ret = 0; + +- pe_align_section(text_section, 8); ++ pe_align_section(st, text_section, 8); + + for_sym_in_symtab(sym) { + if (sym->st_shndx == SHN_UNDEF) { +@@ -941,9 +941,9 @@ + if (sym_index) { + if (type == STT_FUNC) { + unsigned long offset = text_section->data_offset; +- if (pe_add_import(pe, sym_index, offset + 2)) { ++ if (pe_add_import(st, pe, sym_index, offset + 2)) { + /* add the 'jmp IAT[x]' instruction */ +- *(WORD *) section_ptr_add(text_section, 8) = ++ *(WORD *) section_ptr_add(st, text_section, 8) = + 0x25FF; + /* patch the symbol */ + sym->st_shndx = text_section->sh_num; +@@ -951,14 +951,14 @@ + continue; + } + } else if (type == STT_OBJECT) { /* data, ptr to that should be */ +- if (pe_add_import(pe, sym_index, ++ if (pe_add_import(st, pe, sym_index, + (sym - + (Elf32_Sym *) symtab_section->data) | + 0x80000000)) + continue; + } + } +- error_noabort("undefined symbol '%s'", symbol); ++ error_noabort(st, "undefined symbol '%s'", symbol); + ret = 1; + } else + if (pe->s1->rdynamic +@@ -1057,7 +1057,7 @@ + } + #endif + +-static int pe_test_cmd(const char **pp, const char *cmd) ++static int pe_test_cmd(TCCState *st, const char **pp, const char *cmd) + { + const char *p; + char *q, buf[16]; +@@ -1065,9 +1065,9 @@ + + p = *pp; + q = buf; +- while (*p != '\0' && !is_space(*p)) { ++ while (*p != '\0' && !is_space(st, *p)) { + if ((q - buf) < sizeof(buf) - 1) +- *q++ = toup(*p); ++ *q++ = toup(st, *p); + p++; + } + *q = '\0'; +@@ -1077,12 +1077,19 @@ + } + + /* ------------------------------------------------------------- */ +-int pe_load_def_file(TCCState * s1, FILE * fp) ++int pe_load_def_file(TCCState * st, Tcl_Channel fp) + { + DLLReference *dllref; ++ Tcl_Obj * dline; + int f = 0, sym_index; +- char *p, line[120], dllname[40]; +- while (fgets(line, sizeof line, fp)) { ++ char *p, *line, dllname[40]; ++ dline = Tcl_NewObj(); ++ while (1) { ++ Tcl_SetObjLength(dline,0); ++ if (Tcl_GetsObj(fp, dline)==-1) { ++ break; ++ } ++ line = Tcl_GetString(dline); + p = strchr(line, 0); + while (p > line && p[-1] <= ' ') + --p; +@@ -1094,36 +1101,36 @@ + if (*p && ';' != *p) + switch (f) { + case 0: +- if (!pe_test_cmd((const char **)&p, "LIBRARY")) ++ if (!pe_test_cmd(st, (const char **)&p, "LIBRARY")) + return -1; +- while (is_space(*p)) ++ while (is_space(st, *p)) + p++; +- pstrcpy(dllname, sizeof(dllname), p); ++ pstrcpy(st, dllname, sizeof(dllname), p); + ++f; + continue; + + case 1: +- if (!pe_test_cmd((const char **)&p, "EXPORTS")) ++ if (!pe_test_cmd(st, (const char **)&p, "EXPORTS")) + return -1; + ++f; + continue; + + case 2: + dllref = +- tcc_malloc(sizeof(DLLReference) + strlen(dllname)); ++ tcc_malloc(st, sizeof(DLLReference) + strlen(dllname)); + strcpy(dllref->name, dllname); + dllref->level = 0; +- dynarray_add((void ***) &s1->loaded_dlls, +- &s1->nb_loaded_dlls, dllref); ++ dynarray_add(st, (void ***) &st->loaded_dlls, ++ &st->nb_loaded_dlls, dllref); + ++f; + + default: + /* tccpe needs to know from what dll it should import + the sym */ +- sym_index = add_elf_sym(s1->dynsymtab_section, ++ sym_index = add_elf_sym(st, st->dynsymtab_section, + 0, 0, ELF32_ST_INFO(STB_GLOBAL, + STT_FUNC), +- s1->nb_loaded_dlls - 1, ++ st->nb_loaded_dlls - 1, + text_section->sh_num, p); + continue; + } +@@ -1132,7 +1139,7 @@ + } + + /* ------------------------------------------------------------- */ +-void pe_guess_outfile(char *objfilename, int output_type) ++void pe_guess_outfile(TCCState *st, char *objfilename, int output_type) + { + char *ext = strrchr(objfilename, '.'); + if (NULL == ext) +@@ -1146,11 +1153,11 @@ + if (output_type == TCC_OUTPUT_OBJ && strcmp(ext, ".o")) + strcpy(ext, ".o"); + else +- error("no outputfile given"); ++ tcc_error(st, "no outputfile given"); + } + + /* ------------------------------------------------------------- */ +-unsigned long pe_add_runtime(TCCState * s1) ++unsigned long pe_add_runtime(TCCState * st) + { + const char *start_symbol; + unsigned long addr; +@@ -1158,42 +1165,42 @@ + if (find_elf_sym(symtab_section, "WinMain")) + pe_type = PE_GUI; + else +- if (TCC_OUTPUT_DLL == s1->output_type) ++ if (TCC_OUTPUT_DLL == st->output_type) + { + pe_type = PE_DLL; +- // need this for 'tccelf.c:relocate_section()' +- s1->output_type = TCC_OUTPUT_EXE; ++ /* need this for 'tccelf.c:relocate_section()' */ ++ st->output_type = TCC_OUTPUT_EXE; + } + + start_symbol = +- TCC_OUTPUT_MEMORY == s1->output_type ++ TCC_OUTPUT_MEMORY == st->output_type + ? PE_GUI == pe_type ? "_runwinmain" : NULL + : PE_DLL == pe_type ? "_dllstart" + : PE_GUI == pe_type ? "_winstart" : "_start"; + + /* grab the startup code from libtcc1 */ + if (start_symbol) +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + 0, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + SHN_UNDEF, start_symbol); + +- if (0 == s1->nostdlib) { +- tcc_add_library(s1, "tcc1"); +- tcc_add_library(s1, "msvcrt"); ++ if (0 == st->nostdlib) { ++ tcc_add_library(st, "tcc1"); ++ tcc_add_library(st, "msvcrt"); + if (PE_DLL == pe_type || PE_GUI == pe_type) { +- tcc_add_library(s1, "kernel32"); +- tcc_add_library(s1, "user32"); +- tcc_add_library(s1, "gdi32"); ++ tcc_add_library(st, "kernel32"); ++ tcc_add_library(st, "user32"); ++ tcc_add_library(st, "gdi32"); + } + } + + addr = start_symbol ? +- (unsigned long) tcc_get_symbol_err(s1, start_symbol) : 0; ++ (unsigned long) tcc_get_symbol_err(st, start_symbol) : 0; + +- if (s1->output_type == TCC_OUTPUT_MEMORY && addr) { ++ if (st->output_type == TCC_OUTPUT_MEMORY && addr) { + /* for -run GUI's, put '_runwinmain' instead of 'main' */ +- add_elf_sym(symtab_section, ++ add_elf_sym(st, symtab_section, + addr, 0, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, + text_section->sh_num, "main"); +@@ -1214,16 +1221,16 @@ + pe.start_addr = pe_add_runtime(s1); + + relocate_common_syms(); /* assign bss adresses */ +- ret = pe_check_symbols(&pe); ++ ret = pe_check_symbols(s1, &pe); + if (0 == ret) { +- pe_assign_addresses(&pe); ++ pe_assign_addresses(s1, &pe); + relocate_syms(s1, 0); + for (i = 1; i < s1->nb_sections; ++i) { + Section *s = s1->sections[i]; + if (s->reloc) + relocate_section(s1, s); + } +- ret = pe_write_pe(&pe); ++ ret = pe_write_pe(s1, &pe); + } + #ifdef PE_PRINT_SECTIONS + { +--- tcc-0.9.24/tcctok.h 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/generic/tcctok.h 2007-11-07 10:04:32.000000000 -0500 +@@ -130,6 +130,7 @@ + DEF(TOK_memcpy, "memcpy") + DEF(TOK_memset, "memset") + #endif ++ DEF(TOK_alloca, "_alloca_tcc") + DEF(TOK___divdi3, "__divdi3") + DEF(TOK___moddi3, "__moddi3") + DEF(TOK___udivdi3, "__udivdi3") +@@ -208,15 +209,14 @@ + DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16") + DEF(TOK___bound_local_new, "__bound_local_new") + DEF(TOK___bound_local_delete, "__bound_local_delete") +- DEF(TOK_malloc, "malloc") +- DEF(TOK_free, "free") +- DEF(TOK_realloc, "realloc") ++ DEF(TOK_malloc, "ckalloc") ++ DEF(TOK_free, "ckfree") ++ DEF(TOK_realloc, "ckrealloc") + DEF(TOK_memalign, "memalign") + DEF(TOK_calloc, "calloc") + DEF(TOK_memmove, "memmove") + DEF(TOK_strlen, "strlen") + DEF(TOK_strcpy, "strcpy") +- DEF(TOK__alloca, "_alloca") + #endif + + /* Tiny Assembler */ +@@ -444,7 +444,7 @@ + #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) + #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) + #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) +-#include "i386-asm.h" ++#include "i386/i386-asm.h" + + #define ALT(x) + #define DEF_ASM_OP0(name, opcode) +@@ -452,6 +452,6 @@ + #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name) + #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name) + #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name) +-#include "i386-asm.h" ++#include "i386/i386-asm.h" + + #endif +--- tcc-0.9.24/VERSION 2008-03-31 03:24:00.000000000 -0400 ++++ tcltcc-0.4/demo/expat/VERSION 2007-11-07 10:04:16.000000000 -0500 +@@ -1 +1 @@ +-0.9.24 +\ No newline at end of file ++expat-2.0.1 ADDED configure.ac Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -0,0 +1,44 @@ +dnl Define ourselves +AC_INIT(tcc4tcl, @@VERS@@) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_MAKE_SET +AC_PROG_INSTALL +AC_GNU_SOURCE + +dnl Determine system information +DC_CHK_OS_INFO + +dnl Determine if a shared or static build is requested +target=shared +AC_ARG_ENABLE([static], AS_HELP_STRING([--enable-static], [build static library instead of shared library]), [ + target=static +], [ + target=shared +]) + +if test "${target}" = "shared"; then + dnl Determine how to make shared objects + DC_GET_SHOBJFLAGS + + TARGETS="tcltcc-shared.${SHOBJEXT}" +else + TARGETS="tcltcc-static.a" +fi +AC_SUBST(TARGETS) + +dnl Find out if we have the functions needed to open shared objects +AC_SEARCH_LIBS(dlopen, dl,, [ + AC_SEARCH_LIBS(shl_load, dld dl) +]) +AC_CHECK_FUNCS(dlopen shl_load) + +dnl Look for appropriate headers +AC_CHECK_HEADERS(unistd.h stdlib.h string.h strings.h dlfcn.h dl.h) + +dnl Perform Tcl Extension required stuff +TCLEXT_INIT + +dnl Produce output +AC_OUTPUT(Makefile pkgIndex.tcl) ADDED pkgIndex.tcl.in Index: pkgIndex.tcl.in ================================================================== --- pkgIndex.tcl.in +++ pkgIndex.tcl.in ADDED tcc.tcl Index: tcc.tcl ================================================================== --- tcc.tcl +++ tcc.tcl @@ -0,0 +1,378 @@ +# tcc.tcl - library routines for the tcc wrapper (Mark Janssen) + +namespace eval tcc { + variable dir + variable libs + variable includes + variable count + variable command_count + variable commands + + set dir [file dirname [info script]] + if {[info command ::tcc] == ""} { + catch { load {} tcc } + } + if {[info command ::tcc] == ""} { + switch -exact -- $::tcl_platform(platform) { + windows { load $dir/tcc04.dll tcc } + unix { load $dir/libtcc0.4.so tcc } + default {error "unsupport platform"} + } + } + set libs $dir/lib + set includes $dir/include + set count 0 + set command_count 0 + array set commands {} + proc new {} { + variable dir + variable count + set handle tcc_[incr count] + tcc $dir $handle + return tcc_$count + } + proc tclcommand {handle name ccode} { + variable commands + variable command_count + set cname _tcc_tcl_command_[incr command_count] + set code {#include "tcl.h"} + append code "\n int $cname" + append code "(ClientData cdata,Tcl_Interp *interp,int objc,Tcl_Obj* CONST objv[]){" + append code "\n$ccode" + append code "}" + $handle compile $code + set commands($handle,$name) $cname + return + } + proc compile {handle} { + variable commands + foreach cmd [array names commands $handle*] { + puts $cmd + puts $commands($cmd) + set cname $commands($cmd) + set tclcommand [join [lrange [split $cmd ,] 1 end] {}] + set handle [lindex [split $cmd ,] 0] + $handle command $tclcommand $cname + } + return + } +} +proc tcc::to_dll {code dll {libs {}}} { + tcc $::tcc::dir dll tcc_1 + tcc_1 add_library tcl8.5 + tcc_1 add_library_path . + foreach lib $libs {tcc_1 add_library $lib} + if {$::tcl_platform(platform) eq "windows"} { + tcc_1 define DLL_EXPORT {__declspec(dllexport)} + set f [open $::tcc::dir/c/dllcrt1.c] + tcc_1 compile [read $f] + close $f + set f [open $::tcc::dir/c/dllmain.c] + tcc_1 compile [read $f] + close $f + } else { + tcc_1 define DLL_EXPORT "" + } + tcc_1 compile $code + tcc_1 output_file $dll + rename tcc_1 {} +} +proc ::tcc::Log {args} { + # puts $args +} +proc ::tcc::reset {} { + variable tcc + set tcc(code) "" + set tcc(cfiles) [list] + set tcc(tk) 0 +} +# Custom helpers +proc ::tcc::checkname {n} {expr {[regexp {^[a-zA-Z0-9_]+$} $n] > 0}} +proc ::tcc::cleanname {n} {regsub -all {[^a-zA-Z0-9_]+} $n _} + +proc ::tcc::ccode {code} { + variable tcc + Log "INJECTING CCODE" + append tcc(code) $code \n +} +proc ::tcc::cc {code} { + variable tcc + if {![info exists tcc(cc)]} { + set tcc(cc) tcc1 + tcc $tcc::dir $tcc(cc) + $tcc(cc) add_library tcl8.5 + $tcc(cc) add_include_path [file join $::tcc::dir include] + } + Log code:$code + $tcc(cc) compile $code +} +#----------------------------------------------------------- New DLL API +proc ::tcc::dll {{name ""}} { + variable count + if {$name eq ""} {set name dll[incr count]} + namespace eval ::tcc::dll::$name { + variable code "#include \n" ;# always needed + variable cmds {} + } + proc ::$name {cmd args} "::tcc::dll::\$cmd $name \$args" + return $name +} +namespace eval ::tcc::dll {} +proc ::tcc::dll::ccode {name argl} { + append ${name}::code \n [lindex $argl 0] + return +} +proc ::tcc::dll::cproc {name argl} { + foreach {pname pargs rtype body} $argl break + set code [::tcc::wrapCmd $pname $pargs $rtype cx_$pname $body] + lappend ${name}::cmds $pname cx_$pname + append ${name}::code \n $code + return +} +proc ::tcc::dll::write {name argl} { + set (-dir) . + set (-code) "" ;# possible extra code to go into the _Init function + set (-libs) "" + set (-name) [string tolower $name] + array set "" $argl + append ${name}::code \n \ + [::tcc::wrapExport $(-name) [set ${name}::cmds] $(-code)] + set outfile $(-dir)/$(-name)[info sharedlibextension] + ::tcc::to_dll [set ${name}::code] $outfile $(-libs) +} +#--------------------------------------------------------------------- +proc ::tcc::wrap {name adefs rtype {body "#"}} { + set cname c_$name + set wname tcl_$name + array set types {} + set names {} + set cargs {} + set cnames {} + # if first arg is "Tcl_Interp*", pass it without counting it as a cmd arg + if {[lindex $adefs 0] eq "Tcl_Interp*"} { + lappend cnames ip + lappend cargs [lrange $adefs 0 1] + set adefs [lrange $adefs 2 end] + } + foreach {t n} $adefs { + set types($n) $t + lappend names $n + lappend cnames _$n + lappend cargs "$t $n" + } + switch -- $rtype { + ok { set rtype2 "int" } + string - dstring - vstring { set rtype2 "char*" } + default { set rtype2 $rtype } + } + set code "" + append code "\n#include " "\n" + if {[info exists tcc(tk)] && $tcc(tk)} { + append code "\#include " "\n" + } + if {$body ne "#"} { + append code "static $rtype2" "\n" + append code "${cname}([join $cargs {, }]) \{\n" + append code $body + append code "\}" "\n" + } else { + append code "#define $cname $name" "\n" + } + # Supported input types + # Tcl_Interp* + # int + # long + # float + # double + # char* + # Tcl_Obj* + # void* + foreach x $names { + set t $types($x) + switch -- $t { + int - long - float - double - char* - Tcl_Obj* { + append cbody " $types($x) _$x;" "\n" + } + default {append cbody " void *_$x;" "\n"} + } + } + if {$rtype ne "void"} { append cbody " $rtype2 rv;" "\n" } + append cbody " if (objc != [expr {[llength $names] + 1}]) {" "\n" + append cbody " Tcl_WrongNumArgs(ip, 1, objv, \"[join $names { }]\");\n" + append cbody " return TCL_ERROR;" "\n" + append cbody " }" "\n" + set n 0 + foreach x $names { + incr n + switch -- $types($x) { + int { + append cbody " if (Tcl_GetIntFromObj(ip, objv\[$n], &_$x) != TCL_OK)" + append cbody " return TCL_ERROR;" "\n" + } + long { + append cbody " if (Tcl_GetLongFromObj(ip, objv\[$n], &_$x) != TCL_OK)" + append cbody " return TCL_ERROR;" "\n" + } + float { + append cbody " {" "\n" + append cbody " double t;" "\n" + append cbody " if (Tcl_GetDoubleFromObj(ip, objv\[$n], &t) != TCL_OK)" + append cbody " return TCL_ERROR;" "\n" + append cbody " _$x = (float) t;" "\n" + append cbody " }" "\n" + } + double { + append cbody " if (Tcl_GetDoubleFromObj(ip, objv\[$n], &_$x) != TCL_OK)" + append cbody " return TCL_ERROR;" "\n" + } + char* { + append cbody " _$x = Tcl_GetString(objv\[$n]);" "\n" + } + default { + append cbody " _$x = objv\[$n];" "\n" + } + } + } + append cbody "\n " + if {$rtype != "void"} {append cbody "rv = "} + append cbody "${cname}([join $cnames {, }]);" "\n" + # Return types supported by critcl + # void + # ok + # int + # long + # float + # double + # char* (TCL_STATIC char*) + # string (TCL_DYNAMIC char*) + # dstring (TCL_DYNAMIC char*) + # vstring (TCL_VOLATILE char*) + # default (Tcl_Obj*) + # Our extensions + # wide + switch -- $rtype { + void { } + ok { append cbody " return rv;" "\n" } + int { append cbody " Tcl_SetIntObj(Tcl_GetObjResult(ip), rv);" "\n" } + long { append cbody " Tcl_SetLongObj(Tcl_GetObjResult(ip), rv);" "\n" } + float - + double { append cbody " Tcl_SetDoubleObj(Tcl_GetObjResult(ip), rv);" "\n" } + char* { append cbody " Tcl_SetResult(ip, rv, TCL_STATIC);" "\n" } + string - + dstring { append cbody " Tcl_SetResult(ip, rv, TCL_DYNAMIC);" "\n" } + vstring { append cbody " Tcl_SetResult(ip, rv, TCL_VOLATILE);" "\n" } + default { append cbody " Tcl_SetObjResult(ip, rv); Tcl_DecrRefCount(rv);" "\n" } + } + if {$rtype != "ok"} {append cbody " return TCL_OK;" \n} + + #puts ----code:\n$code + #puts ----cbody:\n$cbody + list $code $cbody +} +proc ::tcc::wrapCmd {tclname argl rtype cname body} { + foreach {code cbody} [wrap $tclname $argl $rtype $body] break + append code "\nstatic int $cname" + append code {(ClientData cdata,Tcl_Interp *ip, + int objc,Tcl_Obj* CONST objv[])} " \{" + append code \n$cbody \n\}\n +} +proc ::tcc::wrapExport {name cmds {body ""}} { + set code "DLL_EXPORT int [string totitle $name]_Init(Tcl_Interp *interp)" + append code " \{\n" + foreach {tclname cname} $cmds { + append code \ + "Tcl_CreateObjCommand(interp,\"$tclname\",$cname,NULL,NULL);\n" + } + append code $body + append code "\nreturn TCL_OK;\n\}" +} +#--------------------------------------------------------------------- +proc ::tcc::cproc {name adefs rtype {body "#"}} { + foreach {code cbody} [wrap $name $adefs $rtype $body] break + ccode $code + set ns [namespace current] + uplevel 1 [list ${ns}::ccommand $name {dummy ip objc objv} $cbody] +} +#--------------------------------------------------------------------- +proc ::tcc::cdata {name data} { + # Extract bytes from data + binary scan $data c* bytes + set inittext "\n" + set line "" + set n 0 + set l 0 + foreach c $bytes { + if {$n>0} {append inittext ","} + if {$l>20} { + append inittext "\n" + set l 0 + } + if {$l==0} {append inittext " "} + append inittext [format "0x%02X" [expr {$c & 0xff}]] + incr n + incr l + } + append inittext "\n" + set count [llength $bytes] + set cbody "" + append cbody "static unsigned char script\[$count\] = \{" "\n" + append cbody $inittext + append cbody "\};" "\n" + append cbody "Tcl_SetByteArrayObj(Tcl_GetObjResult(ip), (unsigned char*) script, $count);\n" + append cbody "return TCL_OK;" "\n" + set ns [namespace current] + uplevel 1 [list ${ns}::ccommand $name {dummy ip objc objv} $cbody] + return $name +} +#------------------------------------------------------------------- +proc ::tcc::ccommand {procname anames args} { + variable tcc + # Fully qualified proc name + if {[string match "::*" $procname]} { + # procname is already absolute + } else { + set nsfrom [uplevel 1 {namespace current}] + if {$nsfrom eq "::"} {set nsfrom ""} + set procname "${nsfrom}::${procname}" + } + set v(clientdata) clientdata + set v(interp) interp + set v(objc) objc + set v(objv) objv + set id 0 + foreach defname {clientdata interp objc objv} { + if {[llength $anames]>$id} { + set vname [lindex $anames $id] + if {![checkname $vname]} { + error "invalid variable name \"$vname\"" + } + } else {set vname $defname} + set v($defname) $vname + incr id + } + set cname Cmd_N${id}_[cleanname $procname] + set code "" + if {[info exists tcc(tk)] && $tcc(tk)} { + append code "\#include " "\n" + } + if {[info exists tcc(code)] && [string length $tcc(code)]>0} { + append code $tcc(code) + append code "\n" + } + append code "int $cname (ClientData $v(clientdata),Tcl_Interp *$v(interp)," + append code "int $v(objc),Tcl_Obj *CONST $v(objv)\[\]) {" "\n" + append code [lindex $args end] "\n" + append code "}" "\n" + set ns [namespace current] + uplevel 1 [list ${ns}::cc $code] + Log "CREATING TCL COMMAND $procname / $cname" + uplevel 1 [list $tcc(cc) command $procname $cname] + unset tcc(cc) ;# can't be used for compiling anymore +} +proc ::tcc::tk {args} { + variable tcc + set tcc(tk) 1 +} +::tcc::reset +namespace eval tcc {namespace export cproc ccode cdata} + ADDED tcltcc.c Index: tcltcc.c ================================================================== --- tcltcc.c +++ tcltcc.c @@ -0,0 +1,253 @@ +/* + * TclTCC - Tcl binding to Tiny C Compiler + * + * Copyright (c) 2007 Mark Janssen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +static void TccErrorFunc(Tcl_Interp * interp, char * msg) { + Tcl_AppendResult(interp, msg, "\n", NULL); +} + + +static void TccCCommandDeleteProc (ClientData cdata) { + TCCState * s ; + s = (TCCState *)cdata; + Tcl_DecrRefCount(s->tcc_lib_path); + /* We can delete the compiler if the output was not to memory */ + if (s->output_type != TCC_OUTPUT_MEMORY) { + tcc_delete(s); + } +} + +static int TccHandleCmd ( ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]){ + unsigned long val; + int index; + int res; + TCCState * s = (TCCState *)cdata ; + Tcl_Obj * sym_addr; + + static CONST char *options[] = { + "add_include_path", "add_file", "add_library", + "add_library_path", "add_symbol", "command", "compile", + "define", "get_symbol", "output_file", "undefine", (char *) NULL + }; + enum options { + TCLTCC_ADD_INCLUDE, TCLTCC_ADD_FILE, TCLTCC_ADD_LIBRARY, + TCLTCC_ADD_LIBRARY_PATH, TCLTCC_ADD_SYMBOL, TCLTCC_COMMAND, TCLTCC_COMPILE, + TCLTCC_DEFINE, TCLTCC_GET_SYMBOL, TCLTCC_OUTPUT_FILE, TCLTCC_UNDEFINE + }; + + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "subcommand arg ?arg ...?"); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch (index) { + case TCLTCC_ADD_INCLUDE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "path"); + return TCL_ERROR; + } else { + tcc_add_include_path(s, Tcl_GetString(objv[2])); + return TCL_OK; + } + case TCLTCC_ADD_FILE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "filename"); + return TCL_ERROR; + } else { + if(tcc_add_file(s, Tcl_GetString(objv[2]))!=0) { + return TCL_ERROR; + } else { + return TCL_OK; + } + } + case TCLTCC_ADD_LIBRARY: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "lib"); + return TCL_ERROR; + } else { + tcc_add_library(s, Tcl_GetString(objv[2])); + return TCL_OK; + } + case TCLTCC_ADD_LIBRARY_PATH: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "path"); + return TCL_ERROR; + } else { + tcc_add_library_path(s, Tcl_GetString(objv[2])); + return TCL_OK; + } + case TCLTCC_ADD_SYMBOL: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "symbol value"); + return TCL_ERROR; + } + Tcl_GetLongFromObj(interp,objv[3], &val); + tcc_add_symbol(s,Tcl_GetString(objv[2]),val); + return TCL_OK; + case TCLTCC_COMMAND: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "tclname cname"); + return TCL_ERROR; + } + if (!s->relocated) { + if(tcc_relocate(s)!=0) { + Tcl_AppendResult(interp, "relocating failed", NULL); + return TCL_ERROR; + } else { + s->relocated=1; + } + } + if (tcc_get_symbol(s,&val,Tcl_GetString(objv[3]))!=0) { + Tcl_AppendResult(interp, "symbol '", Tcl_GetString(objv[3]),"' not found", NULL); + return TCL_ERROR; + } + + /*printf("symbol: %x\n",val); */ + Tcl_CreateObjCommand(interp,Tcl_GetString(objv[2]),(void *)val,NULL,NULL); + return TCL_OK; + case TCLTCC_COMPILE: + if(s->relocated == 1) { + Tcl_AppendResult(interp, "code already relocated, cannot compile more",NULL); + return TCL_ERROR; + } + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "ccode"); + return TCL_ERROR; + } else { + + int i; + Tcl_GetString(objv[2]); + i = tcc_compile_string(s,Tcl_GetString(objv[2])); + if (i!=0) { + Tcl_AppendResult(interp,"compilation failed",NULL); + return TCL_ERROR; + } else { + return TCL_OK; + } + } + case TCLTCC_DEFINE: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "symbol value"); + return TCL_ERROR; + } + tcc_define_symbol(s,Tcl_GetString(objv[2]),Tcl_GetString(objv[3])); + return TCL_OK; + case TCLTCC_GET_SYMBOL: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "symbol"); + return TCL_ERROR; + } + if (!s->relocated) { + if(tcc_relocate(s)!=0) { + Tcl_AppendResult(interp, "relocating failed", NULL); + return TCL_ERROR; + } else { + s->relocated=1; + } + } + if(tcc_get_symbol(s,&val,Tcl_GetString(objv[2]))!=0) { + Tcl_AppendResult(interp, "symbol '", Tcl_GetString(objv[2]),"' not found", NULL); + return TCL_ERROR; + } + sym_addr = Tcl_NewLongObj(val); + Tcl_SetObjResult(interp, sym_addr); + return TCL_OK; + case TCLTCC_OUTPUT_FILE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "filename"); + return TCL_ERROR; + } + if (s->relocated) { + Tcl_AppendResult(interp, "code already relocated, cannot output to file", NULL); + return TCL_ERROR; + } + if (s->output_type == TCC_OUTPUT_MEMORY) { + Tcl_AppendResult(interp, "output_type memory not valid for output to file", NULL); + return TCL_ERROR; + } +#ifdef WIN32 + res = tcc_output_pe(s,Tcl_GetString(objv[2])); +#else + res = tcc_output_file(s,Tcl_GetString(objv[2])); +#endif + + if (res!=0) { + Tcl_AppendResult(interp, "output to file failed", NULL); + return TCL_ERROR; + } else { + return TCL_OK; + } + case TCLTCC_UNDEFINE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "symbol"); + return TCL_ERROR; + } + tcc_undefine_symbol(s,Tcl_GetString(objv[2])); + return TCL_OK; + default: + Tcl_Panic("internal error during option lookup"); + } + return TCL_OK; +} + +static int TccCreateCmd( ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]){ + TCCState * s; + static CONST char *types[] = { + "memory", "exe", "dll", "obj", "preprocess", (char *) NULL + }; + int index; + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 1, objv, "tcc_libary_path ?output_type? handle"); + return TCL_ERROR; + } + if (objc == 3) { + index = TCC_OUTPUT_MEMORY; + } else { + if (Tcl_GetIndexFromObj(interp, objv[2], types, "type", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + } + s = tcc_new(objv[1]); + tcc_set_error_func(s, interp, (void *)&TccErrorFunc); + s->relocated = 0; + /*printf("type: %d\n", index); */ + tcc_set_output_type(s,index); + Tcl_CreateObjCommand(interp,Tcl_GetString(objv[objc-1]),TccHandleCmd,s,TccCCommandDeleteProc); + + return TCL_OK; +} + +DLL_EXPORT int Tcc_Init(Tcl_Interp *interp) +{ + if (Tcl_InitStubs(interp, "8.4" , 0) == 0L) { + return TCL_ERROR; + } + Tcl_CreateObjCommand(interp,PACKAGE_NAME,TccCreateCmd,NULL,NULL); + Tcl_PkgProvide(interp,PACKAGE_NAME,PACKAGE_VERSION); + return TCL_OK; +} + + +