UrForth: removed some unused code; oops! fixed bug in C kernel basic compiler (negati...
[urasm.git] / src / urcforth.c
blob3819ebdef17cd547432cf256b716bda45ad882ea
1 // UrForth/C standalone
2 // coded by Ketmar // Invisible Vector
3 // GPLv3 ONLY
4 //
5 #ifndef _GNU_SOURCE
6 # define _GNU_SOURCE
7 #endif
9 #include <getopt.h>
10 #include <setjmp.h>
11 #include <stdarg.h>
12 #include <stddef.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
23 #ifdef WIN32
24 # include <windows.h>
25 #else
26 # include <signal.h>
27 #endif
29 #include "liburforth/urforth.h"
32 #define UR_FORCE_INLINE static inline __attribute__((always_inline))
33 #define UR_INLINE static inline
36 #define VERSION_HI 0
37 #define VERSION_MID 2
38 #define VERSION_LO 2
41 #define MAYBE_UNUSED __attribute__((unused))
44 // ////////////////////////////////////////////////////////////////////////// //
45 __attribute((unused))
46 static const char *ur_assert_failure (const char *cond, const char *fname, int fline,
47 const char *func)
49 for (const char *t = fname; *t; ++t) {
50 #ifdef WIN32
51 if (*t == '/' || *t == '\\') fname = t+1;
52 #else
53 if (*t == '/') fname = t+1;
54 #endif
56 fflush(stdout);
57 fprintf(stderr, "\n%s:%d: Assertion in `%s` failed: %s\n", fname, fline, func, cond);
58 fflush(stderr);
59 abort();
62 #define ur_assert(cond_) do { if (__builtin_expect((!(cond_)), 0)) { ur_assert_failure(#cond_, __FILE__, __LINE__, __PRETTY_FUNCTION__); } } while (0)
65 // ////////////////////////////////////////////////////////////////////////// //
66 static char *ufoIncludeDir = NULL;
69 //==========================================================================
71 // initUFEInclideDir
73 //==========================================================================
74 static void initUFEInclideDir (void) {
75 const char *id = getenv("URASM_URFORTH_INCLUDE_DIR");
76 if (id && id[0]) {
77 ufoIncludeDir = strdup(id);
78 } else {
79 char myDir[4096];
80 memset(myDir, 0, sizeof(myDir));
81 #ifndef WIN32
82 if (readlink("/proc/self/exe", myDir, sizeof(myDir)-1) < 0) {
83 strcpy(myDir, ".");
84 } else {
85 char *p = (char *)strrchr(myDir, '/');
86 if (!p) strcpy(myDir, "."); else *p = '\0';
88 #else
89 GetModuleFileName(GetModuleHandle(NULL), myDir, sizeof(myDir)-1);
90 char *p = strrchr(myDir, '\\');
91 if (!p) strcpy(myDir, "."); else *p = '\0';
92 #endif
93 strcat(myDir, "/urflibs");
94 ur_assert(ufoIncludeDir == NULL);
95 ufoIncludeDir = strdup(myDir);
97 while (ufoIncludeDir[0] && ufoIncludeDir[strlen(ufoIncludeDir)-1] == '/') ufoIncludeDir[strlen(ufoIncludeDir)-1] = '\0';
98 if (!ufoIncludeDir[0]) strcpy(ufoIncludeDir, ".");
102 ///////////////////////////////////////////////////////////////////////////////
103 // options
105 static struct option longOpts[] = {
106 {"help", 0, NULL, 'h'},
107 {NULL, 0, NULL, 0}
111 //==========================================================================
113 // usage
115 //==========================================================================
116 static void usage (const char *pname) {
117 printf(
118 "usage: %s [options] infile\n"
119 "\n"
120 "options:\n"
121 " -h --help this help\n"
122 , pname);
126 static jmp_buf errJP;
129 //==========================================================================
131 // ufoFatalError
133 //==========================================================================
134 __attribute__((noreturn))
135 void ufoFatalError (void) {
136 longjmp(errJP, 666);
140 //==========================================================================
142 // strprintfVA
144 //==========================================================================
145 static char *strprintfVA (const char *fmt, va_list vaorig) {
146 char *buf = NULL;
147 int olen, len = 128;
149 buf = malloc(len);
150 if (buf == NULL) { fprintf(stderr, "\nFATAL: out of memory!\n"); abort(); }
151 for (;;) {
152 char *nb;
153 va_list va;
155 va_copy(va, vaorig);
156 olen = vsnprintf(buf, len, fmt, va);
157 va_end(va);
158 if (olen >= 0 && olen < len) return buf;
159 if (olen < 0) olen = len*2-1;
160 nb = realloc(buf, olen+1);
161 if (nb == NULL) { fprintf(stderr, "\nFATAL: out of memory!\n"); abort(); }
162 buf = nb;
163 len = olen+1;
168 //==========================================================================
170 // strprintf
172 //==========================================================================
173 static __attribute__((format(printf,1,2))) char *strprintf (const char *fmt, ...) {
174 char *buf = NULL;
175 va_list va;
176 va_start(va, fmt);
177 buf = strprintfVA(fmt, va);
178 va_end(va);
179 return buf;
183 //==========================================================================
185 // strHasPathDelim
187 //==========================================================================
188 static int strHasPathDelim (const char *s) {
189 if (!s || !s[0]) return 0;
190 #ifdef WIN32
191 return (strchr(s, '/') || strchr(s, '\\') ? 1 : 0);
192 #else
193 return (strchr(s, '/') ? 1 : 0);
194 #endif
198 //==========================================================================
200 // createIncludeName
202 // returns malloced string
204 //==========================================================================
205 static char *createIncludeName (const char *fname, int assystem, const char *defaultmain,
206 const char *lastIncPathUFO)
208 if (!fname || !fname[0]) return NULL;
209 char *res;
210 if (fname[0] != '/') {
211 const char *incdir;
212 if (!assystem) {
213 incdir = NULL;
214 } else if (assystem == -669) {
215 incdir = lastIncPathUFO;
216 } else if (assystem == -666) {
217 incdir = lastIncPathUFO;
218 if (!incdir || !incdir[0]) incdir = ufoIncludeDir;
219 } else {
220 ur_assert(0);
222 if (incdir == NULL || incdir[0] == 0) incdir = ".";
223 res = strprintf("%s/%s", (incdir && incdir[0] ? incdir : "."), fname);
224 } else {
225 res = strprintf("%s", fname);
227 struct stat st;
228 if (defaultmain && defaultmain[0]) {
229 if (stat(res, &st) == 0) {
230 if (S_ISDIR(st.st_mode)) {
231 char *rs = strprintf("%s/%s", res, defaultmain);
232 free(res);
233 res = rs;
237 /* check if there is the disk file */
238 if (strHasPathDelim(fname) && stat(res, &st) != 0) {
239 /* no file, try "root include" */
240 const char *incdir = (!assystem ? NULL : ufoIncludeDir);
241 char *rs = strprintf("%s/%s", (incdir && incdir[0] ? incdir : "."), fname);
242 free(res);
243 res = rs;
244 /* check for dir again */
245 if (defaultmain && defaultmain[0]) {
246 if (stat(res, &st) == 0) {
247 if (S_ISDIR(st.st_mode)) {
248 char *rs = strprintf("%s/%s", res, defaultmain);
249 free(res);
250 res = rs;
255 //fprintf(stderr, "inc: fname=<%s>; sys=%d; def=<%s>; res=<%s>\n", fname, assystem, defaultmain, res);
256 return res;
260 //==========================================================================
262 // ufoCreateIncludeName
264 //==========================================================================
265 char *ufoCreateIncludeName (const char *fname, int assystem, const char *lastIncPath) {
266 #if 0
267 fprintf(stderr, "ICIN: fname=<%s>; lastinc=<%s>; assystem=%d\n",
268 fname, lastIncPath, assystem);
269 #endif
270 assystem = (assystem ? -666 : -669);
271 if (lastIncPath == NULL) lastIncPath = ufoIncludeDir;
272 char *res = createIncludeName(fname, assystem, NULL, lastIncPath);
273 struct stat st;
274 char *tmp;
275 if (res == NULL || res[0] == 0 || stat(res, &st) != 0) return res;
276 if (S_ISDIR(st.st_mode)) {
277 tmp = strprintf("%s/%s", res, "00-main-loader.f");
278 free(res);
279 res = tmp;
281 return res;
285 #ifndef WIN32
286 //==========================================================================
288 // sigCtrlC
290 //==========================================================================
291 static void sigCtrlC (int sig) {
292 ufoSetUserAbort();
294 #endif
297 //==========================================================================
299 // initUrForth
301 //==========================================================================
302 static void initUrForth (void) {
303 ufoCondDefine("STANDALONE");
307 //==========================================================================
309 // main
311 //==========================================================================
312 int main (int argc, char *argv[]) {
313 int res = 0, c;
314 const char *pname = argv[0];
316 ufoSetUserPostInit(&initUrForth);
318 initUFEInclideDir();
320 printf("UrForth/C v%d.%d.%d, compile date: %s %s\n", VERSION_HI, VERSION_MID, VERSION_LO, __DATE__, __TIME__);
321 while ((c = getopt_long(argc, argv, "h", longOpts, NULL)) >= 0) {
322 switch (c) {
323 case '?': return 1;
324 case 'h': usage(pname); res = 0; goto earlyerrquit;
325 break;
329 if (optind >= argc) {
330 fprintf(stderr, "load what?\n");
331 res = 1;
332 goto earlyerrquit;
333 } else {
334 //inFile = strdup(argv[optind]);
337 #ifndef WIN32
338 signal(SIGINT, &sigCtrlC);
339 #endif
340 if (setjmp(errJP) == 0) {
341 ufoInit();
342 ufoRunFile(argv[optind]);
343 } else {
344 res = 1;
347 ufoDeinit();
349 earlyerrquit:
350 if (ufoIncludeDir) free(ufoIncludeDir);
352 return (res ? 1 : 0);