lex.c revision 15a44745412679c30a6d022733925af70a38b715
/*
* Copyright (C) 1998-2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: lex.c,v 1.34 2000/07/27 09:50:54 tale Exp $ */
#include <config.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
typedef struct inputsource {
unsigned int char_count;
int chars[2];
void * input;
char * name;
unsigned long line;
} inputsource;
struct isc_lex {
/* Unlocked. */
unsigned int magic;
char * data;
unsigned int options;
unsigned int comments;
unsigned int paren_count;
};
static inline isc_result_t
char *new;
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
/*
* Create a lexer.
*/
return (ISC_R_NOMEMORY);
return (ISC_R_NOMEMORY);
}
lex->paren_count = 0;
return (ISC_R_SUCCESS);
}
void
/*
* Destroy the lexer.
*/
}
unsigned int
/*
* Return the current lexer commenting styles.
*/
}
void
/*
* Set allowed lexer commenting styles.
*/
}
void
/*
* Put the current list of specials into 'specials'.
*/
}
void
/*
* The characters in 'specials' are returned as tokens. Along with
* whitespace, they delimit strings and numbers.
*/
}
static inline isc_result_t
{
return (ISC_R_NOMEMORY);
source->char_count = 0;
return (ISC_R_NOMEMORY);
}
return (ISC_R_SUCCESS);
}
/*
* Open 'filename' and make it the current input source for 'lex'.
*/
if (result != ISC_R_SUCCESS)
return (result);
}
char name[128];
/*
* Make 'stream' the current input source for 'lex'.
*/
/* This is safe. */
}
char name[128];
/*
* Make 'buffer' the current input source for 'lex'.
*/
/* This is safe. */
}
/*
* Close the most recently opened object (i.e. file or buffer).
*/
return (ISC_R_NOMORE);
if (source->need_close)
}
return (ISC_R_SUCCESS);
}
typedef enum {
} lexstate;
static void
if (c == '\n')
}
int c;
unsigned long ulong;
unsigned int saved_options;
char *e;
/*
* Get the next token.
*/
if ((options & ISC_LEXOPT_NOMORE) != 0) {
return (ISC_R_SUCCESS);
}
return (ISC_R_NOMORE);
}
if (source->have_token) {
return (ISC_R_SUCCESS);
}
if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
lex->paren_count != 0)
return (ISC_R_UNBALANCED);
if ((options & ISC_LEXOPT_EOF) != 0) {
return (ISC_R_SUCCESS);
}
return (ISC_R_EOF);
}
do {
if (source->char_count > 0) {
source->char_count--;
c = getc_unlocked(stream);
if (c == EOF) {
}
}
} else {
c = EOF;
} else {
}
}
if (c == '\n')
if (!escaped && c == ';' &&
!= 0)) {
saved_state = state;
continue;
} else if (c == '/' &&
ISC_LEXCOMMENT_CPLUSPLUS)) != 0) {
saved_state = state;
continue;
} else if (c == '#' &&
!= 0)) {
saved_state = state;
continue;
}
}
/* INSIST(c == EOF || (c >= 0 && c <= 255)); */
switch (state) {
case lexstate_start:
if (c == EOF) {
if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
lex->paren_count != 0)
return (ISC_R_UNBALANCED);
if ((options & ISC_LEXOPT_EOF) == 0)
return (ISC_R_EOF);
} else if (c == ' ' || c == '\t') {
if (lex->last_was_eol &&
!= 0) {
}
} else if (c == '\n') {
if ((options & ISC_LEXOPT_EOL) != 0) {
}
} else if (c == '\r') {
if ((options & ISC_LEXOPT_EOL) != 0)
} else if (c == '"' &&
(options & ISC_LEXOPT_QSTRING) != 0) {
if ((c == '(' || c == ')') &&
(options & ISC_LEXOPT_DNSMULTILINE) != 0) {
if (c == '(') {
if (lex->paren_count == 0)
lex->paren_count++;
} else {
if (lex->paren_count == 0)
return (ISC_R_UNBALANCED);
lex->paren_count--;
if (lex->paren_count == 0)
options =
}
continue;
}
} else if (isdigit((unsigned char)c) &&
(options & ISC_LEXOPT_NUMBER) != 0) {
goto no_read;
} else {
goto no_read;
}
break;
case lexstate_crlf:
if (c != '\n')
break;
case lexstate_number:
if (c == ' ' || c == '\t' || c == '\r' ||
c == '\n' || c == EOF ||
int base;
if ((options & ISC_LEXOPT_CNUMBER) != 0)
base = 0;
else
base = 10;
return (ISC_R_RANGE);
} else if (*e == 0) {
} else {
isc_tokenvalue_t *v;
v->as_textregion.base =
v->as_textregion.length =
}
continue;
} else if (!(options & ISC_LEXOPT_CNUMBER) ||
((c != 'x' && c != 'X') ||
/* Above test supports hex numbers */
}
}
if (remaining == 0) {
if (result != ISC_R_SUCCESS)
return (result);
}
*curr++ = c;
*curr = '\0';
remaining--;
break;
case lexstate_string:
if ((!escaped &&
continue;
}
if ((options & ISC_LEXOPT_ESCAPE) != 0)
if (remaining == 0) {
if (result != ISC_R_SUCCESS)
return (result);
}
*curr++ = c;
*curr = 0;
remaining--;
break;
case lexstate_maybecomment:
if (c == '*' &&
continue;
} else if (c == '/' &&
continue;
}
c = '/';
state = saved_state;
goto no_read;
case lexstate_ccomment:
if (c == EOF)
return (ISC_R_UNEXPECTEDEND);
if (c == '*')
break;
case lexstate_ccommentend:
if (c == EOF)
return (ISC_R_UNEXPECTEDEND);
if (c == '/') {
/*
* C-style comments become a single space.
* We do this to ensure that a comment will
* act as a delimiter for strings and
* numbers.
*/
c = ' ';
state = saved_state;
goto no_read;
} else
break;
case lexstate_eatline:
if (c == EOF)
return (ISC_R_UNEXPECTEDEND);
if (c == '\n') {
state = saved_state;
goto no_read;
}
break;
case lexstate_qstring:
if (c == EOF)
return (ISC_R_UNEXPECTEDEND);
if (c == '"') {
if (escaped) {
/*
* Overwrite the preceding backslash.
*/
*prev = '"';
} else {
}
} else {
if (c == '\\' && !escaped)
else
if (remaining == 0) {
if (result != ISC_R_SUCCESS)
return (result);
}
*curr++ = c;
*curr = 0;
remaining--;
}
break;
default:
"Unexpected state %d", state);
/* Does not return. */
}
} while (!done);
return (ISC_R_SUCCESS);
}
void
/*
* Unget the current token.
*/
}
char *
return(NULL);
}
unsigned long
return(0);
}
return (ISC_FALSE);
}