/* This is a parser for ISC files (named.conf, dhcpd.conf). The parser is using VIEWITEMS to keep all comments and file layout. Those files are very difficult to parse. Unlike common configuration file, where you have line oriented statements, ISC files are free form. Ultimatly, named.conf may be expressed as a single big line. So we are using a trick. We are reworking internally the file into a simpler format: A line oriented one. The strategy is simple. A line ends with either a semi-column, an opening brace or a closing brace. Once we have this canonical format, we can handle the file using simple strategy and do "edit in place", where only known configuration statements are affected by linuxconf. So the strategy goes like this. -We read the file using VIEWITEMS -We reformat it internally -We run another VIEWITEMS on top of that. */ #include #include #include "parsers.h" PUBLIC ISC_PARSER::ISC_PARSER() { tmp[0] = '\0'; } /* Decompose the statements in tmp in multiple logical lines tmp is left with the last incomplete statement. */ PRIVATE void ISC_PARSER::splittmp() { while (true){ char *pt = strchr(tmp,';'); if (pt == NULL){ pt = strchr (tmp,'{'); if (pt == NULL){ pt = strchr (tmp,'}'); } } if (pt != NULL){ pt++; char car = *pt; *pt = '\0'; vi->add(new VIEWITEM(tmp,VIEWITEM_VARIABLE)); // vi.afprintf (stderr,"%s\n",tmp); *pt = car; strcpy (tmp,pt); }else{ break; } } } PUBLIC void ISC_PARSER::addline (const char *line) { strcat (tmp,line); char *pt = strchr(tmp,'#'); if (pt == NULL){ pt = strstr (tmp,"//"); } if (pt != NULL){ char *start = tmp; while (start < pt){ if (!isspace(*start)) break; start++; } if (start == pt){ // Ok, this line is just a comment vi->add(new VIEWITEM(tmp,VIEWITEM_COMMENT)); tmp[0] = '\0'; }else{ // The line has some statements at the start *pt = '\0'; splittmp(); } }else{ pt = str_skip(tmp); if (*pt == '\0'){ vi->add(new VIEWITEM(tmp,VIEWITEM_COMMENT)); }else{ splittmp(); } } } #if 0 PUBLIC const char *ISC_PARSER::getline (bool reset) { return ""; } #endif #ifdef TEST static CONFIG_FILE f_sample ("file.sample",help_nil,CONFIGF_OPTIONAL); int main (int, char *[]) { ISC_PARSER p; VIEWITEMS items (p); items.read (f_sample); for (int i=0; iline.get()); } return 0; } #endif