+ oldstate= cstate;
+ cstate= cstate->upstate;
+ if (cstate) yy_switch_to_buffer(cstate->ybuf);
+ yy_delete_buffer(oldstate->ybuf);
+}
+
+int parse_string(const char *string, const char *descrip, int isinternal) {
+ /* Returns the same things as parser, except that tokv_eof is turned
+ * into 0. *string must be statically allocated or copied, so that
+ * it is not overwritten while the parsing takes place (unlike with
+ * parse_file).
+ */
+ static const struct stat blankstab;
+
+ struct parser_state usestate;
+ YY_BUFFER_STATE ybuf;
+ int r;
+
+ ybuf= yy_scan_string(string);
+ if (!ybuf) syscallerror("unable to create flex buffer for internal string");
+ parser_push(&usestate,descrip,&blankstab,ybuf,isinternal);
+
+ r= parser(0);
+
+ parser_pop();
+ if (r == tokv_eof) r= 0;
+ return r;
+}
+
+static int parse_file(const char *string, int *didexist) {
+ /* Returns the same things as parser, except that tokv_eof is turned
+ * into 0. If *didexist is 0 then errno will have been set.
+ * *string will be copied by parse_file so it may be be overwritten
+ * during the parsing (so, for example, yytext need not be copied).
+ */
+ static int fileparselevel= 0;
+
+ struct parser_state usestate, *checkrecurse;
+ YY_BUFFER_STATE ybuf;
+ int r;
+ FILE *file;
+ char *filename;
+ struct stat newstab;
+
+ if (fileparselevel >= MAX_INCLUDE_NEST) {
+ parseerrprint("too many nested levels of included files");
+ return tokv_error;
+ }
+ file= fopen(string,"r");
+ if (!file) {
+ if (errno == ENOENT) {
+ if (didexist) *didexist= 0;
+ return 0;
+ }
+ parseerrprint("unable to open config file `%s': %s",string,strerror(errno));
+ return tokv_error;
+ }
+ r= fstat(fileno(file),&newstab); if (r) syscallerror("unable to fstat new file");
+ for (checkrecurse= cstate; checkrecurse; checkrecurse= checkrecurse->upstate) {
+ if (!checkrecurse->filestab.st_mode) continue;
+ if (newstab.st_dev==checkrecurse->filestab.st_dev &&
+ newstab.st_ino==checkrecurse->filestab.st_ino) {
+ parseerrprint("recursion detected - config file `%s' calls itself",string);
+ fclose(file);
+ return tokv_error;
+ }
+ }
+
+ if (didexist) *didexist= 1;
+
+ ybuf= yy_create_buffer(file,YY_BUF_SIZE);
+ if (!ybuf) syscallerror("unable to create flex buffer for file");
+ filename= xstrsave(string);
+ parser_push(&usestate,filename,&newstab,ybuf,0);
+ fileparselevel++;
+
+ r= parser(0);
+ if (ferror(file)) {
+ parseerrprint("error reading configuration file `%s'",string);
+ r= tokv_error;