+
+/* Look for the program formed by concatenating PROG_NAME and the
+ string running from PREFIX to END_PREFIX. If the concatenated
+ string contains a '/', try appending EXECUTABLE_SUFFIX if it is
+ appropriate. */
+
+static char *
+look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
+{
+ struct stat s;
+ char *cmd;
+
+ cmd = xmalloc (strlen (prefix)
+ + strlen (prog_name)
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ + strlen (EXECUTABLE_SUFFIX)
+#endif
+ + 10);
+ strcpy (cmd, prefix);
+
+ sprintf (cmd + end_prefix, "%s", prog_name);
+
+ if (strchr (cmd, '/') != NULL)
+ {
+ int found;
+
+ found = (stat (cmd, &s) == 0
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
+#endif
+ );
+
+ if (! found)
+ {
+ /* xgettext:c-format */
+ inform (_("Tried file: %s"), cmd);
+ free (cmd);
+ return NULL;
+ }
+ }
+
+ /* xgettext:c-format */
+ inform (_("Using file: %s"), cmd);
+
+ return cmd;
+}
+
+/* Deduce the name of the program we are want to invoke.
+ PROG_NAME is the basic name of the program we want to run,
+ eg "as" or "ld". The catch is that we might want actually
+ run "i386-pe-as" or "ppc-pe-ld".
+
+ If argv[0] contains the full path, then try to find the program
+ in the same place, with and then without a target-like prefix.
+
+ Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
+ deduce_name("as") uses the following search order:
+
+ /usr/local/bin/i586-cygwin32-as
+ /usr/local/bin/as
+ as
+
+ If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
+ name, it'll try without and then with EXECUTABLE_SUFFIX.
+
+ Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
+ as the fallback, but rather return i586-cygwin32-as.
+
+ Oh, and given, argv[0] = dlltool, it'll return "as".
+
+ Returns a dynamically allocated string. */
+
+static char *
+deduce_name (const char *prog_name)
+{
+ char *cmd;
+ char *dash, *slash, *cp;
+
+ dash = NULL;
+ slash = NULL;
+ for (cp = program_name; *cp != '\0'; ++cp)
+ {
+ if (*cp == '-')
+ dash = cp;
+ if (
+#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
+ *cp == ':' || *cp == '\\' ||
+#endif
+ *cp == '/')
+ {
+ slash = cp;
+ dash = NULL;
+ }
+ }
+
+ cmd = NULL;
+
+ if (dash != NULL)
+ {
+ /* First, try looking for a prefixed PROG_NAME in the
+ PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
+ cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
+ }
+
+ if (slash != NULL && cmd == NULL)
+ {
+ /* Next, try looking for a PROG_NAME in the same directory as
+ that of this program. */
+ cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
+ }
+
+ if (cmd == NULL)
+ {
+ /* Just return PROG_NAME as is. */
+ cmd = xstrdup (prog_name);
+ }
+
+ return cmd;
+}
+
+#ifdef DLLTOOL_MCORE_ELF
+typedef struct fname_cache
+{
+ char * filename;
+ struct fname_cache * next;
+}
+fname_cache;
+
+static fname_cache fnames;
+
+static void
+mcore_elf_cache_filename (char * filename)
+{
+ fname_cache * ptr;
+
+ ptr = & fnames;
+
+ while (ptr->next != NULL)
+ ptr = ptr->next;
+
+ ptr->filename = filename;
+ ptr->next = (fname_cache *) malloc (sizeof (fname_cache));
+ if (ptr->next != NULL)
+ ptr->next->next = NULL;
+}
+
+#define MCORE_ELF_TMP_OBJ "mcoreelf.o"
+#define MCORE_ELF_TMP_EXP "mcoreelf.exp"
+#define MCORE_ELF_TMP_LIB "mcoreelf.lib"
+
+static void
+mcore_elf_gen_out_file (void)
+{
+ fname_cache * ptr;
+ dyn_string_t ds;
+
+ /* Step one. Run 'ld -r' on the input object files in order to resolve
+ any internal references and to generate a single .exports section. */
+ ptr = & fnames;
+
+ ds = dyn_string_new (100);
+ dyn_string_append_cstr (ds, "-r ");
+
+ if (mcore_elf_linker_flags != NULL)
+ dyn_string_append_cstr (ds, mcore_elf_linker_flags);
+
+ while (ptr->next != NULL)
+ {
+ dyn_string_append_cstr (ds, ptr->filename);
+ dyn_string_append_cstr (ds, " ");
+
+ ptr = ptr->next;
+ }
+
+ dyn_string_append_cstr (ds, "-o ");
+ dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
+
+ if (mcore_elf_linker == NULL)
+ mcore_elf_linker = deduce_name ("ld");
+
+ run (mcore_elf_linker, ds->s);
+
+ dyn_string_delete (ds);
+
+ /* Step two. Create a .exp file and a .lib file from the temporary file.
+ Do this by recursively invoking dlltool... */
+ ds = dyn_string_new (100);
+
+ dyn_string_append_cstr (ds, "-S ");
+ dyn_string_append_cstr (ds, as_name);
+
+ dyn_string_append_cstr (ds, " -e ");
+ dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
+ dyn_string_append_cstr (ds, " -l ");
+ dyn_string_append_cstr (ds, MCORE_ELF_TMP_LIB);
+ dyn_string_append_cstr (ds, " " );
+ dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
+
+ if (verbose)
+ dyn_string_append_cstr (ds, " -v");
+
+ if (dontdeltemps)
+ {
+ dyn_string_append_cstr (ds, " -n");
+
+ if (dontdeltemps > 1)
+ dyn_string_append_cstr (ds, " -n");
+ }
+
+ /* XXX - FIME: ought to check/copy other command line options as well. */
+ run (program_name, ds->s);
+
+ dyn_string_delete (ds);
+
+ /* Step four. Feed the .exp and object files to ld -shared to create the dll. */
+ ds = dyn_string_new (100);
+
+ dyn_string_append_cstr (ds, "-shared ");
+
+ if (mcore_elf_linker_flags)
+ dyn_string_append_cstr (ds, mcore_elf_linker_flags);
+
+ dyn_string_append_cstr (ds, " ");
+ dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP);
+ dyn_string_append_cstr (ds, " ");
+ dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ);
+ dyn_string_append_cstr (ds, " -o ");
+ dyn_string_append_cstr (ds, mcore_elf_out_file);
+
+ run (mcore_elf_linker, ds->s);
+
+ dyn_string_delete (ds);
+
+ if (dontdeltemps == 0)
+ unlink (MCORE_ELF_TMP_EXP);
+
+ if (dontdeltemps < 2)
+ unlink (MCORE_ELF_TMP_OBJ);
+}
+#endif /* DLLTOOL_MCORE_ELF */