00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "conf/conf.h"
00027
00028
00029 #include <cctype>
00030 #include <cstring>
00031 #include <iostream>
00032
00033
00034 #include "include/config.h"
00035 #include "io/mappedFile.h"
00036 #include "Common/util.h"
00037 #include "conf/conf_bool.h"
00038
00039 using namespace std;
00040 using namespace IXE::io;
00041
00042 namespace IXE {
00043
00044 int Configuration::current_config_file_line_no = 0;
00045
00046 conf<bool> VerboseConfig("VerboseConfig", false);
00047
00048
00063
00064
00065 Configuration::Map& Configuration::variables()
00066 {
00067 static Map m;
00068 return m;
00069 }
00070
00071 void Configuration::insert(Configuration::Item* var)
00072 {
00073 variables()[var->name()] = var;
00074 }
00075
00076
00077
00078 void Configuration::load(char const* file_name)
00079 {
00080 try {
00081 mappedFile conf_file(file_name);
00082
00083 register int line_no = 0;
00084 register mappedFile::const_iterator c = conf_file.begin(), nl = c;
00085
00086 while (c != conf_file.end() && nl != conf_file.end()) {
00087 if (!(nl = ::strchr(c, '\n')))
00088
00089
00090
00091
00092 break;
00093 ++line_no;
00094
00095
00096
00097
00098
00099 while (c != nl && isspace((unsigned char)*c))
00100 ++c;
00101 if (c == nl || *c == '#')
00102 c = nl + 1;
00103 else if (c != nl) {
00104
00105
00106
00107 parseLine(c, line_no);
00108 }
00109 }
00110 } catch (MmapError&) {
00111 if (!::strcmp(file_name, ConfigFileDefault))
00112
00113
00114
00115
00116
00117 error() << "could not read configuration from \""
00118 << file_name << '"' << endl;
00119 }
00120 }
00121
00122 void Configuration::load(istream& is, Map* vars, char const* close)
00123 {
00124 int line_no = 0;
00125 string line;
00126 while (getline(is, line)) {
00127 ++line_no;
00128 if (line == close)
00129 return;
00130
00131 while (line[line.size() - 1] == '\\') {
00132 line[line.size() - 1] = '\n';
00133 string cont;
00134 if (getline(is, cont))
00135 line += cont;
00136 }
00137 char const* c = line.c_str();
00138 char const* end = c + line.size();
00139
00140 while (c != end && isspace((unsigned char)*c))
00141 ++c;
00142
00143 if (*c != '#') {
00144
00145
00146 parseLine(c, line_no, vars);
00147 }
00148 }
00149 }
00150
00151 static int count_lines(char const* start, char const* end)
00152 {
00153 int count = 0;
00154 while ((start = ::strchr(start, '\n')) && start < end) {
00155 start++;
00156 count++;
00157 }
00158 return count;
00159 }
00160
00161 static inline void SKIP_EOL(char const*& x)
00162 {
00163 if (x[0] == '\r') {
00164 ++x;
00165 if (x[0] == '\n') ++x;
00166 } else if (x[0] == '\n') {
00167 ++x;
00168 if (x[0] == '\r') ++x;
00169 }
00170 }
00171
00172
00173 #define EOL(x) ((x)[0] == '\n' || (x)[0] == '\r' && (x)[1] == '\n')
00174 #define SKIP_EOL(x) {if ((x)[0] == '\r') ++(x); ++(x);}
00175 char const* next_token_line(char const*& ptr, const char* sep, char esc)
00176 {
00177
00178
00179 while (*ptr) {
00180 if (*ptr == esc) {
00181 ++ptr;
00182 if (EOL(ptr+1)) {
00183 SKIP_EOL(ptr);
00184 } else if (*ptr)
00185 ++ptr;
00186 } else if (EOL(ptr))
00187 return 0;
00188 else if (strchr(sep, *ptr))
00189 ++ptr;
00190 else
00191 break;
00192 }
00193
00194 if (*ptr) {
00195
00196 char const* start = ptr++;
00197
00198
00199
00200 while (*ptr && !EOL(ptr)) {
00201 if (*ptr == esc) {
00202 ++ptr;
00203 if (*ptr)
00204 ++ptr;
00205 } else if (strchr(sep, *ptr))
00206 break;
00207 else
00208 ++ptr;
00209 }
00210 if (ptr == start)
00211 return 0;
00212 return start;
00213 }
00214
00215
00216 return 0;
00217 }
00218
00219
00220
00221 void Configuration::parseLine(char const*& line, int& line_no, Map* params)
00222 {
00223 current_config_file_line_no = line_no;
00224 char const* varstart = next_token_line(line, " \r\t");
00225 char var[256];
00226 int len = line - varstart;
00227 ::strncpy(var, varstart, len);
00228 var[len] = '\0';
00229 Map vars = (params == 0) ? variables() : *params;
00230 Map::const_iterator const v = vars.find(var);
00231 if (v == vars.end()) {
00232 if (VerboseConfig)
00233 warning() << '"' << line << "\" in config. file unrecognized; ignored\n";
00234 } else {
00235
00236
00237
00238
00239 while (*line && line[0] != '\n' && isspace((unsigned char)*line))
00240 ++line;
00241 char const* start = line;
00242 if (line[0] != '\n')
00243 v->second->parseValue(line);
00244 line_no += count_lines(start, line);
00245
00246 char const* endline = ::strpbrk(line, "\n\r");
00247 if (endline) {
00248 line = endline;
00249 SKIP_EOL(line);
00250 }
00251 }
00252 }
00253
00254
00255
00256 void Configuration::reset()
00257 {
00258 TRANSFORM_EACH(Configuration::Map, Configuration::variables(), v)
00259 v->second->reset();
00260 }
00261
00262
00263
00264 ostream& Configuration::msg(ostream& o, char const* label)
00265 {
00266 if (current_config_file_line_no) {
00267 o << "config file line " << current_config_file_line_no;
00268 current_config_file_line_no = 0;
00269 }
00270 return o << ": " << label << ": ";
00271 }
00272
00273 }