1 /*****************************************************************************\
4 * Author : Chris Koeritz *
6 *******************************************************************************
7 * Copyright (c) 2000-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
15 #include "parser_bits.h"
17 #include <basis/astring.h>
18 #include <basis/environment.h>
19 #include <basis/functions.h>
24 using namespace basis;
27 #define LOG(prf) printf("%s\n", basis::astring(prf).s())
31 parser_bits::line_ending parser_bits::platform_eol()
34 // obviously a unix OS, unless someone's playing games with us.
36 #elif defined(__WIN32__)
40 // pick the unix default if we can't tell.
45 const char *parser_bits::eol_to_chars(line_ending end)
47 static const char *CRLF_AT_END_STRING = "\r\n";
48 static const char *LF_AT_END_STRING = "\n";
49 static const char *NO_ENDING_STRING = "";
52 case CRLF_AT_END: return CRLF_AT_END_STRING;
53 case NO_ENDING: return NO_ENDING_STRING;
54 case LF_AT_END: // fall-through to default.
55 default: return LF_AT_END_STRING;
59 const char *parser_bits::platform_eol_to_chars()
60 { return eol_to_chars(platform_eol()); }
62 bool parser_bits::is_printable_ascii(char to_check)
63 { return (to_check >= 32) && (to_check <= 126); }
65 bool parser_bits::white_space_no_cr(char to_check)
66 { return (to_check == ' ') || (to_check == '\t'); }
68 bool parser_bits::is_eol(char to_check)
69 { return (to_check == '\n') || (to_check == '\r'); }
71 bool parser_bits::white_space(char to_check)
72 { return white_space_no_cr(to_check) || is_eol(to_check); }
74 void parser_bits::translate_CR_for_platform(astring &to_translate)
76 line_ending plat_eol = platform_eol();
77 bool last_was_lf = false;
78 for (int i = 0; i <= to_translate.end(); i++) {
79 if (to_translate[i] == '\r') {
80 if (last_was_lf) continue; // ignore two in a row.
82 } else if (to_translate[i] == '\n') {
84 if (plat_eol != CRLF_AT_END) {
85 // fix it, since there was not supposed to be an LF.
86 to_translate.zap(i - 1, i - 1);
90 if (plat_eol == CRLF_AT_END) {
91 // fix it, since we're missing an LF that we want.
92 to_translate.insert(i, "\r");
98 // not the two power characters.
104 bool parser_bits::is_hexadecimal(char look_at)
106 return range_check(look_at, 'a', 'f')
107 || range_check(look_at, 'A', 'F')
108 || range_check(look_at, '0', '9');
111 bool parser_bits::is_hexadecimal(const char *look_at, int len)
113 for (int i = 0; i < len; i++)
114 if (!is_hexadecimal(look_at[i])) return false;
118 bool parser_bits::is_hexadecimal(const astring &look_at, int len)
119 { return is_hexadecimal(look_at.observe(), len); }
121 bool parser_bits::is_alphanumeric(char look_at)
123 return range_check(look_at, 'a', 'z')
124 || range_check(look_at, 'A', 'Z')
125 || range_check(look_at, '0', '9');
128 bool parser_bits::is_alphanumeric(const char *look_at, int len)
130 for (int i = 0; i < len; i++)
131 if (!is_alphanumeric(look_at[i])) return false;
135 bool parser_bits::is_alphanumeric(const astring &look_at, int len)
136 { return is_alphanumeric(look_at.observe(), len); }
138 bool parser_bits::is_alpha(char look_at)
139 { return range_check(look_at, 'a', 'z') || range_check(look_at, 'A', 'Z'); }
141 bool parser_bits::is_alpha(const char *look_at, int len)
143 for (int i = 0; i < len; i++)
144 if (!is_alpha(look_at[i])) return false;
148 bool parser_bits::is_alpha(const astring &look_at, int len)
149 { return is_alpha(look_at.observe(), len); }
151 bool parser_bits::is_identifier(char look_at)
153 return range_check(look_at, 'a', 'z')
154 || range_check(look_at, 'A', 'Z')
155 || range_check(look_at, '0', '9')
159 bool parser_bits::is_identifier(const char *look_at, int len)
161 if (is_numeric(look_at[0])) return false;
162 for (int i = 0; i < len; i++)
163 if (!is_identifier(look_at[i])) return false;
167 bool parser_bits::is_identifier(const astring &look_at, int len)
168 { return is_identifier(look_at.observe(), len); }
170 bool parser_bits::is_numeric(char look_at)
172 return range_check(look_at, '0', '9') || (look_at == '-');
175 bool parser_bits::is_numeric(const char *look_at, int len)
177 for (int i = 0; i < len; i++) {
178 if (!is_numeric(look_at[i])) return false;
179 if ( (i > 0) && (look_at[i] == '-') ) return false;
184 bool parser_bits::is_numeric(const astring &look_at, int len)
185 { return is_numeric(look_at.observe(), len); }
187 astring parser_bits::substitute_env_vars(const astring &to_process,
190 astring editing = to_process;
192 //LOG(astring("input to subst env: ") + to_process);
194 int indy; // index of the dollar sign in the string.
196 indy = editing.find('$');
197 if (negative(indy)) break; // all done.
199 for (q = indy + 1; q < editing.length(); q++) {
200 if (!parser_bits::is_identifier(editing[q]))
201 break; // done getting variable name.
204 // we caught something in our environment variable trap...
205 astring var_name = editing.substring(indy + 1, q - 1);
206 //LOG(astring("var name ") + var_name);
207 astring value_found = environment::get(var_name);
208 //LOG(astring("val found ") + value_found);
209 if (value_found.t()) {
210 editing.zap(indy, q - 1);
211 editing.insert(indy, value_found);
214 // that lookup failed. let's mark it.
216 // simple replacement, shows variables that failed.
218 // replace it with blankness.
219 editing.zap(indy, q - 1);
223 // well, we didn't see a valid variable name, but we don't want to leave
224 // the dollar sign in there.
225 editing[indy] = '!'; // simple replacement, marks where syntax is bad.
230 //LOG(astring("output from subst env: ") + editing);