-module Linker ( linker )
+module Linker ( linkObjects )
where
-foreign import ccall "linker_top_level" linker_top_level :: Int -> IO Int
+import Foreign.C.String
+import Foreign.Ptr
-linker = linker_top_level
+foreign import ccall "linker_top_level_INIT"
+ linker_top_level_INIT :: IO ()
+
+foreign import ccall "linker_top_level_ADD"
+ linker_top_level_ADD :: CString -> IO ()
+
+foreign import ccall "linker_top_level_LINK"
+ linker_top_level_LINK :: IO (Ptr ())
+
+linkObjects :: [String] -> IO (Ptr ())
+linkObjects objs
+ = do linker_top_level_INIT
+ mapM add_obj objs
+ main_addr <- linker_top_level_LINK
+ return main_addr
+ where
+ add_obj :: String -> IO ()
+ add_obj obj_name = withCString obj_name linker_top_level_ADD
* Top-level linker.
*/
+#define N_OBJS 10
+
+static char* object_names[N_OBJS];
+static int n_object_names = 0;
+
+/* Somewhat naff interface resulting from difficulties in
+ marshalling arrays of strings from Haskell to C.
+*/
+void linker_top_level_INIT ( void )
+{
+ n_object_names = 0;
+}
+
+void linker_top_level_ADD ( char* obj_name )
+{
+ if (n_object_names >= N_OBJS) {
+ fprintf(stderr, "linker: linker_top_level_ADD: too many objs");
+ exit(1);
+ }
+ //fprintf(stderr, "ADD %d %s\n", n_object_names, obj_name);
+ object_names[n_object_names++] = strdup(obj_name);
+}
+
/* Load and link a bunch of .o's, and return the address of
'main'. Or NULL if something borks.
*/
-void* linker_top_level ( int n_objs, char** object_names )
+void* linker_top_level_LINK ( void )
{
int i, r;
void* mainp;
initLinker();
- for (i = 0; i < n_objs; i++) {
+ for (i = 0; i < n_object_names; i++) {
+ //fprintf(stderr, "linkloop %d %s\n", i, object_names[i] );
r = loadObj( object_names[i] );
if (r != 1) return NULL;
}