home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 6 / FreshFish_September1994.bin / gnu / lib / crt0.c < prev    next >
C/C++ Source or Header  |  1993-11-27  |  8KB  |  314 lines

  1. /* revamped version by Loren J. Rittle. Thanks Loren !! */
  2.  
  3. /* I guess I should start to put my sources into RCS........ */
  4.  
  5. #include <exec/types.h>
  6. #include <exec/libraries.h>
  7. #include <exec/execbase.h>
  8. #include <inline/exec.h>
  9. #include <libraries/dosextens.h>
  10. #include <limits.h>
  11.  
  12. #include <sys/syscall.h>
  13. #ifdef BASECRT0
  14. #include <sys/exec.h>
  15. #endif /* BASECRT0 */
  16.  
  17. /* get the current revision number. Version control is automatically done by
  18.  * OpenLibrary(), I just have to check the revision number 
  19.  */
  20. #include "../library/version.h"
  21.  
  22. #undef DEBUG
  23. #ifdef DEBUG
  24. #define DP(a) kprintf a
  25. static int inline __geta4() {int res;asm ("movel a4,%0" : "=g" (res));return res;}
  26. #else
  27. #define DP(a)
  28. #endif
  29.  
  30. #define MSTRING(x) STRING(x)
  31. #define STRING(x) #x
  32.  
  33. struct Library *ixemulbase;
  34.  
  35. static int start_stdio(int, char **, char **);
  36.  
  37. /*
  38.  * Have to take care.. I may not use any library functions in this file,
  39.  * since they are exactly then used, when the library itself couldn't be
  40.  * opened...
  41.  */
  42.  
  43. extern int main();
  44. extern int expand_cmd_line;
  45. extern char *default_wb_window;
  46. extern int errno;
  47. extern char **environ;
  48. extern char *_ctype_;
  49. extern int sys_nerr;
  50. extern struct Library *SysBase, *DOSBase;
  51. extern struct __sFILE **__sF;
  52. static int ENTRY();
  53. static int exec_entry();
  54.  
  55. asm("
  56.     .text
  57.  
  58.     jmp    pc@(_ENTRY-.+2)    | by default jump to normal AmigaDOS startup
  59.  
  60.     | this is a struct exec, for now only OMAGIC is supported
  61.     .globl    exec
  62. exec:
  63.     .word    ___machtype    | a_mid
  64.     .word    0407        | a_magic = OMAGIC
  65.     .long    ___text_size    | a_text
  66.     .long    ___data_size    | a_data
  67.     .long    ___bss_size    | a_bss
  68.     .long    0        | a_syms
  69.     .long    _exec_entry    | a_entry
  70.     .long    0        | a_trsize
  71.     .long    0        | a_drsize
  72.  
  73.     | word alignement is guaranteed
  74. ");
  75.  
  76. #ifdef BASECRT0
  77. extern int __datadata_relocs();
  78. extern int __data_size, __bss_size;
  79.  
  80. #ifdef RCRT0
  81. /* have to do this this way, or it is done base-relative.. */
  82. static inline int dbsize() 
  83. {
  84.   int res;
  85.   asm ("movel #___data_size,%0; addl #___bss_size,%0" : "=r" (res));
  86.   return res;
  87. }
  88.  
  89. static void inline
  90. ix_resident (void *base, int num, int a4, int size, void *relocs)
  91. {
  92.   typedef void (*func)(int, int, int, void *);
  93.  
  94.   ((func)((int)base - 6*(SYS_ix_resident + 4))) (num, a4, size, relocs);
  95. }
  96.  
  97. #else
  98. static void inline
  99. ix_resident (void *base, int num, int a4)
  100. {
  101.   typedef void (*func)(int, int);
  102.  
  103.   ((func)((int)base - 6*(SYS_ix_resident + 4))) (num, a4);
  104. }
  105. #endif
  106. #endif /* BASECRT0 */
  107.  
  108. static int
  109. exec_entry (struct Library *ixembase, int argc, char *argv[], char *env[])
  110. {
  111. #ifdef BASECRT0
  112.   register int a4;
  113.   /* needed, so that data can be accessed. ix_resident might change this
  114.      again afterwards */
  115.   asm volatile ("lea    ___a4_init,a4" : "=r" (a4) : "0" (a4));
  116.   asm volatile ("movel    a4,%0" : "=r" (a4) : "0" (a4));
  117.  
  118. #ifdef RCRT0
  119.   ix_resident (ixembase, 4, a4, dbsize(), __datadata_relocs);
  120. #else
  121.   ix_resident (ixembase, 2, a4);
  122. #endif
  123. #endif /* BASECRT0 */
  124.   ixemulbase = ixembase;
  125.   return ix_exec_entry (argc, argv, env, &errno, start_stdio);
  126. }
  127.  
  128. /* this thing is best done with sprintf else, but it has to work without the
  129.  * library as well ;-(
  130.  */
  131. __inline static char *
  132. itoa (int num)
  133. {
  134.   short snum = num;
  135.  
  136.   /* how large can a long get...?? */
  137.   /* Answer (by ljr): best method to use (in terms of portability)
  138.      involves number theory.  The exact number of decimal digits
  139.      needed to store a given number of binary digits is
  140.  
  141.     ceiling ( number_of_binary_digits * log(2) / log(10) )
  142.      or
  143.     ceiling ( number_of_binary_digits * 0.301029996 )
  144.  
  145.      Since sizeof evaluates to the number of bytes a given type takes 
  146.      instead of the number of bits, we need to multiply sizeof (type) by
  147.      CHAR_BIT to obtain the number of bits.  Since an array size specifier
  148.      needs to be integer type, we multiply by 302 and divide by 1000 instead
  149.      of multiplying by 0.301029996.  Finally, we add 1 for the null terminator
  150.      and 1 because we want the ceiling of the function instead of the floor.
  151.      Funny thing about this whole affair is that you really wanted to know
  152.      the size a short could expand to be and not a long...  :-) I know
  153.      comments get out of date, etc.  The nice thing about this method is
  154.      that the size of the array is picked at compile time based upon the
  155.      number of bytes really needed by the local C implementation. */
  156.   static char buf[sizeof snum * CHAR_BIT * 302 / 1000 + 1 + 1];
  157.   char *cp;
  158.   
  159.   buf[sizeof buf - 1] = 0;
  160.   for (cp = &buf[sizeof buf - 1]; snum; snum /= 10) 
  161.     *--cp = (snum % 10) + '0';
  162.  
  163.   return cp;
  164. }
  165.  
  166. __inline static char *
  167. pstrcpy (char *start, char *arg)
  168. {
  169.   while (*start++=*arg++) ;
  170.   return start-1;
  171. }
  172.  
  173. __inline static char *
  174. build_warn (char *t1, int num1)
  175. {
  176.   static char buf[255];
  177.   char *cp;
  178.   
  179.   cp = pstrcpy (buf, t1);
  180.   cp = pstrcpy (cp, itoa (num1));
  181.  
  182.   return buf;
  183. }
  184.  
  185. static int
  186. ENTRY (void)
  187. {
  188.   register unsigned char *rega0  asm("a0");
  189.   register unsigned long  regd0  asm("d0");
  190. #ifdef BASECRT0
  191.   register int a4;
  192. #endif /* BASECRT0 */
  193.  
  194.   UBYTE *aline = rega0;
  195.   ULONG alen = regd0;
  196. #ifdef BASECRT0
  197.   struct Library *ibase;
  198.  
  199.   /* needed, so that data can be accessed. ix_resident() might change this
  200.      again afterwards */
  201.   asm volatile ("lea    ___a4_init,a4" : "=r" (a4) : "0" (a4));
  202.   asm volatile ("movel a4,%0" : "=r" (a4) : "0" (a4));
  203. #endif /* BASECRT0 */
  204.  
  205. #ifndef BASECRT0
  206.   ixemulbase = OpenLibrary ("ixemul.library", IX_VERSION);
  207.   if (ixemulbase)
  208. #else /* BASECRT0 */
  209. DP(("ENTRY: a4 = $%lx\n", __geta4()));
  210.  
  211.   ibase = OpenLibrary ("ixemul.library", IX_VERSION);
  212.   if (ibase)
  213. #endif /* BASECRT0 */
  214.     {
  215.       int res;
  216.  
  217.       /* just warn, in case the user tries to run program which might require
  218.        * more functions than are currently available under this revision. */
  219. #ifndef BASECRT0
  220.       if (ixemulbase->lib_Version == IX_VERSION &&
  221.       ixemulbase->lib_Revision < IX_REVISION)
  222. #else /* BASECRT0 */
  223.       if (ibase->lib_Version == IX_VERSION &&
  224.       ibase->lib_Revision < IX_REVISION)
  225. #endif /* BASECRT0 */
  226.     /* don't need to block signals, they are blocked until after 
  227.          * ix_startup() in current releases */
  228.     __request_msg (build_warn ("ixemul.library warning: needed revision "
  229.                      MSTRING (IX_REVISION) ", current revision ",
  230. #ifndef BASECRT0
  231.                             ixemulbase->lib_Revision), "Continue");
  232. #else /* BASECRT0 */
  233.                             ibase->lib_Revision), "Continue");
  234.  
  235. #ifdef RCRT0
  236.       ix_resident (ibase, 4, a4, dbsize(), __datadata_relocs);
  237. #else
  238.       ix_resident (ibase, 2, a4);
  239. #endif
  240.  
  241. DP(("ix_resident: a4 = $%lx\n", __geta4()));
  242. #endif /* BASECRT0 */
  243.  
  244. #ifdef BASECRT0
  245.       ixemulbase = ibase;
  246. #endif /* BASECRT0 */
  247.  
  248.       res = ix_startup (aline, alen, 
  249.                 expand_cmd_line, default_wb_window, start_stdio, &errno);
  250.  
  251.       CloseLibrary (ixemulbase);
  252.  
  253.       return res;
  254.     }
  255.   else
  256.     {
  257.       struct Process *me = (struct Process *)((*(struct ExecBase **)4)->ThisTask);
  258.  
  259.       __request_msg ("Need at least version " MSTRING (IX_VERSION)
  260.              " of ixemul.library.", "Abort");
  261.       
  262.       /* quickly deal with the WB startup message, as the library couldn't do
  263.        * this for us. Nothing at all is done that isn't necessary to just shutup
  264.        * workbench..*/
  265.       if (! me->pr_CLI)
  266.         {
  267.       Forbid (); 
  268.       ReplyMsg ((WaitPort (& me->pr_MsgPort), GetMsg (& me->pr_MsgPort)));
  269.     }
  270.       
  271.       return 20;
  272.     }
  273. }
  274.  
  275. int
  276. start_stdio (int argc, char **argv, char **env)
  277. {
  278.   int res;
  279. #ifndef BASECRT0
  280.   extern void etext ();
  281.   extern void _mcleanup ();
  282. #else /* BASECRT0 */
  283.  
  284. DP(("start_stdio1: a4 = $%lx\n", __geta4()));
  285. #endif /* BASECRT0 */
  286.  
  287.   /* more to follow ;-) */
  288.   ix_get_vars2 (6, &_ctype_, &sys_nerr, &SysBase, &DOSBase, &__sF, &environ);
  289.   environ = env;
  290.  
  291. #ifndef BASECRT0
  292. #ifdef MCRT0
  293.   atexit(_mcleanup);
  294.   monstartup(start_stdio, etext);
  295. #endif
  296. #endif /* not BASECRT0 */
  297.  
  298.   res = main (argc, argv, env);
  299.   return res;
  300. }
  301.  
  302. #ifndef BASECRT0
  303. #ifdef CRT0
  304. /*
  305.  * null mcount and moncontrol,
  306.  * just in case some routine is compiled for profiling
  307.  */
  308. asm(".globl mcount");
  309. asm(".globl _moncontrol");
  310. asm("_moncontrol:");
  311. asm("mcount: rts");
  312. #endif CRT0
  313. #endif /* not BASECRT0 */
  314.