1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It is one of the source files comprising zwgc, the Zephyr WindowGram
5 * Created by: Marc Horowitz <marc@athena.mit.edu>
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
14 #if (!defined(lint) && !defined(SABER))
15 static char rcsid_substitute_c[] = "$Id$";
18 #include <zephyr/mit-copyright.h>
21 #include "new_memory.h"
23 #include "substitute.h"
28 * string eat_dollar_sign_stuff(string (*lookup)(string); string *text_ptr)
30 * Effects: This routine deals with handling the stuff after a '$'
31 * for substitute. If *text_ptr starts with a valid
32 * variable reference (minus the leading '$'), we look up
33 * the variable using lookup and return its value.
34 * *text_ptr is also advanced past the variable reference.
35 * If a '$' starts *text_ptr, *text_ptr is advanced past it &
36 * "$" returned. (This handles "$$" -> "$") Otherwise,
37 * "$" is returned and *text_ptr is not advanced.
38 * The returned string must not be freed.
41 static string eat_dollar_sign_stuff(lookup, text_ptr)
43 string *text_ptr; /* Input/Output parameter */
46 char closing_brace = 0;
48 char *variable_name_start;
49 int variable_name_length;
52 * Handle "$$" -> "$" translation:
61 * If opening brace present (i.e., '(' or '{'), skip it and save away
62 * what closing brace we must see at the end of the variable reference:
73 * Eat {identifier_char}* keeping track of what we ate:
75 variable_name_start = p;
76 variable_name_length = 0;
77 while (c = *p, is_identifier_char(c)) {
79 variable_name_length++;
83 * If there was an opening brace, there had better be a comparable
84 * closing brace. If so, skip it. If not, we have an invalid variable
85 * reference so return '$' without advancing *text_ptr.
95 * Zero length variable names are not valid:
97 if (!variable_name_length)
101 * We have a valid variable reference. Advance past it then lookup
102 * its value and return it:
105 if (variable_name_length > MAX_IDENTIFIER_LENGTH)
106 variable_name_length = MAX_IDENTIFIER_LENGTH;
107 variable_name_start = string_CreateFromData(variable_name_start,
108 variable_name_length);
109 p = lookup(variable_name_start);
110 free(variable_name_start);
115 * string substitute(string (*lookup)(string); string text)
116 * Effects: returns the result of expanding all variable
117 * references in text using lookup. Example:
118 * "test $foo.$bar baz" would be translated to
119 * "text <foo>.<bar> baz" where "<foo>" is the value of
120 * lookup("foo") and "<bar>" is the value of lookup("bar").
121 * Variables are case sensitive and have the form
122 * {identifier_char}+ where identifier_char is defined
123 * in lexer.h by is_identifier_char. $(foo) and
124 * ${foo} are alternate forms for $foo. In particular,
125 * ${foo}bar is a reference to foo followed by "bar" while
126 * $foobar is a reference to foobar. Incomplete variable
127 * references like $(foo bar are displayed as if they
128 * were not variable references. To allow quoting, "$$"
129 * is translated to "$". Only the first
130 * MAX_IDENTIFIER_LENGTH characters of an identifier are
131 * significant. The strings returned by lookup are not
132 * modified in any way or freed.
135 string substitute(lookup, text)
139 string result_so_far = string_Copy("");
144 * Move [^$]* from start of text to end of result_so_far:
146 for (p=text; *p && (*p)!='$'; p++) ;
148 temp = string_CreateFromData(text, p-text);
150 result_so_far = string_Concat2(result_so_far, temp);
155 * If text now empty, exit -- the result is in result_so_far:
158 return(result_so_far);
161 * Otherwise, text begins with a '$'. Eat it then call
162 * eat_dollar_sign_stuff to process stuff after it.
163 * Append result to result_so_far, update text, & continue.
166 p = eat_dollar_sign_stuff(lookup, &text);
167 result_so_far = string_Concat2(result_so_far, p);