aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/libdep_plugin.c174
1 files changed, 80 insertions, 94 deletions
diff --git a/ld/libdep_plugin.c b/ld/libdep_plugin.c
index 414f3cf..9cd3d77 100644
--- a/ld/libdep_plugin.c
+++ b/ld/libdep_plugin.c
@@ -132,88 +132,68 @@ get_libdeps (int fd)
return rc;
}
-/* Turn a string into an argvec. */
-static char **
-str2vec (char *in)
+/* Parse arguments in-place as contiguous C-strings
+ and return the number of arguments. */
+
+static int
+parse_libdep (char *str)
{
- char **res;
- char *s, *first, *end;
- char *sq, *dq;
- int i;
-
- end = in + strlen (in);
- s = in;
- while (isspace ((unsigned char) *s)) s++;
- first = s;
-
- i = 1;
- while ((s = strchr (s, ' ')))
- {
- s++;
- i++;
- }
- res = (char **)malloc ((i+1) * sizeof (char *));
- if (!res)
- return res;
-
- i = 0;
- sq = NULL;
- dq = NULL;
- res[0] = first;
- for (s = first; *s; s++)
+ char *src, *dst;
+ char quote;
+ int narg;
+
+ src = dst = str;
+
+ for (; isspace ((unsigned char) *src); ++src)
+ ;
+
+ if (*src == '\0')
+ return 0;
+
+ narg = 1;
+ quote = 0;
+
+ while (*src)
{
- if (*s == '\\')
- {
- memmove (s, s+1, end-s-1);
- end--;
- }
- if (isspace ((unsigned char) *s))
+ if (*src == '\'' || *src == '\"')
{
- if (sq || dq)
- continue;
- *s++ = '\0';
- while (isspace ((unsigned char) *s)) s++;
- if (*s)
- res[++i] = s;
- }
- if (*s == '\'' && !dq)
- {
- if (sq)
+ if (!quote)
+ quote = *src++;
+ else if (*src == quote)
{
- memmove (sq, sq+1, s-sq-1);
- memmove (s-2, s+1, end-s-1);
- end -= 2;
- s--;
- sq = NULL;
+ ++src;
+ quote = 0;
}
else
- {
- sq = s;
- }
+ *dst++ = *src++;
}
- if (*s == '"' && !sq)
+ else if (!quote && isspace ((unsigned char) *src))
{
- if (dq)
- {
- memmove (dq, dq+1, s-dq-1);
- memmove (s-2, s+1, end-s-1);
- end -= 2;
- s--;
- dq = NULL;
- }
- else
- {
- dq = s;
- }
+ ++narg;
+ ++src;
+ *dst++ = '\0';
+ for (; isspace ((unsigned char) *src); ++src);
}
+ else
+ *dst++ = *src++;
}
- res[++i] = NULL;
- return res;
+
+ *dst = '\0';
+
+ if (quote)
+ {
+ TV_MESSAGE (LDPL_WARNING,
+ "libdep syntax error: unterminated quoted string");
+ return 0;
+ }
+
+ return narg;
}
static char *prevfile;
/* Standard plugin API registerable hook. */
+
static enum ld_plugin_status
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
{
@@ -237,8 +217,8 @@ onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
return LDPS_ERR;
/* This hook only gets called on actual object files.
- * We have to examine the archive ourselves, to find
- * our LIBDEPS member. */
+ We have to examine the archive ourselves, to find
+ our LIBDEPS member. */
rv = get_libdeps (file->fd);
if (rv == LDPS_ERR)
return rv;
@@ -256,51 +236,51 @@ onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
}
/* Standard plugin API registerable hook. */
+
static enum ld_plugin_status
onall_symbols_read (void)
{
linerec *lr;
- char **vec;
+ int nargs;
+ char const *arg;
enum ld_plugin_status rv = LDPS_OK;
while ((lr = line_head))
{
line_head = lr->next;
- vec = str2vec (lr->line);
- if (vec)
+ nargs = parse_libdep (lr->line);
+ arg = lr->line;
+
+ int i;
+ for (i = 0; i < nargs; i++, arg = strchr (arg, '\0') + 1)
{
- int i;
- for (i = 0; vec[i]; i++)
+ if (arg[0] != '-')
{
- if (vec[i][0] != '-')
- {
- TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s",
- vec[i]);
- fflush (NULL);
- continue;
- }
- if (vec[i][1] == 'l')
- rv = tv_add_input_library (vec[i]+2);
- else if (vec[i][1] == 'L')
- rv = tv_set_extra_library_path (vec[i]+2);
- else
- {
- TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s",
- vec[i]);
- fflush (NULL);
- }
- if (rv != LDPS_OK)
- break;
+ TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s", arg);
+ fflush (NULL);
+ continue;
}
- free (vec);
+ if (arg[1] == 'l')
+ rv = tv_add_input_library (arg + 2);
+ else if (arg[1] == 'L')
+ rv = tv_set_extra_library_path (arg + 2);
+ else
+ {
+ TV_MESSAGE (LDPL_WARNING, "ignoring libdep argument %s", arg);
+ fflush (NULL);
+ }
+ if (rv != LDPS_OK)
+ break;
}
free (lr);
}
+
line_tail = NULL;
return rv;
}
/* Standard plugin API registerable hook. */
+
static enum ld_plugin_status
oncleanup (void)
{
@@ -309,20 +289,25 @@ oncleanup (void)
free (prevfile);
prevfile = NULL;
}
+
if (line_head)
{
linerec *lr;
+
while ((lr = line_head))
{
line_head = lr->next;
free (lr);
}
+
line_tail = NULL;
}
+
return LDPS_OK;
}
/* Standard plugin API entry point. */
+
enum ld_plugin_status
onload (struct ld_plugin_tv *tv)
{
@@ -351,6 +336,7 @@ onload (struct ld_plugin_tv *tv)
(*tv_register_all_symbols_read) (onall_symbols_read);
(*tv_register_cleanup) (oncleanup);
}
+
fflush (NULL);
return LDPS_OK;
}