3 Copyright (C) 1998 Lars Krueger
5 This file is part of FLK.
7 FLK is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * $Id: flk.c,v 1.25 1998/08/30 10:50:59 root Exp $
24 *****************************************************************************
26 * Revision 1.25 1998/08/30 10:50:59 root
29 * Revision 1.24 1998/07/15 16:38:23 root
30 * TERM=dumb bugss removed
32 * Revision 1.23 1998/07/09 19:16:41 root
33 * fixed relocation to enable code size changes
35 * Revision 1.22 1998/06/24 05:30:46 root
36 * corrected terminal setup and cleanup
38 * Revision 1.21 1998/06/03 07:55:16 root
39 * corrected flush on exit
41 * Revision 1.20 1998/06/01 18:05:39 root
42 * changed image search order (argv[0] doesn't contain a path)
44 * Revision 1.19 1998/06/01 17:51:42 root
47 * Revision 1.18 1998/05/24 18:43:16 root
48 * delayed flush corrected
50 * Revision 1.17 1998/05/24 15:41:26 root
51 * Delayed flush can be turned off
53 * Revision 1.16 1998/05/23 19:23:54 root
54 * delayed flushing of stdout
56 * Revision 1.15 1998/05/21 19:24:49 root
59 * Revision 1.14 1998/05/17 08:27:09 root
62 * Revision 1.13 1998/05/16 16:19:24 root
63 * direct terminfo access
65 * Revision 1.12 1998/05/09 21:47:05 root
69 * Revision 1.11 1998/05/02 15:05:55 root
70 * CREATE-FILE corrected
72 * Revision 1.10 1998/05/01 18:13:33 root
73 * Image search order changed to:
74 * executable, ./flk.flk, default.flk
76 * Revision 1.9 1998/05/01 18:11:25 root
77 * GNU license text added
80 * Revision 1.8 1998/04/30 09:42:25 root
81 * other image search order
83 * Revision 1.7 1998/04/29 18:26:32 root
85 * TYPE fixed (was printf like, now puts like)
87 * Revision 1.6 1998/04/27 18:41:42 root
88 * directory primitives
90 * Revision 1.5 1998/04/25 11:03:28 root
91 * added flk.c to check in list
93 * Revision 1.4 1998/04/11 11:58:14 root
94 * REPOSITION-FILE checked
96 * Revision 1.3 1998/04/10 14:42:50 root
97 * new header format to ease SAVE-SAYSTEM
99 * Revision 1.2 1998/04/07 20:10:33 root
100 * final .flk format, OS calls, image search
115 #include <sys/mman.h>
116 #include <sys/stat.h>
117 #include <sys/time.h>
118 #include <sys/types.h>
120 #define NCURSES_INTERNALS
125 static int goobers
= 0;
128 static DIR *glob_dir
= NULL
;
129 static struct dirent
*glob_dirent
= NULL
;
130 static struct termios shell_ios
;
131 static struct termios prog_ios
;
134 # define FLUSHBUFFERLEN (5000)
135 static char flushBuffer
[FLUSHBUFFERLEN
];
136 static unsigned flushBufferInd
;
139 static void myFlush (void) {
140 write(1, flushBuffer
, flushBufferInd
);
145 static void myputp (const char *s
) {
150 if (l
+flushBufferInd
>= FLUSHBUFFERLEN
) {
151 signal(SIGALRM
, SIG_IGN
);
154 memcpy(flushBuffer
+flushBufferInd
, s
, l
);
159 static void flushHandler (int sig
) {
164 static void startFlusher (void) {
165 if (flushBufferInd
) {
168 to
.it_value
.tv_sec
= 0;
169 to
.it_value
.tv_usec
= 40000;
170 to
.it_interval
.tv_sec
= 0;
171 to
.it_interval
.tv_usec
= 0;
172 setitimer(ITIMER_REAL
, &to
, NULL
);
173 signal(SIGALRM
, flushHandler
);
179 # define startFlusher(...) ((void)0)
183 /*==============================global constants==============================*/
184 static const unsigned char headerID
[] = "FLK Image 1.1";
185 #define HEADER_ID_LEN (sizeof(headerID)-1)
187 #define FTRUE ((unsigned int)(~0))
189 #define STACK unsigned int _stptr_ = 0
191 #define POP(var,erg) do { erg=stack[_stptr_].var; _stptr_++; } while (0)
192 #define PUSH(var, val) do {_stptr_--; stack[_stptr_].var=val; } while (0)
193 #define POPSTRING(erg) do { unsigned int len; char *s; POP(uval, len); POP(caddr, s); erg=makeCString(s, len); } while (0)
194 #define DPUSH(x) do { PUSH(nval, x); PUSH(nval, (x<0) ? -1 : 0); } while (0)
195 #define UDPUSH(x) do { PUSH(uval, x); PUSH(uval, 0); } while (0)
198 /*==============================global variables==============================*/
199 static unsigned int *ReloTable
;
200 static unsigned int *ForthDataStack
, *ForthCallStack
;
201 static unsigned int *Image
;
202 static unsigned int MemorySize
= 0;
205 /*==============================static functions==============================*/
206 /* This could be done more eloquently, right? */
207 static void printErrorBanner (void) {
208 printf("FLK Error: ");
212 static char *makeCString (const char *fstr
, unsigned int len
) {
213 char *res
= (char *)malloc(len
+1);
216 memcpy(res
, fstr
, len
);
222 static void setupTerm (void) {
223 setupterm(NULL
, 1, NULL
);
225 tcgetattr(1, &shell_ios
);
226 prog_ios
= shell_ios
;
227 prog_ios
.c_lflag
&= ~(ICANON
| ECHO
);
228 prog_ios
.c_iflag
&= ~(ICRNL
| INLCR
);
229 tcsetattr(1, TCSANOW
, &prog_ios
);
240 static void cleanupTerm (void) {
241 if (glob_dir
) closedir(glob_dir
);
243 tcsetattr(1, TCSADRAIN
, &shell_ios
);
245 signal(SIGALRM
, SIG_IGN
);
251 /*==============================system primitives=============================*/
259 typedef void (*SystemPrimitive
) (Cell
*stack
);
263 static void EMIT (Cell
*stack
) {
270 case -1: /* backspace */
271 if (!cursor_left
) myputp("\010"); else myputp(cursor_left
);
284 static void KEY (Cell
*stack
) {
290 } while (!(32 <= key
&& key
< 127));
296 static void TYPE (Cell
*stack
) {
308 static void CR (Cell
*stack
) {
320 static void AT_XY (Cell
*stack
) {
326 if (cursor_address
) {
327 myputp(tgoto(cursor_address
, x
, y
));
334 static void KEY_IF (Cell
*stack
) {
343 PUSH(nval
, select(2, &set
, NULL
, NULL
, &tv
) ? FTRUE
: 0);
348 static void PAGE (Cell
*stack
) {
350 myputp(clear_screen
);
357 static void EKEY (Cell
*stack
) {
364 /* u -- u false | char true */
365 static void EKEY_2_CHAR (Cell
*stack
) {
371 PUSH(uval
, (32 <= key
&& key
< 127) ? FTRUE
: 0);
376 static void EKEY_IF (Cell
*stack
) {
382 static void EMIT_IF (Cell
*stack
) {
389 static void MS (Cell
*stack
) {
396 signal(SIGALRM
, SIG_IGN
);
400 tv
.tv_usec
= (ms
%1000)*1000;
401 select(0, 0, 0, 0, &tv
);
405 /* -- sec min hr day mn yr */
406 static void TIME_DATE (Cell
*stack
) {
408 time_t t
= time(NULL
);
409 struct tm
*tms
= localtime(&t
);
412 PUSH(uval
, tms
->tm_sec
);
413 PUSH(uval
, tms
->tm_min
);
414 PUSH(uval
, tms
->tm_hour
);
415 PUSH(uval
, tms
->tm_mday
);
416 PUSH(uval
, tms
->tm_mon
+1);
417 PUSH(uval
, tms
->tm_year
+1900);
421 /* u -- a-addr ior */
422 static void ALLOCATE (Cell
*stack
) {
430 PUSH(uval
, p
? 0 : -9);
435 static void _FREE (Cell
*stack
) {
445 /* addr u -- addr2 ior */
446 static void RESIZE (Cell
*stack
) {
455 PUSH(nval
, p2
? 0 : -9);
460 static void BYE (Cell
*stack
) {
471 static void SCR_ROWS (Cell
*stack
) {
478 static void SCR_COLS (Cell
*stack
) {
485 static void CLOSE_FILE (Cell
*stack
) {
490 if (close(fid
)) PUSH(nval
, -37); else PUSH(nval
, 0);
499 static int c_mode (int forth_mode
) {
502 if (forth_mode
&FM_RO
) erg
= O_RDONLY
;
503 else if (forth_mode
&FM_RW
) erg
= O_RDWR
;
504 else if (forth_mode
&FM_WO
) erg
= O_WRONLY
;
509 /* addr u mode -- fid ior */
510 static void CREATE_FILE (Cell
*stack
) {
512 int mode
, fid
, nmode
;
517 nmode
= c_mode(mode
);
518 fid
= open(name
, nmode
|O_CREAT
, 0666);
520 if (fid
== -1) PUSH(nval
, -37); else PUSH(nval
, 0);
526 static void DELETE_FILE (Cell
*stack
) {
531 if (unlink(name
) < 0) PUSH(nval
, -37); else PUSH(nval
, 0);
537 static void FILE_POSITION (Cell
*stack
) {
542 where
= lseek(fid
, 0, SEEK_CUR
);
545 if (where
== -1) PUSH(nval
, -37); else PUSH(nval
, 0);
550 static void FILE_SIZE (Cell
*stack
) {
556 where
= lseek(fid
, 0, SEEK_CUR
);
562 off_t end
= lseek(fid
, 0, SEEK_END
);
565 if (-1 == lseek(fid
, where
, SEEK_SET
)) PUSH(nval
, -37); else PUSH(nval
, 0);
570 /* addr u mode -- fid ior */
571 static void OPEN_FILE (Cell
*stack
) {
573 int mode
, fid
, nmode
;
578 nmode
= c_mode(mode
);
579 fid
= open(name
, nmode
);
581 if (fid
== -1) PUSH(nval
, -38); else PUSH(nval
, 0);
586 /* addr u fid -- u2 ior */
587 static void READ_FILE (Cell
*stack
) {
590 unsigned int len
, lread
;
596 lread
= read(fid
, buf
, len
);
598 if (lread
== -1) PUSH(nval
, -37); else PUSH(nval
, 0);
602 /* addr u fid -- u2 flag ior */
603 static void READ_LINE (Cell
*stack
) {
605 int fid
, seek_res
, len
, lread
, i
;
611 lread
= read(fid
, buf
, len
);
612 for(i
= 0; i
< lread
&& buf
[i
] != '\n'; i
++);
613 seek_res
= lseek(fid
, i
-lread
+1, SEEK_CUR
);
615 PUSH(nval
, lread
? FTRUE
: 0);
616 PUSH(nval
, (lread
== -1 || seek_res
== -1) ? -37 : 0);
621 static void REPOSITION_FILE (Cell
*stack
) {
624 unsigned int udh
, udl
;
629 if (!udh
) res
= lseek(fid
, udl
, SEEK_SET
);
630 if (res
< 0) PUSH(nval
, -37); else PUSH(nval
, 0);
635 static void RESIZE_FILE (Cell
*stack
) {
638 unsigned int udh
, udl
, flen
;
644 flen
= lseek(fid
, 0, SEEK_END
);
645 if ((int)flen
!= -1) {
648 char *buf
= malloc(udl
-flen
);
650 res
= write(fid
, buf
, udl
-flen
);
653 } else res
= ftruncate(fid
, udl
);
656 if (res
< 0) PUSH(nval
, -37); else PUSH(nval
, 0);
660 /* a1 u1 a2 u2 -- ior */
661 static void RENAME_FILE (Cell
*stack
) {
667 if (rename(from
, to
) < 0) PUSH(nval
, -37); else PUSH(nval
, 0);
673 /* addr u fid -- ior */
674 static void WRITE_FILE (Cell
*stack
) {
683 if (write(fid
, buf
, len
) != len
) PUSH(nval
, -37); else PUSH(nval
, 0);
687 /* addr u fid -- ior */
688 static void WRITE_LINE (Cell
*stack
) {
691 unsigned int len
, lwr
;
697 lwr
= write(fid
, buf
, len
);
700 if (1 != write(fid
, &cr
, 1)) lwr
= -1;
702 if (lwr
!= len
) PUSH(nval
, -37); else PUSH(nval
, 0);
706 /* addr u -- x ior */
707 static void FILE_STATUS (Cell
*stack
) {
710 static struct stat buf
;
714 erg
= stat(name
, &buf
);
716 if (erg
== 0) PUSH(nval
, 0); else PUSH(nval
, -38);
722 static void FLUSH_FILE (Cell
*stack
) {
727 if (-1 == fsync(fid
)) PUSH(nval
, -37); else PUSH(nval
, 0);
733 static void IS_DIRECTORY (Cell
*stack
) {
738 if (S_ISDIR(buf
->st_mode
)) PUSH(uval
, FTRUE
); else PUSH(uval
, 0);
743 static void SCR_BELL (Cell
*stack
) {
752 static void SCR_FLASH (Cell
*stack
) {
754 myputp(flash_screen
);
760 /* addr len -- retval */
761 static void SYSTEM (Cell
*stack
) {
767 tcsetattr(1, TCSADRAIN
, &shell_ios
);
769 signal(SIGALRM
, SIG_IGN
);
772 PUSH(nval
, system(cmd
));
774 tcsetattr(1, TCSADRAIN
, &prog_ios
);
779 #define READDIR do { \
785 glob_dirent = readdir(glob_dir); \
786 if (!glob_dirent) { \
791 closedir(glob_dir); \
794 PUSH(caddr, glob_dirent->d_name); \
795 PUSH(uval, strlen(glob_dirent->d_name)); \
802 /* addr1 u1 -- addr2 u2 flag1 */
803 static void FIND_FIRST (Cell
*stack
) {
808 if (glob_dir
) closedir(glob_dir
);
809 glob_dir
= opendir(dir
);
815 /* -- addr u flag1 */
816 static void FIND_NEXT (Cell
*stack
) {
823 static void TIME_OF_DAY (Cell
*stack
) {
827 gettimeofday(&tv
, NULL
);
828 PUSH(uval
, tv
.tv_sec
);
829 PUSH(uval
, tv
.tv_usec
);
833 /* addr len flag -- lib */
834 static void OPENLIB (Cell
*stack
) {
842 lib
= dlopen(name
, flags
);
849 static void LIBERROR (Cell
*stack
) {
851 PUSH(caddr
, (char *)dlerror());
855 /* lib addr len -- fct */
856 static void LIBSYMBOL (Cell
*stack
) {
863 sym
= dlsym(lib
, name
);
870 static void CLOSELIB (Cell
*stack
) {
879 /* -- bool-array-addr */
880 static void TERM_BOOL (Cell
*stack
) {
882 PUSH(vaddr
, cur_term
->type
.Booleans
);
886 /* -- short-array-addr */
887 static void TERM_NUMBER (Cell
*stack
) {
889 PUSH(vaddr
, cur_term
->type
.Numbers
);
893 /* -- char*-array-addr */
894 static void TERM_STRING (Cell
*stack
) {
896 PUSH(vaddr
, cur_term
->type
.Strings
);
901 static void GET_CWD (Cell
*stack
) {
903 static char buf
[PATH_MAX
];
905 getcwd(buf
, sizeof(buf
));
912 static void IS_GOOBERSP (Cell
*stack
) {
919 static void GET_BIN_PATH (Cell
*stack
) {
921 static char buf
[PATH_MAX
];
923 memset(buf
, 0, sizeof(buf
));
924 if (readlink("/proc/self/exe", buf
, sizeof(buf
)-1) < 0) {
927 char *p
= strrchr(buf
, '/');
929 if (p
!= NULL
) p
[1] = 0; else strcpy(buf
, "./");
935 static const SystemPrimitive primitives
[] = {
936 (SystemPrimitive
)(51), // # of primitives
937 EMIT
, KEY
, TYPE
, CR
, AT_XY
, KEY_IF
, PAGE
, EKEY
, EKEY_2_CHAR
, EKEY_IF
,
938 EMIT_IF
, MS
, TIME_DATE
, ALLOCATE
, _FREE
, RESIZE
, BYE
, CLOSE_FILE
,
939 CREATE_FILE
, DELETE_FILE
, FILE_POSITION
, FILE_SIZE
, OPEN_FILE
, READ_FILE
,
940 READ_LINE
, REPOSITION_FILE
, RESIZE_FILE
, RENAME_FILE
, WRITE_FILE
,
941 WRITE_LINE
, FILE_STATUS
, FLUSH_FILE
, SCR_ROWS
, SCR_COLS
, FIND_FIRST
,
942 FIND_NEXT
, IS_DIRECTORY
, SCR_BELL
, SCR_FLASH
, SYSTEM
, TIME_OF_DAY
, OPENLIB
,
943 LIBERROR
, LIBSYMBOL
, CLOSELIB
, TERM_BOOL
, TERM_NUMBER
, TERM_STRING
, GET_CWD
,
944 IS_GOOBERSP
, GET_BIN_PATH
948 /* Fill the global variables with values. */
950 HA_INIT_DATASTACK
= 0, /* initial value of EBP */
951 HA_INIT_CALLSTACK
, /* initial value of ESP */
952 HA_RELTABLE
, /* address of relocation table */
953 HA_LOADER
, /* loader table address */
954 HA_HERE_LIMIT
, /* first byte after data area */
955 HA_CHERE_LIMIT
, /* first byte after code area */
956 HA_IMAGE_BASE
, /* base address of image */
957 HA_INIT_HERE
, /* initial value of HERE */
958 HA_INIT_CHERE
, /* initial value of CHERE */
959 HA_BOOT_CODE
, /* address of boot code */
960 HA_ENTRY
, /* address of entry_point */
961 HA_CODESIZE
, /* number of cells in code area */
962 HA_DATASIZE
, /* number of cells in data area */
963 HA_DATA_CELLS
, /* initial size of data stack in cells */
964 HA_CALL_CELLS
/* initial size of call stack in cells */
968 #define READCELL(x) read(inFile, &x, sizeof(unsigned int))
970 static int readImage (int inFile
, unsigned int offs
) {
971 unsigned int imglen
, caLen
, daLen
, reloAlloc
, reloCnt
, caUse
, daUse
, imgBase
, oldCaLen
/*, oldDaLen*/;
972 /* inFile is correctly positioned */
973 #define FP printf("%d\n", lseek(inFile, 0, SEEK_CUR));
975 reloAlloc
= (3*reloCnt
)/2;
976 ReloTable
= (unsigned int *)calloc(reloAlloc
+2, sizeof(unsigned int));
977 if (!ReloTable
) return 0;
978 ReloTable
[0] = reloAlloc
;
979 ReloTable
[1] = reloCnt
;
980 read(inFile
, &ReloTable
[2], reloCnt
*sizeof(unsigned int));
989 if (MemorySize
> caLen
) {
992 printf("Memory size override for code area used.\n");
995 if (MemorySize
> daLen
) {
998 printf("Memory size override for data area used.\n");
1001 imglen
= caLen
+daLen
;
1002 //Image = (unsigned int *)calloc(imglen, sizeof(char));
1003 Image
= (unsigned int *)mmap(NULL
, imglen
, PROT_EXEC
|PROT_READ
|PROT_WRITE
, MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
1004 if (Image
== MAP_FAILED
) {
1006 printf("Could not allocate memory for image.\n");
1010 memset(Image
, 0, imglen
);
1012 printf("code area length: %d bytes; data area length: %d bytes; relocation records: %u\n", caLen
, daLen
, reloCnt
);
1014 read(inFile
, Image
, caUse
);
1015 read(inFile
, Image
+caLen
/sizeof(unsigned int), daUse
);
1016 ForthDataStack
= (unsigned int *)calloc(Image
[HA_DATA_CELLS
]+1, sizeof(unsigned int));
1017 if (ForthDataStack
== NULL
) return 0;
1018 ForthCallStack
= (unsigned int *)calloc(Image
[HA_CALL_CELLS
], sizeof(unsigned int));
1019 if (ForthCallStack
== NULL
) return 0;
1020 Image
[HA_INIT_DATASTACK
] = (unsigned int) ForthDataStack
+Image
[HA_DATA_CELLS
]*sizeof(unsigned int);
1021 Image
[HA_INIT_CALLSTACK
] = (unsigned int) ForthCallStack
+Image
[HA_CALL_CELLS
]*sizeof(unsigned int);
1022 Image
[HA_RELTABLE
] = (unsigned int)ReloTable
;
1023 Image
[HA_LOADER
] = (unsigned int)primitives
;
1024 Image
[HA_HERE_LIMIT
] = (unsigned int)Image
+imglen
;
1025 Image
[HA_CHERE_LIMIT
] = (unsigned int)Image
+caLen
;
1026 Image
[HA_IMAGE_BASE
] = (unsigned int)Image
;
1027 Image
[HA_INIT_CHERE
] = (unsigned int)Image
+caUse
;
1028 Image
[HA_INIT_HERE
] = (unsigned int)Image
+daUse
+caLen
;
1029 oldCaLen
= Image
[HA_CODESIZE
];
1030 //oldDaLen = Image[HA_DATASIZE];
1031 Image
[HA_CODESIZE
] = caLen
;
1032 Image
[HA_DATASIZE
] = daLen
;
1033 for (unsigned int i
= 0; i
< ReloTable
[1]; ++i
) {
1034 unsigned int *relAddr
, origVal
;
1035 char *cImage
= (char *)Image
;
1036 unsigned int relItem
= ReloTable
[i
+2];
1038 if (relItem
>= oldCaLen
) {
1039 relItem
= relItem
-oldCaLen
+caLen
;
1040 ReloTable
[i
+2] = relItem
;
1042 relAddr
= (unsigned int *)(&cImage
[relItem
]);
1043 origVal
= *relAddr
-imgBase
;
1044 if (origVal
>= oldCaLen
) {
1045 *relAddr
= (unsigned int)Image
+origVal
-oldCaLen
+caLen
;
1047 *relAddr
= (unsigned int)Image
+origVal
;
1054 /* Jump to the start of the image. */
1055 typedef void (*GoForth
) (int argc
, char **argv
);
1058 static void startImage (int argc
, char **argv
) {
1059 GoForth goForth
= (GoForth
)Image
[HA_BOOT_CODE
];
1061 goForth(argc
, argv
);
1065 /* Free all allocated space. */
1066 #define DELETE(x) if (x) { free(x); x=NULL; }
1068 static void freeImage (void) {
1071 DELETE(ForthCallStack
);
1072 DELETE(ForthDataStack
);
1076 static int idFound (int fi
, unsigned int offs
) {
1077 unsigned char buf
[HEADER_ID_LEN
];
1079 lseek(fi
, offs
, SEEK_SET
);
1080 read(fi
, buf
, HEADER_ID_LEN
);
1081 for (unsigned int i
= 0; i
< HEADER_ID_LEN
; ++i
) if (buf
[i
] != (headerID
[i
]|0x80)) return 0;
1086 static int findImageHeader (int fi
, unsigned int *offs
) {
1087 unsigned int len
= lseek(fi
, 0, SEEK_END
);
1090 for (unsigned int i
= 0; i
< len
; ++i
) {
1091 if (idFound(fi
, i
)) {
1100 /* The function needs no return value, because it does not return, if it is
1101 successful. Otherwise you may try to run a different image. */
1102 static void runImage (const char *fileName
, int argc
, char **argv
) {
1103 /* we want to open a binary file, therefore we use handles, not FILEs,
1104 because some systems (e.g. NeXTStep 3.1 for Intel 386) can't open binary
1105 FILES, only binary handles. */
1107 unsigned imageOk
, offs
;
1111 printf("Trying image file '%s': ", fileName
);
1114 inFile
= open(fileName
, O_RDONLY
);
1116 /* some error occured; tell what happened and return */
1118 printf("%s\n", strerror(errno
));
1123 if (findImageHeader(inFile
, &offs
)) {
1124 if (readImage(inFile
, offs
)) imageOk
= 1;
1125 else if (goobers
) printf("Error loading image.\n");
1126 } else if (goobers
) printf("Contains no image.\n");
1131 printf("Image started.\n");
1133 /* this function never returns */
1134 startImage(argc
, argv
);
1141 static void removeOptions (int *argc
, char **argv
, int pos
, int cnt
) {
1142 if (pos
+cnt
>= *argc
) {
1145 for (int f
= pos
+cnt
; f
< *argc
; ++f
) argv
[f
-cnt
] = argv
[f
];
1151 static void processOptions (int *argc
, char **argv
) {
1152 for (int i
= 1; i
< *argc
; ++i
) {
1153 if (strcmp(argv
[i
], "-m") == 0) {
1155 MemorySize
= (atoi(argv
[i
+1])+3)&~3;
1156 removeOptions(argc
, argv
, i
, 2);
1159 printf("Memory size overrride: %d bytes\n", MemorySize
);
1162 } else if (strcmp(argv
[i
], "-goobers") == 0) {
1164 removeOptions(argc
, argv
, i
, 1);
1173 /*================================main program================================*/
1174 int main (int argc
, char **argv
) {
1175 char buf
[4096]; // this should be enough for everyone
1177 processOptions(&argc
, argv
);
1178 /* Try to find an image in this program. */
1179 memset(buf
, 0, sizeof(buf
));
1180 if (readlink("/proc/self/exe", buf
, sizeof(buf
)-1) < 0) {
1181 runImage(argv
[0], argc
, argv
);
1183 runImage(buf
, argc
, argv
);
1185 strcpy(buf
, INSTALL_BIN_DIR
);
1186 strcat(buf
, argv
[0]);
1187 runImage(buf
, argc
, argv
);
1188 runImage("flk.flk", argc
, argv
);
1189 runImage(INSTALL_DIR
"default.flk", argc
, argv
);
1190 /* No image could be found. This must be a User-too-stupid error. */
1192 printf("I could not load any image. This is all your fault.\n");