1 /*
2  * scheme.h - Scheme system header
3  *
4  *   Copyright (c) 2008  Higepon(Taro Minowa)  <higepon@users.sourceforge.jp>
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *   1. Redistributions of source code must retain the above copyright
11  *      notice, this list of conditions and the following disclaimer.
12  *
13  *   2. Redistributions in binary form must reproduce the above copyright
14  *      notice, this list of conditions and the following disclaimer in the
15  *      documentation and/or other materials provided with the distribution.
16  *
17  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23  *   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  *   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  $Id$
30  */
31 
32 #ifndef SCHEME_SCHEME_H_
33 #define SCHEME_SCHEME_H_
34 
35 #ifdef HAVE_CONFIG_H
36 #    include "config.h"
37 #else
38 #  ifdef MONA
39 #define HAVE_OPENSSL 1
40 //#    include "config_mona.h"
41 #  else
42 #    error "config.h not found"
43 #  endif
44 #endif
45 
46 #ifdef MONA
47 #include <monapi.h>
48 #endif
49 
50 #ifdef _WIN32
51 #else
52 #include <unistd.h>
53 #endif
54 #include <errno.h>
55 #include <stdio.h>
56 
57 #ifdef _WIN32
58     typedef unsigned char uint8_t;
59     typedef unsigned short uint16_t;
60     typedef unsigned int uint32_t;
61     typedef unsigned __int64 uint64_t;
62     typedef signed char int8_t;
63     typedef short int16_t;
64     typedef int int32_t;
65     typedef __int64 int64_t;
66 #else
67 #include <inttypes.h>
68 #endif
69 #include <stdlib.h>
70 #include <limits.h>
71 #include <string.h>
72 #ifdef _MSC_VER
73 #pragma warning(push)
74 #pragma warning(disable : 4146) // convert from signed to unsigned (this may be not necessary if gmp is latest version)
75 #endif
76 #ifndef MONA
77 #include <cstdio>
78 #endif
79 #ifdef MONA
80 extern "C" {
81 #include <gmp.h>
82 };
83 #else
84 #include <gmp.h>
85 #endif
86 #ifdef _MSC_VER
87 #pragma warning(pop)
88 #endif
89 #include <map>
90 #include <vector>
91 #include <set>
92 #ifdef USE_BOEHM_GC
93 #  define EXTEND_GC : public gc
94    // Boehm GC 7.1 lacks this prototype.
95    // http://article.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/2581/match=gc_dlopen
96    extern "C" {
97        void* GC_dlopen(const char* path, int mode);
98    }
99 #  include <gc.h>
100 #  include <gc_cpp.h>
101 #  include <gc_allocator.h>
102    template <class T1, class T2>
103    class gc_map : public std::map<T1, T2, std::less<T1>, gc_allocator<std::pair<const T1, T2> > >, public gc { };
104    template <class T1>
105    class gc_vector : public std::vector<T1, gc_allocator<T1> >, public gc { };
106 #else
107 #define EXTEND_GC
108 template <class T1, class T2>
109 class gc_map : public std::map<T1, T2> {};
110 
111 template <class T1>
112 class gc_vector : public std::vector<T1> {};
113 #endif
114 
115 #define LOG1(fmt, a)       fprintf(stderr, "%s", format(NULL, UC(fmt), Pair::list1(a)).toString()->data().ascii_c_str());fflush(stderr);
116 #define LOG2(fmt, a, b)    fprintf(stderr, "%s", format(NULL, UC(fmt), L2(a, b)).toString()->data().ascii_c_str());fflush(stderr);
117 #define LOG3(fmt, a, b, c) fprintf(stderr, "%s", format(NULL, UC(fmt), L3(a, b, c)).toString()->data().ascii_c_str());fflush(stderr);
118 
119 #define VM_LOG1(fmt, a)       fprintf(stderr, "%s", format(this, UC(fmt), L1(a)).toString()->data().ascii_c_str());fflush(stderr);
120 #define VM_LOG2(fmt, a, b)    fprintf(stderr, "%s", format(this, UC(fmt), L2(a, b)).toString()->data().ascii_c_str());fflush(stderr);
121 #define VM_LOG3(fmt, a, b, c) fprintf(stderr, "%s", format(this, UC(fmt), L3(a, b, c)).toString()->data().ascii_c_str());fflush(stderr);
122 
123 
124 #ifdef DEBUG_VERSION
125 #define MOSH_ASSERT(condition) { if (!(condition)) { fprintf(stderr, "ASSERT failure %s:%d: %s\n", __FILE__, __LINE__, #condition); ::exit(-1);}}
126 #define MOSH_FATAL(condition) { fprintf(stderr, "FATAL  %s:%d: %s\n", __FILE__, __LINE__, #condition); ::exit(-1);}
127 #else
128 #define MOSH_ASSERT(condition) /* */
129 #define MOSH_FATAL(condition) /* */
130 #endif
131 
132 #define INIT_TIME_TRACE() struct timeval tv1, tv2
133 #define START_TIME_TRACE() gettimeofday(&tv1, NULL)
134 #define END_TIME_TRACE(label) gettimeofday(&tv2, NULL);printf("%s %ld usec\n", #label, (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec))
135 
136 
137 enum {
138     MOSH_SUCCESS,
139     MOSH_FAILURE,
140     forbidden_comma
141 };
142 
143 //#define UC(a) (reinterpret_cast<const ucs4char*>(L##""a))
144 
145 typedef int32_t ucs4char; // use -1 for EOF
146 typedef int fixedint;
147 
148 #if defined(_MSC_VER) || defined(MONA)
149 const ucs4char* UC(const char *str);
150 #elif defined(__CYGWIN__) || defined (_WIN32)
151 #define UC_(x) L ## x
152 #define UC(x) reinterpret_cast<const ucs4char*>(UC_(x)L"\0")
153 #else
154 #define UC_(x) L ## x
155 #define UC(x) reinterpret_cast<const ucs4char*>(UC_(x))
156 #endif
157 
158 #ifdef __GNUC__
159 #define ALWAYS_INLINE  __attribute__((always_inline))
160 // FIXME: disable DIRECT_THREADED_CODE for XCode and Clang builds
161 // USE_XCODE: set by CMakeLists.txt
162 #if !defined(USE_XCODE) && !defined(__clang__)
163 #define USE_DIRECT_THREADED_CODE
164 #endif /* USE_XCODE */
165 #else
166 #define ALWAYS_INLINE
167 #endif
168 
169 #include "ucs4string.h"
170 
171 #define PRFILER_TEMP_FILE "/tmp/mosh-profiler.log"
172 
173 void* my_realloc(void *ptr, size_t oldSize, size_t newSize);
174 void my_dont_free(void *ptr, size_t size);
175 void mosh_init();
176 
177 
178 namespace scheme {
179 
180 
181 #ifdef USE_BOEHM_GC
182 class Object;
183 typedef std::vector<Object, gc_allocator<Object> > ObjectVector;
184 #else
185 class Object;
186 typedef std::vector<Object> ObjectVector;
187 #endif
188 
189 
190 //extern int strcmp99(const ucs4char *s1, const ucs4char *s2);
191 struct ltstr EXTEND_GC
192 {
operatorEXTEND_GC193   bool operator()(const ucs4char* s1, const ucs4char* s2) const
194   {
195       while (*s1 == *s2++) {
196           if (*s1++=='\0') {
197               return false;
198           }
199       }
200     return(*s1 - *--s2) < 0;
201   }
202 };
203 
204 /*
205     @return always true if sizeof(size_t) == 8
206     @return true or false if sizeof(size_t) == 4
207 */
isInSize_t(int64_t size)208 inline bool isInSize_t(int64_t size)
209 {
210     return static_cast<size_t>(size) == static_cast<uint64_t>(size);
211 }
212 
213 /*
214     memcpy after checking size in size_t
215 */
moshMemcpy(void * dest,const void * src,int64_t size)216 inline void moshMemcpy(void *dest, const void *src, int64_t size)
217 {
218     MOSH_ASSERT(isInSize_t(size));
219     memcpy(dest, src, static_cast<size_t>(size));
220 }
221 
222 #ifdef USE_BOEHM_GC
223 class gc_map2 : public std::map<const ucs4char* const, Object, ltstr, gc_allocator<std::pair<const ucs4char* const, Object> > >, public gc { };
224 #else
225     class gc_map2 : public std::map<const ucs4char* const, Object, ltstr, std::allocator<std::pair<const ucs4char* const, Object> > > {};
226 #endif
227 }
228 
allocatePointerFreeU8Array(int64_t size)229 inline uint8_t* allocatePointerFreeU8Array(int64_t size)
230 {
231     MOSH_ASSERT(scheme::isInSize_t(size));
232 #ifdef USE_BOEHM_GC
233     return new(PointerFreeGC) uint8_t[static_cast<size_t>(size)];
234 #else
235     return new uint8_t[BUF_SIZE];
236 #endif
237 }
238 
239 #endif // SCHEME_SCHEME_H_
240