/* recdb.c - recursive/record database implementation
* Copyright 2000-2004 srvx Development Team
*
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of srvx.
+ *
+ * srvx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version. Important limitations are
- * listed in the COPYING file that accompanies this software.
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, email srvx-maintainers@srvx.net.
+ * along with srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include "recdb.h"
} RECDB_OUT;
#ifdef HAVE_MMAP
-static int mmap_error=0;
+static int mmap_error;
#endif
#define EOL '\n'
enum fail_codes {
UNTERMINATED_STRING,
+ UNTERMINATED_COMMENT,
EXPECTED_OPEN_QUOTE,
EXPECTED_OPEN_BRACE,
EXPECTED_OPEN_PAREN,
do {
do {
c = dbgetc(recdb);
- } while (c != '*' && c != EOF);
+ if (c == EOF) ABORT(recdb, UNTERMINATED_COMMENT, c);
+ } while (c != '*');
if ((c = dbgetc(recdb)) == '/') in_comment = 0;
+ if (c == EOF) ABORT(recdb, UNTERMINATED_COMMENT, c);
} while (in_comment);
} else if (d == '/') {
/* C++ style comment, with slash slash comment newline */
const char *reason;
switch (code >> 8) {
case UNTERMINATED_STRING: reason = "Unterminated string"; break;
+ case UNTERMINATED_COMMENT: reason = "Unterminated comment"; break;
case EXPECTED_OPEN_QUOTE: reason = "Expected '\"'"; break;
case EXPECTED_OPEN_BRACE: reason = "Expected '{'"; break;
case EXPECTED_OPEN_PAREN: reason = "Expected '('"; break;
void
explain_failure(RECDB *recdb, int code)
{
- log_module(MAIN_LOG, LOG_ERROR, "%s (got '%c') at %s line %d column %d.",
- failure_reason(code), code & 255,
- recdb->source, recdb->ctx.line, recdb->ctx.col);
+ static char msg[1024];
+ snprintf(msg, sizeof(msg), "%s (got '%c') at %s line %d column %d.",
+ failure_reason(code), code & 255,
+ recdb->source, recdb->ctx.line, recdb->ctx.col);
+ if (MAIN_LOG == NULL) {
+ fputs(msg, stderr);
+ fputc('\n', stderr);
+ fflush(stderr);
+ } else
+ log_module(MAIN_LOG, LOG_ERROR, "%s", msg);
}
const char *
if (fstat(fileno(recdb.f), &statinfo)) {
log_module(MAIN_LOG, LOG_ERROR, "Unable to fstat database file '%s': %s", filename, strerror(errno));
+ fclose(recdb.f);
return NULL;
}
recdb.length = (size_t)statinfo.st_size;
+ if (recdb.length == 0) {
+ fclose(recdb.f);
+ return alloc_database();
+ }
#ifdef HAVE_MMAP
/* Try mmap */
if (!mmap_error && (recdb.s = mmap(NULL, recdb.length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(recdb.f), 0)) != MAP_FAILED) {
recdb.type = RECDB_MMAP;
+ madvise(recdb.s, recdb.length, MADV_SEQUENTIAL);
} else {
/* Fall back to stdio */
if (!mmap_error) {