Avoid leaving temporary batch files in the temporary directory.
[make.git] / load.c
blob076dd30e0e6e9c50f64806393df6ea1685c9548e
1 /* Loading dynamic objects for GNU Make.
2 Copyright (C) 2012 Free Software Foundation, Inc.
3 This file is part of GNU Make.
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
8 version.
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along with
15 this program. If not, see <http://www.gnu.org/licenses/>. */
17 #include "make.h"
19 #if MAKE_LOAD
21 #include <string.h>
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <dlfcn.h>
25 #include <errno.h>
27 #define SYMBOL_EXTENSION "_gmake_setup"
29 static void *global_dl = NULL;
31 #include "debug.h"
32 #include "filedef.h"
33 #include "variable.h"
35 static int
36 init_symbol (const struct floc *flocp, const char *ldname, load_func_t symp)
38 int r;
39 const char *p;
40 int nmlen = strlen (ldname);
41 char *loaded = allocated_variable_expand("$(.LOADED)");
43 /* If it's already been loaded don't do it again. */
44 p = strstr (loaded, ldname);
45 r = p && (p==loaded || p[-1]==' ') && (p[nmlen]=='\0' || p[nmlen]==' ');
46 free (loaded);
47 if (r)
48 return 1;
50 /* Now invoke the symbol. */
51 r = (*symp) (flocp);
53 /* If it succeeded, add the symbol to the loaded variable. */
54 if (r > 0)
55 do_variable_definition (flocp, ".LOADED", ldname, o_default, f_append, 0);
57 return r;
60 int
61 load_file (const struct floc *flocp, const char *ldname, int noerror)
63 load_func_t symp;
64 const char *fp;
65 char *symname = NULL;
66 char *new = alloca (strlen (ldname) + CSTRLEN (SYMBOL_EXTENSION) + 1);
68 if (! global_dl)
70 global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL);
71 if (! global_dl)
72 fatal (flocp, _("Failed to open global symbol table: %s"), dlerror());
75 /* If a symbol name was provided, use it. */
76 fp = strchr (ldname, '(');
77 if (fp)
79 const char *ep;
81 /* If there's an open paren, see if there's a close paren: if so use
82 that as the symbol name. We can't have whitespace: it would have
83 been chopped up before this function is called. */
84 ep = strchr (fp+1, ')');
85 if (ep && ep[1] == '\0')
87 int l = fp - ldname;;
89 ++fp;
90 if (fp == ep)
91 fatal (flocp, _("Empty symbol name for load: %s"), ldname);
93 /* Make a copy of the ldname part. */
94 memcpy (new, ldname, l);
95 new[l] = '\0';
96 ldname = new;
98 /* Make a copy of the symbol name part. */
99 symname = new + l + 1;
100 memcpy (symname, fp, ep - fp);
101 symname[ep - fp] = '\0';
105 /* If we didn't find a symbol name yet, construct it from the ldname. */
106 if (! symname)
108 char *p = new;
110 fp = strrchr (ldname, '/');
111 if (!fp)
112 fp = ldname;
113 else
114 ++fp;
115 while (isalnum (*fp) || *fp == '_')
116 *(p++) = *(fp++);
117 strcpy (p, SYMBOL_EXTENSION);
118 symname = new;
121 DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, ldname));
123 /* See if it's already defined. */
124 symp = (load_func_t) dlsym (global_dl, symname);
125 if (! symp) {
126 void *dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
127 if (! dlp)
129 if (noerror)
130 DB (DB_BASIC, ("%s", dlerror()));
131 else
132 error (flocp, "%s", dlerror());
133 return 0;
136 symp = dlsym (dlp, symname);
137 if (! symp)
138 fatal (flocp, _("Failed to load symbol %s from %s: %s"),
139 symname, ldname, dlerror());
142 /* Invoke the symbol to initialize the loaded object. */
143 return init_symbol(flocp, ldname, symp);
146 #else
149 load_file (const struct floc *flocp, const char *ldname, int noerror)
151 if (! noerror)
152 fatal (flocp, _("The 'load' operation is not supported on this platform."));
154 return 0;
157 #endif /* MAKE_LOAD */