/*
* dnsutl - utilities to make DNS easier to configure
* Copyright (C) 1999, 2006, 2007 Peter Miller
*
* This program 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 3 of the License, or
* (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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* 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, see
* <http://www.gnu.org/licenses/>.
*
* functions to lexically analyze files containing lines which consist
* of space separated fields
*/
#include <ac/ctype.h>
#include <ac/stdarg.h>
#include <ac/stdio.h>
#include <map.h>
#include <error.h>
#include <mem.h>
#include <mprintf.h>
#include <strlist.h>
static const char *fn;
static FILE *fp;
static int linum;
static int incriment_line_number;
static int non_printing_whine;
map_token_ty map_token;
char *map_value;
static int error_count;
void
map_open(const char *filename)
{
if (filename)
{
fn = filename;
fp = fopen(fn, "r");
if (!fp)
nfatal("open \"%s\"", fn);
}
else
{
fn = "(stdin)";
fp = stdin;
}
linum = 1;
}
void
map_close(void)
{
if (error_count)
{
fatal
(
"%s: found %d fatal error%s",
fn,
error_count,
(error_count == 1 ? "" : "s")
);
}
if (fp != stdin)
fclose(fp);
fn = 0;
fp = 0;
linum = 0;
error_count = 0;
incriment_line_number = 0;
}
static int
map_getc(void)
{
int c;
for (;;)
{
c = getc(fp);
switch (c)
{
case EOF:
if (ferror(fp))
nfatal("read \"%s\"", fn);
break;
case '\\':
c = getc(fp);
if (c == '\n')
{
++incriment_line_number;
continue;
}
if (c != EOF)
ungetc(c, fp);
c = '\\';
break;
}
return c;
}
}
static void
map_ungetc(int c)
{
if (c != EOF)
ungetc(c, fp);
}
void
map_lex(void)
{
int c;
int bufpos;
static int bufmax;
static char *buffer;
map_value = 0;
if (incriment_line_number)
{
linum += incriment_line_number;
incriment_line_number = 0;
}
for (;;)
{
c = map_getc();
switch (c)
{
case EOF:
if (ferror(fp))
nfatal("read \"%s\"", fn);
map_token = map_token_eof;
return;
case '\n':
++incriment_line_number;
non_printing_whine = 0;
map_token = map_token_eoln;
return;
case ' ':
case '\t':
break;
default:
bufpos = 0;
non_printing_whine = 0;
for (;;)
{
if (!isprint(c) && !non_printing_whine)
map_error("line contains non printing character");
if (bufpos >= bufmax)
{
bufmax += 100;
buffer = mem_change_size(buffer, bufmax);
}
buffer[bufpos++] = c;
c = map_getc();
if (c == '\n' || c == ' ' || c == '\t' || c == EOF)
{
map_ungetc(c);
break;
}
}
if (bufpos >= bufmax)
{
bufmax += 100;
buffer = mem_change_size(buffer, bufmax);
}
buffer[bufpos] = 0;
map_value = buffer;
map_token = map_token_string;
return;
case '#':
/*
* throw comments away
*/
for (;;)
{
c = map_getc();
if (c == '\n' || c == EOF)
{
map_ungetc(c);
break;
}
}
break;
}
}
}
void
map_error(const char *s, ...)
{
va_list ap;
char *msg;
va_start(ap, s);
msg = vmprintf(s, ap);
va_end(ap);
msg = mem_copy_string(msg);
error("%s: %d: %s", fn, linum, msg);
mem_free(msg);
++error_count;
if (error_count >= 20)
fatal("%s: too many fatal errors, aborting", fn);
}
void
map_warning(const char *s, ...)
{
va_list ap;
char *msg;
va_start(ap, s);
msg = vmprintf(s, ap);
va_end(ap);
msg = mem_copy_string(msg);
error("%s: %d: warning: %s", fn, linum, msg);
mem_free(msg);
}
int
map_read(strlist_ty *slp)
{
strlist_zero(slp);
for (;;)
{
map_lex();
switch (map_token)
{
case map_token_eof:
return 0;
case map_token_eoln:
/* ignore blank lines */
break;
case map_token_string:
for (;;)
{
string_ty *s;
s = str_from_c(map_value);
strlist_append(slp, s);
str_free(s);
map_lex();
if (map_token != map_token_string)
break;
}
if (map_token == map_token_eoln)
return 1;
if (map_token == map_token_eof)
return 1;
/* fall through... */
default:
map_error("syntax error");
for (;;)
{
map_lex();
if (map_token == map_token_eoln)
break;
if (map_token == map_token_eof)
break;
}
break;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1