home *** CD-ROM | disk | FTP | other *** search
- /* revamped version by Loren J. Rittle. Thanks Loren !! */
-
- /* I guess I should start to put my sources into RCS........ */
-
- #include <exec/types.h>
- #include <exec/libraries.h>
- #include <exec/execbase.h>
- #include <inline/exec.h>
- #include <libraries/dosextens.h>
- #include <limits.h>
-
- #include <sys/syscall.h>
- #include <sys/exec.h>
-
- /* get the current revision number. Version control is automatically done by
- * OpenLibrary(), I just have to check the revision number
- */
- #include "../library/version.h"
-
- #undef DEBUG
- #ifdef DEBUG
- #define DP(a) kprintf a
- static int inline __geta4() {int res;asm ("movel a4,%0" : "=g" (res));return res;}
- #else
- #define DP(a)
- #endif
-
- #define MSTRING(x) STRING(x)
- #define STRING(x) #x
-
- struct Library *ixemulbase;
-
- static int start_stdio();
-
- /*
- * Have to take care.. I may not use any library functions in this file,
- * since they are exactly then used, when the library itself couldn't be
- * opened...
- */
-
- extern int main();
- extern int expand_cmd_line;
- extern char *default_wb_window;
- extern int errno;
- extern char **environ;
- extern char *_ctype_;
- extern int sys_nerr;
- extern struct Library *SysBase, *DOSBase;
- extern struct __sFILE **__sF;
- static int ENTRY();
- static int exec_entry();
-
- asm("
- .text
-
- jmp pc@(_ENTRY-.+2) | by default jump to normal AmigaDOS startup
-
- | this is a struct exec, for now only OMAGIC is supported
- .globl exec
- exec:
- .word ___machtype | a_mid
- .word 0407 | a_magic = OMAGIC
- | until gld knows about this, the following fields are not filled out.
- | the relocation fields will be used to provide self-relocating programs
- | that are then residentable
- .long ___text_size | a_text
- .long ___data_size | a_data
- .long ___bss_size | a_bss
- .long 0 | a_syms
- .long _exec_entry | a_entry
- .long 0 | a_trsize
- .long 0 | a_drsize
-
- | word alignement is guaranteed
- ");
-
- extern struct exec exec asm ("exec");
- extern int _sdata(), __a4_init(), __datadata_relocs();
- extern int __data_size, __bss_size;
-
- #ifdef RCRT0
- /* have to do this this way, or it is done base-relative.. */
- static inline int dbsize()
- {
- int res;
- asm ("movel #___data_size,%0; addl #___bss_size,%0" : "=r" (res));
- return res;
- }
-
- static void inline
- ix_resident (void *base, int num, int a4, int size, void *relocs)
- {
- typedef void (*func)(int, int, int, void *);
-
- ((func)((int)base - 6*(SYS_ix_resident + 4))) (num, a4, size, relocs);
- }
-
- #else
- static void inline
- ix_resident (void *base, int num, int a4)
- {
- typedef void (*func)(int, int);
-
- ((func)((int)base - 6*(SYS_ix_resident + 4))) (num, a4);
- }
- #endif
-
- static int
- exec_entry (struct Library *ixembase, int argc, char *argv[], char *env[])
- {
- register int a4;
- /* needed, so that data can be accessed. ix_resident might change this
- again afterwards */
- asm volatile ("lea ___a4_init,a4" : "=r" (a4) : "0" (a4));
- asm volatile ("movel a4,%0" : "=r" (a4) : "0" (a4));
-
- #ifdef RCRT0
- ix_resident (ixembase, 4, a4, dbsize(), __datadata_relocs);
- #else
- ix_resident (ixembase, 2, a4);
- #endif
- ixemulbase = ixembase;
- environ = env;
- return ix_exec_entry (argc, argv, env, &errno, start_stdio);
- }
-
- /* this thing is best done with sprintf else, but it has to work without the
- * library as well ;-(
- */
- __inline static char *
- itoa (int num)
- {
- short snum = num;
-
- /* how large can a long get...?? */
- /* Answer (by ljr): best method to use (in terms of portability)
- involves number theory. The exact number of decimal digits
- needed to store a given number of binary digits is
-
- ceiling ( number_of_binary_digits * log(2) / log(10) )
- or
- ceiling ( number_of_binary_digits * 0.301029996 )
-
- Since sizeof evaluates to the number of bytes a given type takes
- instead of the number of bits, we need to multiply sizeof (type) by
- CHAR_BIT to obtain the number of bits. Since an array size specifier
- needs to be integer type, we multiply by 302 and divide by 1000 instead
- of multiplying by 0.301029996. Finally, we add 1 for the null terminator
- and 1 because we want the ceiling of the function instead of the floor.
- Funny thing about this whole affair is that you really wanted to know
- the size a short could expand to be and not a long... :-) I know
- comments get out of date, etc. The nice thing about this method is
- that the size of the array is picked at compile time based upon the
- number of bytes really needed by the local C implementation. */
- static char buf[sizeof snum * CHAR_BIT * 302 / 1000 + 1 + 1];
- char *cp;
-
- buf[sizeof buf - 1] = 0;
- for (cp = &buf[sizeof buf - 1]; snum; snum /= 10)
- *--cp = (snum % 10) + '0';
-
- return cp;
- }
-
- __inline static char *
- pstrcpy (char *start, char *arg)
- {
- while (*start++=*arg++) ;
- return start-1;
- }
-
- __inline static char *
- build_warn (char *t1, int num1)
- {
- static char buf[255];
- char *cp;
-
- cp = pstrcpy (buf, t1);
- cp = pstrcpy (cp, itoa (num1));
-
- return buf;
- }
-
- static int
- ENTRY (void)
- {
- register unsigned char *rega0 asm("a0");
- register unsigned long regd0 asm("d0");
- register int a4;
-
- UBYTE *aline = rega0;
- ULONG alen = regd0;
- struct Library *ibase;
-
- /* needed, so that data can be accessed. ix_resident() might change this
- again afterwards */
- asm volatile ("lea ___a4_init,a4" : "=r" (a4) : "0" (a4));
- asm volatile ("movel a4,%0" : "=r" (a4) : "0" (a4));
-
- DP(("ENTRY: a4 = $%lx\n", __geta4()));
-
- ibase = OpenLibrary ("ixemul.library", IX_VERSION);
- if (ibase)
- {
- int res;
-
- /* just warn, in case the user tries to run program which might require
- * more functions than are currently available under this revision. */
- if (ibase->lib_Version == IX_VERSION &&
- ibase->lib_Revision < IX_REVISION)
- /* don't need to block signals, they are blocked until after
- * ix_startup() in current releases */
- __request_msg (build_warn ("ixemul.library warning: needed revision "
- MSTRING (IX_REVISION) ", current revision ",
- ibase->lib_Revision), "Continue");
-
- #ifdef RCRT0
- ix_resident (ibase, 4, a4, dbsize(), __datadata_relocs);
- #else
- ix_resident (ibase, 2, a4);
- #endif
-
- DP(("ix_resident: a4 = $%lx\n", __geta4()));
-
- ixemulbase = ibase;
-
- res = ix_startup (aline, alen,
- expand_cmd_line, default_wb_window, start_stdio, &errno);
-
- CloseLibrary (ixemulbase);
-
- return res;
- }
- else
- {
- struct Process *me = (struct Process *)((*(struct ExecBase **)4)->ThisTask);
-
- __request_msg ("Need at least version " MSTRING (IX_VERSION)
- " of ixemul.library.", "Abort");
-
- /* quickly deal with the WB startup message, as the library couldn't do
- * this for us. Nothing at all is done that isn't necessary to just shutup
- * workbench..*/
- if (! me->pr_CLI)
- {
- Forbid ();
- ReplyMsg ((WaitPort (& me->pr_MsgPort), GetMsg (& me->pr_MsgPort)));
- }
-
- return 20;
- }
- }
-
- int
- start_stdio (int a1, int a2, int a3)
- {
- int res;
-
- DP(("start_stdio1: a4 = $%lx\n", __geta4()));
-
- /* more to follow ;-) */
- ix_get_vars2 (5, &_ctype_, &sys_nerr, &SysBase, &DOSBase, &__sF);
-
- res = main (a1, a2, a3);
- return res;
- }
-