lex.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
/*
* Copyright (C) 1998-2005, 2007, 2013-2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* $Id: lex.c,v 1.86 2007/09/17 09:56:29 shane Exp $ */
/*! \file */
#include <config.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <isc/parseint.h>
typedef struct inputsource {
unsigned int ignored;
void * input;
char * name;
unsigned long line;
unsigned long saved_line;
} inputsource;
struct isc_lex {
/* Unlocked. */
unsigned int magic;
char * data;
unsigned int comments;
unsigned int brace_count;
unsigned int paren_count;
unsigned int saved_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->brace_count = 0;
lex->paren_count = 0;
lex->saved_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);
return (ISC_R_NOMEMORY);
}
if (result != ISC_R_SUCCESS) {
return (result);
}
return (ISC_R_SUCCESS);
}
/*
* Open 'filename' and make it the current input source for 'lex'.
*/
if (result != ISC_R_SUCCESS)
return (result);
if (result != ISC_R_SUCCESS)
return (result);
}
char name[128];
/*
* Make 'stream' the current input source for 'lex'.
*/
}
char name[128];
/*
* Make 'buffer' the current input source for 'lex'.
*/
}
/*
* 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 == EOF) {
return;
}
if (c == '\n')
}
static isc_result_t
unsigned int oldlen;
if (result != ISC_R_SUCCESS)
return (result);
}
return (ISC_R_SUCCESS);
}
int c;
unsigned int saved_options;
/*
* Get the next token.
*/
if ((options & ISC_LEXOPT_NOMORE) != 0) {
return (ISC_R_SUCCESS);
}
return (ISC_R_NOMORE);
}
{
if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
lex->paren_count != 0)
{
lex->paren_count = 0;
return (ISC_R_UNBALANCED);
}
if ((options & ISC_LEXOPT_BTEXT) != 0 &&
lex->brace_count != 0)
{
lex->brace_count = 0;
return (ISC_R_UNBALANCED);
}
if ((options & ISC_LEXOPT_EOF) != 0) {
return (ISC_R_SUCCESS);
}
return (ISC_R_EOF);
}
*curr = '\0';
#ifdef HAVE_FLOCKFILE
#endif
do {
#if defined(HAVE_FLOCKFILE) && defined(HAVE_GETCUNLOCKED)
c = getc_unlocked(stream);
#else
#endif
if (c == EOF) {
goto done;
}
}
} else {
c = EOF;
} else {
}
}
if (c != EOF) {
goto done;
}
}
}
if (state == lexstate_start)
/* Token has not started yet. */
} else {
c = EOF;
}
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) {
lex->paren_count = 0;
goto done;
}
if ((options & ISC_LEXOPT_BTEXT) != 0 &&
lex->brace_count != 0) {
lex->brace_count = 0;
goto done;
}
if ((options & ISC_LEXOPT_EOF) == 0) {
goto done;
}
} 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) {
result =
goto done;
}
lex->paren_count--;
if (lex->paren_count == 0)
}
continue;
} else if (c == '{' &&
(options & ISC_LEXOPT_BTEXT) != 0)
{
if (lex->brace_count != 0) {
goto done;
}
lex->brace_count++;
continue;
}
} else if (isdigit((unsigned char)c) &&
(options & ISC_LEXOPT_NUMBER) != 0) {
if ((options & ISC_LEXOPT_OCTAL) != 0 &&
(c == '8' || c == '9'))
else
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_OCTAL) != 0)
base = 8;
else if ((options & ISC_LEXOPT_CNUMBER) != 0)
base = 0;
else
base = 10;
base);
if (result == ISC_R_SUCCESS) {
} else if (result == ISC_R_BADNUMBER) {
isc_tokenvalue_t *v;
v->as_textregion.base =
v->as_textregion.length =
(unsigned int)
} else
goto done;
continue;
} else if (!(options & ISC_LEXOPT_CNUMBER) ||
((c != 'x' && c != 'X') ||
/* Above test supports hex numbers */
}
} else if ((options & ISC_LEXOPT_OCTAL) != 0 &&
(c == '8' || c == '9')) {
}
if (remaining == 0U) {
if (result != ISC_R_SUCCESS)
goto done;
}
*curr++ = c;
*curr = '\0';
remaining--;
break;
case lexstate_string:
/*
* EOF needs to be checked before lex->specials[c]
* as lex->specials[EOF] is not a good idea.
*/
(!escaped &&
goto done;
}
(unsigned int)
continue;
}
if ((options & ISC_LEXOPT_ESCAPE) != 0)
if (remaining == 0U) {
if (result != ISC_R_SUCCESS)
goto done;
}
*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) {
goto done;
}
if (c == '*')
break;
case lexstate_ccommentend:
if (c == EOF) {
goto done;
}
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 if (c != '*')
break;
case lexstate_eatline:
if ((c == '\n') || (c == EOF)) {
state = saved_state;
goto no_read;
}
break;
case lexstate_qstring:
if (c == EOF) {
goto done;
}
if (c == '"') {
if (escaped) {
/*
* Overwrite the preceding backslash.
*/
*prev = '"';
} else {
(unsigned int)
}
} else {
if (c == '\n' && !escaped &&
(options & ISC_LEXOPT_QSTRINGMULTILINE) == 0) {
goto done;
}
if (c == '\\' && !escaped)
else
if (remaining == 0U) {
if (result != ISC_R_SUCCESS)
goto done;
}
*curr++ = c;
*curr = '\0';
remaining--;
}
break;
case lexstate_btext:
if (c == EOF) {
goto done;
}
if (c == '{') {
if (escaped) {
*prev = '{';
} else {
lex->brace_count++;
}
} else if (c == '}') {
if (escaped) {
*prev = '}';
break;
}
lex->brace_count--;
if (lex->brace_count > 0)
break;
} else {
if (c == '\\' && !escaped)
else
if (remaining == 0U) {
if (result != ISC_R_SUCCESS)
goto done;
}
*curr++ = c;
*curr = '\0';
remaining--;
}
break;
default:
"Unexpected state %d"),
state);
/* Does not return. */
}
} while (!done);
done:
#ifdef HAVE_FLOCKFILE
#endif
return (result);
}
{
if (expect == isc_tokentype_qstring)
else if (expect == isc_tokentype_number)
if (result == ISC_R_RANGE)
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
return (ISC_R_UNEXPECTEDEND);
if (expect == isc_tokentype_number)
return (ISC_R_BADNUMBER);
return (ISC_R_UNEXPECTEDTOKEN);
}
return (ISC_R_SUCCESS);
}
{
if (result == ISC_R_RANGE)
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_UNEXPECTEDEND);
return (ISC_R_BADNUMBER);
}
return (ISC_R_SUCCESS);
}
void
/*
* Unget the current token.
*/
}
void
{
}
char *
return (NULL);
}
unsigned long
return (0);
}
char *newname;
return(ISC_R_NOTFOUND);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
return (ISC_FALSE);
}