/* * (c) Thomas Pornin 1999, 2000 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. The name of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef UCPP__CPP__#define UCPP__CPP__ /* * Uncomment the following if you want ucpp to use externally provided * error-reporting functions (ucpp_warning(), ucpp_error() and ucpp_ouch()) *//* #define NO_UCPP_ERROR_FUNCTIONS */ /* * Tokens (do not change the order unless checking operators_name[] in cpp.c) * * It is important that the token NONE is 0 * Check the STRING_TOKEN macro */#define CPPERR 512enum { NONE, /* whitespace */ NEWLINE, /* newline */ COMMENT, /* comment */ NUMBER, /* number constant */ NAME, /* identifier */ BUNCH, /* non-C characters */ PRAGMA, /* a #pragma directive */ CONTEXT, /* new file or #line */ STRING, /* constant "xxx" */ CHAR, /* constant 'xxx' */ SLASH, /* / */ ASSLASH, /* /= */ MINUS, /* - */ MMINUS, /* -- */ ASMINUS, /* -= */ ARROW, /* -> */ PLUS, /* + */ PPLUS, /* ++ */ ASPLUS, /* += */ LT, /* < */ LEQ, /* <= */ LSH, /* << */ ASLSH, /* <<= */ GT, /* > */ GEQ, /* >= */ RSH, /* >> */ ASRSH, /* >>= */ ASGN, /* = */ SAME, /* == */#ifdef CAST_OP CAST, /* => */#endif NOT, /* ~ */ NEQ, /* != */ AND, /* & */ LAND, /* && */ ASAND, /* &= */ OR, /* | */ LOR, /* || */ ASOR, /* |= */ PCT, /* % */ ASPCT, /* %= */ STAR, /* * */ ASSTAR, /* *= */ CIRC, /* ^ */ ASCIRC, /* ^= */ LNOT, /* ! */ ASNOT, /* ~= */ LBRA, /* { */ RBRA, /* } */ LBRK, /* [ */ RBRK, /* ] */ LPAR, /* ( */ RPAR, /* ) */ COMMA, /* , */ QUEST, /* ? */ SEMIC, /* ; */ COLON, /* : */ DOT, /* . */ MDOTS, /* ... */ SHARP, /* # */ DSHARP, /* ## */ OPT_NONE, /* optional space to separate tokens in text output */ DIGRAPH_TOKENS, /* there begin digraph tokens */ /* for DIG_*, do not change order, unless checking undig() in cpp.c */ DIG_LBRK, /* <: */ DIG_RBRK, /* :> */ DIG_LBRA, /* <% */ DIG_RBRA, /* %> */ DIG_SHARP, /* %: */ DIG_DSHARP, /* %:%: */ DIGRAPH_TOKENS_END, /* digraph tokens end here */ LAST_MEANINGFUL_TOKEN, /* reserved words will go there */ MACROARG, /* special token for representing macro arguments */ UPLUS = CPPERR, /* unary + */ UMINUS /* unary - */}; #include <stdio.h>#include <setjmp.h>#include "tune.h" struct token { int type; long line; char *name;}; struct token_fifo { struct token *t; size_t nt, art;}; struct lexer_state { /* input control */ FILE *input;#ifndef NO_UCPP_BUF unsigned char *input_buf;#ifdef UCPP_MMAP int from_mmap; unsigned char *input_buf_sav;#endif#endif unsigned char *input_string; size_t ebuf; size_t pbuf; int lka[2]; int nlka; int macfile; int last; int discard; unsigned long utf8; unsigned char copy_line[COPY_LINE_LENGTH]; int cli; /* output control */ FILE *output; struct token_fifo *output_fifo, *toplevel_of;#ifndef NO_UCPP_BUF unsigned char *output_buf;#endif size_t sbuf; /* token control */ struct token *ctok; struct token *save_ctok; int tknl; int ltwnl; int pending_token;#ifdef INMACRO_FLAG int inmacro; long macro_count;#endif /* lexer options */ long line; long oline; unsigned long flags; long count_trigraphs; struct garbage_fifo *gf; int ifnest; int condnest; int condcomp; int condmet; unsigned long condf[2];}; /* * Flags for struct lexer_state *//* warning flags */#define WARN_STANDARD 0x000001UL /* emit standard warnings */#define WARN_ANNOYING 0x000002UL /* emit annoying warnings */#define WARN_TRIGRAPHS 0x000004UL /* warn when trigraphs are used */#define WARN_TRIGRAPHS_MORE 0x000008UL /* extra-warn for trigraphs */#define WARN_PRAGMA 0x000010UL /* warn for pragmas in non-lexer mode */ /* error flags */#define FAIL_SHARP 0x000020UL /* emit errors on rogue '#' */#define CCHARSET 0x000040UL /* emit errors on non-C characters */ /* emission flags */#define DISCARD_COMMENTS 0x000080UL /* discard comments from text output */#define CPLUSPLUS_COMMENTS 0x000100UL /* understand C++-like comments */#define LINE_NUM 0x000200UL /* emit #line directives in output */#define GCC_LINE_NUM 0x000400UL /* same as #line, with gcc-syntax */ /* language flags */#define HANDLE_ASSERTIONS 0x000800UL /* understand assertions */#define HANDLE_PRAGMA 0x001000UL /* emit PRAGMA tokens in lexer mode */#define MACRO_VAARG 0x002000UL /* understand macros with '...' */#define UTF8_SOURCE 0x004000UL /* identifiers are in UTF8 encoding */#define HANDLE_TRIGRAPHS 0x008000UL /* handle trigraphs */ /* global ucpp behaviour */#define LEXER 0x010000UL /* behave as a lexer */#define KEEP_OUTPUT 0x020000UL /* emit the result of preprocessing */#define COPY_LINE 0x040000UL /* make a copy of the parsed line */ /* internal flags */#define READ_AGAIN 0x080000UL /* emit again the last token */#define TEXT_OUTPUT 0x100000UL /* output text */ /* * Public function prototypes */ #ifndef NO_UCPP_BUFvoid flush_output(struct lexer_state *);#endif void init_assertions(void);int make_assertion(char *);int destroy_assertion(char *);void print_assertions(void); void init_macros(void);int define_macro(struct lexer_state *, char *);int undef_macro(struct lexer_state *, char *);void print_defines(void); void set_init_filename(char *, int);void init_cpp(void);void init_include_path(char *[]);void init_lexer_state(struct lexer_state *);void init_lexer_mode(struct lexer_state *);void free_lexer_state(struct lexer_state *);int lex(struct lexer_state *);int check_cpp_errors(struct lexer_state *);void add_incpath(char *);void init_tables(int);void enter_file(struct lexer_state *, unsigned long);int cpp(struct lexer_state *); #ifdef UCPP_MMAPFILE *fopen_mmap_file(char *);void set_input_file(struct lexer_state *, FILE *);#endif struct stack_context { char *long_name, *name; long line;};struct stack_context *report_context(void); extern int no_special_macros, system_macros, emit_dependencies, emit_defines, emit_assertions;extern int c99_compliant, c99_hosted;extern FILE *emit_output;extern char *current_filename, *current_long_filename;extern char *operators_name[];extern struct protect { char *macro; int state; struct found_file *ff;} protect_detect; void ucpp_ouch(char *, ...);void ucpp_error(long, char *, ...);void ucpp_warning(long, char *, ...); extern int *transient_characters; /* * Errors from CPPERR_EOF and above are not real erros, only show-stoppers. * Errors below CPPERR_EOF are real ones. */#define CPPERR_NEST 900#define CPPERR_EOF 1000 /* * This macro tells whether the name field of a given token type is * relevant, or not. Irrelevant name field means that it might point * to outerspace. */#ifdef SEMPER_FIDELIS#define STRING_TOKEN(x) ((x) == NONE || ((x) >= COMMENT && (x) <= CHAR))#else#define STRING_TOKEN(x) ((x) >= NUMBER && (x) <= CHAR)#endif #endif
/*
* (c) Thomas Pornin 1999, 2000
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. The name of the authors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef UCPP__CPP__
#define UCPP__CPP__
/*
* Uncomment the following if you want ucpp to use externally provided
* error-reporting functions (ucpp_warning(), ucpp_error() and ucpp_ouch())
*/
/* #define NO_UCPP_ERROR_FUNCTIONS */
/*
* Tokens (do not change the order unless checking operators_name[] in cpp.c)
*
* It is important that the token NONE is 0
* Check the STRING_TOKEN macro
*/
#define CPPERR 512
enum {
NONE, /* whitespace */
NEWLINE, /* newline */
COMMENT, /* comment */
NUMBER, /* number constant */
NAME, /* identifier */
BUNCH, /* non-C characters */
PRAGMA, /* a #pragma directive */
CONTEXT, /* new file or #line */
STRING, /* constant "xxx" */
CHAR, /* constant 'xxx' */
SLASH, /* / */
ASSLASH, /* /= */
MINUS, /* - */
MMINUS, /* -- */
ASMINUS, /* -= */
ARROW, /* -> */
PLUS, /* + */
PPLUS, /* ++ */
ASPLUS, /* += */
LT, /* < */
LEQ, /* <= */
LSH, /* << */
ASLSH, /* <<= */
GT, /* > */
GEQ, /* >= */
RSH, /* >> */
ASRSH, /* >>= */
ASGN, /* = */
SAME, /* == */
#ifdef CAST_OP
CAST, /* => */
#endif
NOT, /* ~ */
NEQ, /* != */
AND, /* & */
LAND, /* && */
ASAND, /* &= */
OR, /* | */
LOR, /* || */
ASOR, /* |= */
PCT, /* % */
ASPCT, /* %= */
STAR, /* * */
ASSTAR, /* *= */
CIRC, /* ^ */
ASCIRC, /* ^= */
LNOT, /* ! */
ASNOT, /* ~= */
LBRA, /* { */
RBRA, /* } */
LBRK, /* [ */
RBRK, /* ] */
LPAR, /* ( */
RPAR, /* ) */
COMMA, /* , */
QUEST, /* ? */
SEMIC, /* ; */
COLON, /* : */
DOT, /* . */
MDOTS, /* ... */
SHARP, /* # */
DSHARP, /* ## */
OPT_NONE, /* optional space to separate tokens in text output */
DIGRAPH_TOKENS, /* there begin digraph tokens */
/* for DIG_*, do not change order, unless checking undig() in cpp.c */
DIG_LBRK, /* <: */
DIG_RBRK, /* :> */
DIG_LBRA, /* <% */
DIG_RBRA, /* %> */
DIG_SHARP, /* %: */
DIG_DSHARP, /* %:%: */
DIGRAPH_TOKENS_END, /* digraph tokens end here */
LAST_MEANINGFUL_TOKEN, /* reserved words will go there */
MACROARG, /* special token for representing macro arguments */
UPLUS = CPPERR, /* unary + */
UMINUS /* unary - */
};
#include <stdio.h>
#include <setjmp.h>
#include "tune.h"
struct token {
int type;
long line;
char *name;
};
struct token_fifo {
struct token *t;
size_t nt, art;
};
struct lexer_state {
/* input control */
FILE *input;
#ifndef NO_UCPP_BUF
unsigned char *input_buf;
#ifdef UCPP_MMAP
int from_mmap;
unsigned char *input_buf_sav;
#endif
#endif
unsigned char *input_string;
size_t ebuf;
size_t pbuf;
int lka[2];
int nlka;
int macfile;
int last;
int discard;
unsigned long utf8;
unsigned char copy_line[COPY_LINE_LENGTH];
int cli;
/* output control */
FILE *output;
struct token_fifo *output_fifo, *toplevel_of;
#ifndef NO_UCPP_BUF
unsigned char *output_buf;
#endif
size_t sbuf;
/* token control */
struct token *ctok;
struct token *save_ctok;
int tknl;
int ltwnl;
int pending_token;
#ifdef INMACRO_FLAG
int inmacro;
long macro_count;
#endif
/* lexer options */
long line;
long oline;
unsigned long flags;
long count_trigraphs;
struct garbage_fifo *gf;
int ifnest;
int condnest;
int condcomp;
int condmet;
unsigned long condf[2];
};
/*
* Flags for struct lexer_state
*/
/* warning flags */
#define WARN_STANDARD 0x000001UL /* emit standard warnings */
#define WARN_ANNOYING 0x000002UL /* emit annoying warnings */
#define WARN_TRIGRAPHS 0x000004UL /* warn when trigraphs are used */
#define WARN_TRIGRAPHS_MORE 0x000008UL /* extra-warn for trigraphs */
#define WARN_PRAGMA 0x000010UL /* warn for pragmas in non-lexer mode */
/* error flags */
#define FAIL_SHARP 0x000020UL /* emit errors on rogue '#' */
#define CCHARSET 0x000040UL /* emit errors on non-C characters */
/* emission flags */
#define DISCARD_COMMENTS 0x000080UL /* discard comments from text output */
#define CPLUSPLUS_COMMENTS 0x000100UL /* understand C++-like comments */
#define LINE_NUM 0x000200UL /* emit #line directives in output */
#define GCC_LINE_NUM 0x000400UL /* same as #line, with gcc-syntax */
/* language flags */
#define HANDLE_ASSERTIONS 0x000800UL /* understand assertions */
#define HANDLE_PRAGMA 0x001000UL /* emit PRAGMA tokens in lexer mode */
#define MACRO_VAARG 0x002000UL /* understand macros with '...' */
#define UTF8_SOURCE 0x004000UL /* identifiers are in UTF8 encoding */
#define HANDLE_TRIGRAPHS 0x008000UL /* handle trigraphs */
/* global ucpp behaviour */
#define LEXER 0x010000UL /* behave as a lexer */
#define KEEP_OUTPUT 0x020000UL /* emit the result of preprocessing */
#define COPY_LINE 0x040000UL /* make a copy of the parsed line */
/* internal flags */
#define READ_AGAIN 0x080000UL /* emit again the last token */
#define TEXT_OUTPUT 0x100000UL /* output text */
/*
* Public function prototypes
*/
#ifndef NO_UCPP_BUF
void flush_output(struct lexer_state *);
#endif
void init_assertions(void);
int make_assertion(char *);
int destroy_assertion(char *);
void print_assertions(void);
void init_macros(void);
int define_macro(struct lexer_state *, char *);
int undef_macro(struct lexer_state *, char *);
void print_defines(void);
void set_init_filename(char *, int);
void init_cpp(void);
void init_include_path(char *[]);
void init_lexer_state(struct lexer_state *);
void init_lexer_mode(struct lexer_state *);
void free_lexer_state(struct lexer_state *);
int lex(struct lexer_state *);
int check_cpp_errors(struct lexer_state *);
void add_incpath(char *);
void init_tables(int);
void enter_file(struct lexer_state *, unsigned long);
int cpp(struct lexer_state *);
#ifdef UCPP_MMAP
FILE *fopen_mmap_file(char *);
void set_input_file(struct lexer_state *, FILE *);
#endif
struct stack_context {
char *long_name, *name;
long line;
};
struct stack_context *report_context(void);
extern int no_special_macros, system_macros,
emit_dependencies, emit_defines, emit_assertions;
extern int c99_compliant, c99_hosted;
extern FILE *emit_output;
extern char *current_filename, *current_long_filename;
extern char *operators_name[];
extern struct protect {
char *macro;
int state;
struct found_file *ff;
} protect_detect;
void ucpp_ouch(char *, ...);
void ucpp_error(long, char *, ...);
void ucpp_warning(long, char *, ...);
extern int *transient_characters;
/*
* Errors from CPPERR_EOF and above are not real erros, only show-stoppers.
* Errors below CPPERR_EOF are real ones.
*/
#define CPPERR_NEST 900
#define CPPERR_EOF 1000
/*
* This macro tells whether the name field of a given token type is
* relevant, or not. Irrelevant name field means that it might point
* to outerspace.
*/
#ifdef SEMPER_FIDELIS
#define STRING_TOKEN(x) ((x) == NONE || ((x) >= COMMENT && (x) <= CHAR))
#else
#define STRING_TOKEN(x) ((x) >= NUMBER && (x) <= CHAR)
#endif
#endif