00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <string.h>
00033 #include <ctype.h>
00034 #include <stdio.h>
00035 #include "InfoStream.h"
00036 #include "ConfigList.h"
00037 #include "common.h"
00038
00039 #include "strlib.h"
00040
00041
00042
00043 ConfigList::ConfigListNode *ConfigList::find_key_word(const char *key) const
00044 {
00045 ConfigListNode *tmp;
00046 for (tmp=theList; tmp!= NULL; tmp = tmp -> next) {
00047 if (!strcasecmp(tmp->name, key))
00048 return tmp;
00049 }
00050 return NULL;
00051 }
00052
00053
00054
00055
00056
00057
00058
00059 void ConfigList::add_element(const char *s1, int len1, const char *s2, int len2)
00060 {
00061 char *temps = new char[len1 + 1];
00062 if ( temps == NULL )
00063 {
00064 NAMD_die("new failed in ConfigList::add_element");
00065 }
00066 #ifndef NAMD_NO_STDOUT_FLUSH
00067 fflush(stdout);
00068 #endif
00069 strncpy(temps, s1, len1);
00070 temps[len1] = 0;
00071 ConfigListNode *tmpList;
00072
00073 tmpList = find_key_word( temps);
00074 if (tmpList == NULL ) {
00075 tmpList = new ConfigListNode( theList, temps, NULL);
00076 if ( tmpList == NULL )
00077 {
00078 NAMD_die("new failed in ConfigList::add_element");
00079 }
00080
00081 theList = tmpList;
00082 }
00083
00084 if (len1 < len2) {
00085 delete [] temps;
00086 temps = new char[len2 + 1];
00087 if ( temps == NULL )
00088 {
00089 NAMD_die("new failed in ConfigList::add_element");
00090 }
00091 }
00092 strncpy(temps, s2, len2);
00093 temps[len2] = 0;
00094
00095 StringList *newStrList = new StringList(temps);
00096 if ( newStrList == NULL )
00097 {
00098 NAMD_die("new failed in ConfigList::add_element");
00099 }
00100 newStrList -> next = NULL;
00101 if (tmpList -> data == NULL) {
00102 tmpList -> data = newStrList;
00103 } else {
00104 StringList *tmpStrList = tmpList -> data;
00105 while (tmpStrList -> next != NULL)
00106 tmpStrList = tmpStrList -> next;
00107 tmpStrList -> next = newStrList;
00108 }
00109
00110 delete [] temps;
00111 }
00112
00113
00114
00115
00116 ConfigList::ConfigList(void)
00117 {
00118 isokay = TRUE;
00119 theList = NULL;
00120 }
00121
00122
00123
00124 struct FileStack {
00125 FILE *file;
00126 int linenumber;
00127 char *filename;
00128 FileStack *next;
00129 };
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 ConfigList::ConfigList(const char *filename_in)
00146 {
00147 char *filename = new char[strlen(filename_in)+1];
00148 strcpy(filename,filename_in);
00149 FileStack *fileStack = 0;
00150 FILE *infile;
00151
00152 isokay = FALSE;
00153 theList = NULL;
00154 int linenumber = 0;
00155
00156 if (!strcmp(filename,"-")) {
00157 infile = stdin;
00158 } else {
00159 if ( (infile = Fopen(filename, "r")) == NULL ) {
00160 iout << iWARN << "Unable to open configuration file '"
00161 << filename << "'.\n" << endi;
00162 isokay = FALSE;
00163 return;
00164 }
00165 }
00166 isokay = TRUE;
00167
00168
00169 char buf[1000];
00170 char *namestart, *nameend, *datastart, *dataend;
00171 char *s;
00172 int spacecount;
00173 int fileok;
00174 while ((fileok = ! ! fgets(buf, 999, infile)) || fileStack) {
00175 if ( fileStack && ! fileok ) {
00176 delete [] filename;
00177 filename = fileStack->filename;
00178 linenumber = fileStack->linenumber;
00179 infile = fileStack->file;
00180 FileStack *delStack = fileStack;
00181 fileStack = fileStack->next;
00182 delete delStack;
00183 continue;
00184 }
00185 linenumber ++;
00186 namestart = nameend = datastart = dataend = NULL;
00187 spacecount = 0;
00188
00189 for (s = buf; *s && *s!='\n'; s++) {
00190 if (*s == '#')
00191 break;
00192 if ( !isspace(*s) )
00193 dataend = s;
00194 if ( !isspace(*s) && !namestart)
00195 {namestart = s; continue; }
00196 if ( (isspace(*s) || *s == '=') &&
00197 namestart && !nameend)
00198 nameend = s - 1;
00199 if ( !isspace(*s) && !datastart &&
00200 nameend)
00201 if (*s == '=' && spacecount == 0)
00202 {spacecount++; continue; }
00203 else
00204 {datastart = s; continue; }
00205 }
00206 if (*s == '\n')
00207 *s = 0;
00208 else
00209 if (*s != '#') {
00210 iout << iWARN << "Line " << linenumber << " of configuration file "
00211 << filename << " contains more than 999 characters."
00212 << " Excess characters will be ignored.\n" << endi;
00213 } else {
00214 *s = 0;
00215 }
00216
00217
00218
00219
00220 if (!namestart || !nameend || !datastart || !dataend) {
00221 if (!namestart && datastart || namestart && !datastart) {
00222 iout << iWARN << "Couldn't parse line " << linenumber << " in "
00223 << "configuration file " << filename << ". The line was: "
00224 << buf << "\n" << endi;
00225 }
00226 continue;
00227 }
00228
00229 if ( ! strncmp(namestart, "source", nameend-namestart+1) ) {
00230
00231
00232
00233 FileStack *newStack = new FileStack;
00234 newStack->filename = filename;
00235 newStack->linenumber = linenumber;
00236 newStack->file = infile;
00237 newStack->next = fileStack;
00238 fileStack = newStack;
00239
00240
00241 char *cpychar = new char[dataend-datastart+2];
00242 strcpy(cpychar,datastart);
00243 filename = cpychar;
00244
00245
00246 if ( (infile = Fopen(filename, "r")) == NULL ) {
00247 iout << iWARN << "Unable to open file '"
00248 << filename << "' sourced by '"
00249 << fileStack->filename << "' at line "
00250 << fileStack->linenumber << ".\n" << endi;
00251 isokay = FALSE;
00252 return;
00253 }
00254 iout << iINFO << "Sourcing " << filename << "\n" << endi;
00255 isokay = TRUE;
00256 linenumber = 0;
00257
00258 } else if (datastart[0] == '{') {
00259
00260
00261 std::ostringstream alldata;
00262 char newdata[1000];
00263 int found_end = 0;
00264 ++datastart;
00265 int open_brace_count = 1;
00266 char *newline = datastart;
00267 strcat(newline,"\n");
00268
00269 while ( 1 ) {
00270 int i;
00271 int escape_next = 0;
00272 for (i=0; i<1000; i++) {
00273 if (! newline[i]) {
00274 break;
00275 }
00276 if (escape_next) {
00277 escape_next = 0;
00278 continue;
00279 }
00280 if (newline[i] == '\\' && ! escape_next) {
00281 escape_next = 1;
00282 }
00283 if (newline[i] == '{' && ! escape_next) {
00284 ++open_brace_count;
00285 }
00286 if (newline[i] == '}' && ! escape_next) {
00287 if ( ( found_end = ! --open_brace_count ) ) {
00288 newline[i] = 0;
00289 break;
00290 }
00291 }
00292 }
00293 alldata << newline;
00294 if (found_end) break;
00295 newline = newdata;
00296 if ( ! fgets(newdata, 999, infile) ) break;
00297 linenumber ++;
00298 }
00299 std::string alldatastr = alldata.str();
00300 add_element(namestart, nameend-namestart+1, alldatastr.c_str(), alldata.str().length());
00301
00302 if (!found_end) {
00303 *(nameend+1) = 0;
00304 sprintf(newdata, "configuration file ended early while parsing line "
00305 "%d of keyword structure %s", linenumber, namestart);
00306 NAMD_die(newdata);
00307 }
00308 } else {
00309
00310 add_element( namestart, nameend - namestart + 1, datastart,
00311 dataend - datastart + 1 );
00312 }
00313 }
00314
00315 if (strcmp(filename,"-")) {
00316 Fclose(infile);
00317 }
00318 delete [] filename;
00319 }
00320
00321
00322 ConfigList::~ConfigList( void)
00323 {
00324 ConfigListNode *curr=theList, *next=NULL;
00325
00326 while ( curr!=NULL )
00327 {
00328 next = curr -> next;
00329 delete curr;
00330
00331
00332 curr = next;
00333 }
00334
00335 theList = NULL;
00336 }
00337
00338
00339
00340
00341 StringList *ConfigList::find(const char *name) const
00342 {
00343 ConfigListNode *tmpList;
00344 tmpList = find_key_word(name);
00345 if (tmpList != NULL)
00346 return tmpList -> data;
00347 return NULL;
00348 }
00349
00350
00351 #ifdef TEST_CONFIGLIST_C
00352 #include <iostream.h>
00353
00354 main()
00355 {
00356 ConfigList dat("namd.conf");
00357 StringList *strings;
00358 int i;
00359
00360 if (!dat.okay())
00361 NAMD_die("Can't continue - cannot get info from file.");
00362 std::cout << "Searching for: 'fullname'\n";
00363 strings = dat.find("fullname");
00364 if (!strings) {
00365 NAMD_die("Couldn't find fullname.\n");
00366 }
00367 i=0;
00368 while (strings) {
00369 std::cout << i << " = " << strings->data << '\n';
00370 strings = strings -> next;
00371 i++;
00372 }
00373 }
00374
00375 #endif
00376