1 // UrForth/C standalone
2 // coded by Ketmar // Invisible Vector
19 #include <sys/types.h>
29 #include "liburforth/urforth.h"
32 #define UR_FORCE_INLINE static inline __attribute__((always_inline))
33 #define UR_INLINE static inline
41 #define MAYBE_UNUSED __attribute__((unused))
44 // ////////////////////////////////////////////////////////////////////////// //
46 static const char *ur_assert_failure (const char *cond
, const char *fname
, int fline
,
49 for (const char *t
= fname
; *t
; ++t
) {
51 if (*t
== '/' || *t
== '\\') fname
= t
+1;
53 if (*t
== '/') fname
= t
+1;
57 fprintf(stderr
, "\n%s:%d: Assertion in `%s` failed: %s\n", fname
, fline
, func
, cond
);
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 //==========================================================================
73 //==========================================================================
74 static void initUFEInclideDir (void) {
75 const char *id
= getenv("URASM_URFORTH_INCLUDE_DIR");
77 ufoIncludeDir
= strdup(id
);
80 memset(myDir
, 0, sizeof(myDir
));
82 if (readlink("/proc/self/exe", myDir
, sizeof(myDir
)-1) < 0) {
85 char *p
= (char *)strrchr(myDir
, '/');
86 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
89 GetModuleFileName(GetModuleHandle(NULL
), myDir
, sizeof(myDir
)-1);
90 char *p
= strrchr(myDir
, '\\');
91 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
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 ///////////////////////////////////////////////////////////////////////////////
105 static struct option longOpts
[] = {
106 {"help", 0, NULL
, 'h'},
111 //==========================================================================
115 //==========================================================================
116 static void usage (const char *pname
) {
118 "usage: %s [options] infile\n"
121 " -h --help this help\n"
126 static jmp_buf errJP
;
129 //==========================================================================
133 //==========================================================================
134 __attribute__((noreturn
))
135 void ufoFatalError (void) {
140 //==========================================================================
144 //==========================================================================
145 static char *strprintfVA (const char *fmt
, va_list vaorig
) {
150 if (buf
== NULL
) { fprintf(stderr
, "\nFATAL: out of memory!\n"); abort(); }
156 olen
= vsnprintf(buf
, len
, fmt
, 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(); }
168 //==========================================================================
172 //==========================================================================
173 static __attribute__((format(printf
,1,2))) char *strprintf (const char *fmt
, ...) {
177 buf
= strprintfVA(fmt
, va
);
183 //==========================================================================
187 //==========================================================================
188 static int strHasPathDelim (const char *s
) {
189 if (!s
|| !s
[0]) return 0;
191 return (strchr(s
, '/') || strchr(s
, '\\') ? 1 : 0);
193 return (strchr(s
, '/') ? 1 : 0);
198 //==========================================================================
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
;
210 if (fname
[0] != '/') {
214 } else if (assystem
== -669) {
215 incdir
= lastIncPathUFO
;
216 } else if (assystem
== -666) {
217 incdir
= lastIncPathUFO
;
218 if (!incdir
|| !incdir
[0]) incdir
= ufoIncludeDir
;
222 if (incdir
== NULL
|| incdir
[0] == 0) incdir
= ".";
223 res
= strprintf("%s/%s", (incdir
&& incdir
[0] ? incdir
: "."), fname
);
225 res
= strprintf("%s", fname
);
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
);
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
);
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
);
255 //fprintf(stderr, "inc: fname=<%s>; sys=%d; def=<%s>; res=<%s>\n", fname, assystem, defaultmain, res);
260 //==========================================================================
262 // ufoCreateIncludeName
264 //==========================================================================
265 char *ufoCreateIncludeName (const char *fname
, int assystem
, const char *lastIncPath
) {
267 fprintf(stderr
, "ICIN: fname=<%s>; lastinc=<%s>; assystem=%d\n",
268 fname
, lastIncPath
, assystem
);
270 assystem
= (assystem
? -666 : -669);
271 if (lastIncPath
== NULL
) lastIncPath
= ufoIncludeDir
;
272 char *res
= createIncludeName(fname
, assystem
, NULL
, lastIncPath
);
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");
286 //==========================================================================
290 //==========================================================================
291 static void sigCtrlC (int sig
) {
297 //==========================================================================
301 //==========================================================================
302 static void initUrForth (void) {
303 ufoCondDefine("STANDALONE");
307 //==========================================================================
311 //==========================================================================
312 int main (int argc
, char *argv
[]) {
314 const char *pname
= argv
[0];
316 ufoSetUserPostInit(&initUrForth
);
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) {
324 case 'h': usage(pname
); res
= 0; goto earlyerrquit
;
329 if (optind
>= argc
) {
330 fprintf(stderr
, "load what?\n");
334 //inFile = strdup(argv[optind]);
338 signal(SIGINT
, &sigCtrlC
);
340 if (setjmp(errJP
) == 0) {
342 ufoRunFile(argv
[optind
]);
350 if (ufoIncludeDir
) free(ufoIncludeDir
);
352 return (res
? 1 : 0);