|
|
00001 #include "lexer.h" 00002 #include "substitute.h" 00003 #include <stdlib.h> 00004 00005 /* 00006 * Copyright (c) 1989 by the Massachusetts Institute of Technology. 00007 * For copying and distribution information, see the file 00008 * "mit-copyright.h". 00009 * 00010 * Modified for jwgc by Daniel Henninger. 00011 */ 00012 00013 #include "mit-copyright.h" 00014 00015 /* 00016 * Internal Routine: 00017 * 00018 * string eat_dollar_sign_stuff(string (*lookup)(string); string *text_ptr) 00019 * Modifies: *text_ptr 00020 * Effects: This routine deals with handling the stuff after a '$' 00021 * for substitute. If *text_ptr starts with a valid 00022 * variable reference (minus the leading '$'), we look up 00023 * the variable using lookup and return its value. 00024 * *text_ptr is also advanced past the variable reference. 00025 * If a '$' starts *text_ptr, *text_ptr is advanced past it & 00026 * "$" returned. (This handles "$$" -> "$") Otherwise, 00027 * "$" is returned and *text_ptr is not advanced. 00028 * The returned string must not be freed. 00029 */ 00030 00031 static string 00032 eat_dollar_sign_stuff(lookup, text_ptr) 00033 string(*lookup) (); 00034 string *text_ptr; /* Input/Output parameter */ 00035 { 00036 char c; 00037 char closing_brace = 0; 00038 char *p = *text_ptr; 00039 char *variable_name_start; 00040 int variable_name_length; 00041 00042 /* 00043 * Handle "$$" -> "$" translation: 00044 */ 00045 c = *p; 00046 if (c == '$') { 00047 *text_ptr = p + 1; 00048 return ("$"); 00049 } 00050 00051 /* 00052 * If opening brace present (i.e., '(' or '{'), skip it and save away 00053 * what closing brace we must see at the end of the variable reference: 00054 */ 00055 if (c == '{') { 00056 closing_brace = '}'; 00057 c = *++p; 00058 } 00059 else if (c == '(') { 00060 closing_brace = ')'; 00061 c = *++p; 00062 } 00063 00064 /* 00065 * Eat {identifier_char}* keeping track of what we ate: 00066 */ 00067 variable_name_start = p; 00068 variable_name_length = 0; 00069 while (c = *p, is_identifier_char(c)) { 00070 p++; 00071 variable_name_length++; 00072 } 00073 00074 /* 00075 * If there was an opening brace, there had better be a comparable 00076 * closing brace. If so, skip it. If not, we have an invalid variable 00077 * reference so return '$' without advancing *text_ptr. 00078 */ 00079 if (closing_brace) { 00080 if (c == closing_brace) 00081 c = *++p; 00082 else 00083 return ("$"); 00084 } 00085 00086 /* 00087 * Zero length variable names are not valid: 00088 */ 00089 if (!variable_name_length) 00090 return ("$"); 00091 00092 /* 00093 * We have a valid variable reference. Advance past it then lookup 00094 * its value and return it: 00095 */ 00096 *text_ptr = p; 00097 if (variable_name_length > MAX_IDENTIFIER_LENGTH) 00098 variable_name_length = MAX_IDENTIFIER_LENGTH; 00099 variable_name_start = string_CreateFromData(variable_name_start, 00100 variable_name_length); 00101 p = lookup(variable_name_start); 00102 free(variable_name_start); 00103 return (p); 00104 } 00105 00106 /* 00107 * string substitute(string (*lookup)(string); string text) 00108 * Effects: returns the result of expanding all variable 00109 * references in text using lookup. Example: 00110 * "test $foo.$bar baz" would be translated to 00111 * "text <foo>.<bar> baz" where "<foo>" is the value of 00112 * lookup("foo") and "<bar>" is the value of lookup("bar"). 00113 * Variables are case sensitive and have the form 00114 * {identifier_char}+ where identifier_char is defined 00115 * in lexer.h by is_identifier_char. $(foo) and 00116 * ${foo} are alternate forms for $foo. In particular, 00117 * ${foo}bar is a reference to foo followed by "bar" while 00118 * $foobar is a reference to foobar. Incomplete variable 00119 * references like $(foo bar are displayed as if they 00120 * were not variable references. To allow quoting, "$$" 00121 * is translated to "$". Only the first 00122 * MAX_IDENTIFIER_LENGTH characters of an identifier are 00123 * significant. The strings returned by lookup are not 00124 * modified in any way or freed. 00125 */ 00126 00127 string 00128 substitute(lookup, text) 00129 string(*lookup) (); 00130 string text; 00131 { 00132 string result_so_far = string_Copy(""); 00133 char *p, *temp; 00134 00135 for (;;) { 00136 /* 00137 * Move [^$]* from start of text to end of result_so_far: 00138 */ 00139 for (p = text; *p && (*p) != '$'; p++); 00140 if (text != p) { 00141 temp = string_CreateFromData(text, p - text); 00142 text = p; 00143 result_so_far = string_Concat2(result_so_far, temp); 00144 free(temp); 00145 } 00146 00147 /* 00148 * If text now empty, exit -- the result is in result_so_far: 00149 */ 00150 if (!*text) 00151 return (result_so_far); 00152 00153 /* 00154 * Otherwise, text begins with a '$'. Eat it then call 00155 * eat_dollar_sign_stuff to process stuff after it. 00156 * Append result to result_so_far, update text, & continue. 00157 */ 00158 text++; 00159 p = eat_dollar_sign_stuff(lookup, &text); 00160 result_so_far = string_Concat2(result_so_far, p); 00161 } 00162 }
Last updated at Tue Dec 18 21:07:42 PST 2007. | This site and project hosted by... |