|
|
/* variable.c: variable expansion. |
|
|
|
|
|
Copyright (C) 1993, 94 Karl Berry. |
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
|
|
it under the terms of the GNU General Public License as published by |
|
|
the Free Software Foundation; either version 2, or (at your option) |
|
|
any later version. |
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
GNU General Public License for more details. |
|
|
|
|
|
You should have received a copy of the GNU General Public License |
|
|
along with this program; if not, write to the Free Software |
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
|
|
|
|
#include <kpathsea/config.h> |
|
|
|
|
|
#include <kpathsea/c-ctype.h> |
|
|
#include <kpathsea/cnf.h> |
|
|
#include <kpathsea/fn.h> |
|
|
#include <kpathsea/variable.h> |
|
|
|
|
|
|
|
|
/* Append the result of value of `var' to EXPANSION, where `var' begins |
|
|
at START and ends at END. If `var' is not set, do not complain. */ |
|
|
|
|
|
static void |
|
|
expand P3C(fn_type *, expansion, const_string, start, const_string, end) |
|
|
{ |
|
|
string value; |
|
|
unsigned len = end - start + 1; |
|
|
string var = xmalloc (len + 1); |
|
|
strncpy (var, start, len); |
|
|
var[len] = 0; |
|
|
|
|
|
/* First check the environment variable. */ |
|
|
value = getenv (var); |
|
|
|
|
|
/* If no envvar, check the config files. */ |
|
|
if (!value) |
|
|
value = kpse_cnf_get (var); |
|
|
|
|
|
if (value) |
|
|
{ |
|
|
value = kpse_var_expand (value); |
|
|
fn_grow (expansion, value, strlen (value)); |
|
|
free (value); |
|
|
} |
|
|
|
|
|
free (var); |
|
|
} |
|
|
|
|
|
/* Can't think of when it would be useful to change these (and the |
|
|
diagnostic messages assume them), but ... */ |
|
|
#ifndef IS_VAR_START /* starts all variable references */ |
|
|
#define IS_VAR_START(c) ((c) == '$') |
|
|
#endif |
|
|
#ifndef IS_VAR_CHAR /* variable name constituent */ |
|
|
#define IS_VAR_CHAR(c) (ISALNUM (c) || (c) == '_') |
|
|
#endif |
|
|
#ifndef IS_VAR_BEGIN_DELIMITER /* start delimited variable name (after $) */ |
|
|
#define IS_VAR_BEGIN_DELIMITER(c) ((c) == '{') |
|
|
#endif |
|
|
#ifndef IS_VAR_END_DELIMITER |
|
|
#define IS_VAR_END_DELIMITER(c) ((c) == '}') |
|
|
#endif |
|
|
|
|
|
|
|
|
/* Maybe we should generalize to allow some or all of the various shell |
|
|
${...} constructs, especially ${var-value}. */ |
|
|
|
|
|
string |
|
|
kpse_var_expand P1C(const_string, src) |
|
|
{ |
|
|
const_string s; |
|
|
string ret; |
|
|
fn_type expansion; |
|
|
expansion = fn_init (); |
|
|
|
|
|
/* Copy everything but variable constructs. */ |
|
|
for (s = src; *s; s++) |
|
|
{ |
|
|
if (IS_VAR_START (*s)) |
|
|
{ |
|
|
s++; |
|
|
|
|
|
/* Three cases: `$VAR', `${VAR}', `$<anything-else>'. */ |
|
|
|
|
|
if (IS_VAR_CHAR (*s)) |
|
|
{ /* $V: collect name constituents, then expand. */ |
|
|
const_string var_end = s; |
|
|
|
|
|
do |
|
|
var_end++; |
|
|
while (IS_VAR_CHAR (*var_end)); |
|
|
|
|
|
var_end--; /* had to go one past */ |
|
|
expand (&expansion, s, var_end); |
|
|
s = var_end; |
|
|
} |
|
|
|
|
|
else if (IS_VAR_BEGIN_DELIMITER (*s)) |
|
|
{ /* ${: scan ahead for matching delimiter, then expand. */ |
|
|
const_string var_end = ++s; |
|
|
|
|
|
while (*var_end && !IS_VAR_END_DELIMITER (*var_end)) |
|
|
var_end++; |
|
|
|
|
|
if (! *var_end) |
|
|
{ |
|
|
WARNING1 ("%s: No matching right brace for ${", src); |
|
|
s = var_end - 1; /* will incr to null at top of loop */ |
|
|
} |
|
|
else |
|
|
{ |
|
|
expand (&expansion, s, var_end - 1); |
|
|
s = var_end; /* will incr past } at top of loop*/ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
else |
|
|
{ /* $<something-else>: error. */ |
|
|
WARNING2 ("%s: Unrecognized variable construct `$%c'", src, *s); |
|
|
/* Just ignore those chars and keep going. */ |
|
|
} |
|
|
} |
|
|
else |
|
|
fn_1grow (&expansion, *s); |
|
|
} |
|
|
fn_1grow (&expansion, 0); |
|
|
|
|
|
ret = FN_STRING (expansion); |
|
|
return ret; |
|
|
} |
|
|
|
|
|
#ifdef TEST |
|
|
|
|
|
static void |
|
|
test_var (string test, string right_answer) |
|
|
{ |
|
|
string result = kpse_var_expand (test); |
|
|
|
|
|
printf ("expansion of `%s'\t=> %s", test, result); |
|
|
if (!STREQ (result, right_answer)) |
|
|
printf (" [should be `%s']", right_answer); |
|
|
putchar ('\n'); |
|
|
} |
|
|
|
|
|
|
|
|
int |
|
|
main () |
|
|
{ |
|
|
test_var ("a", "a"); |
|
|
test_var ("$foo", ""); |
|
|
test_var ("a$foo", "a"); |
|
|
test_var ("$foo a", " a"); |
|
|
test_var ("a$foo b", "a b"); |
|
|
|
|
|
xputenv ("FOO", "foo value"); |
|
|
test_var ("a$FOO", "afoo value"); |
|
|
|
|
|
xputenv ("Dollar", "$"); |
|
|
test_var ("$Dollar a", "$ a"); |
|
|
|
|
|
test_var ("a${FOO}b", "afoo valueb"); |
|
|
test_var ("a${}b", "ab"); |
|
|
|
|
|
test_var ("$$", ""); /* and error */ |
|
|
test_var ("a${oops", "a"); /* and error */ |
|
|
|
|
|
return 0; |
|
|
} |
|
|
|
|
|
#endif /* TEST */ |
|
|
|
|
|
|
|
|
/* |
|
|
Local variables: |
|
|
standalone-compile-command: "gcc -g -I. -I.. -DTEST variable.c kpathsea.a" |
|
|
End: |
|
|
*/
|
|
|
|