edje now uses (and installs if not previously found) epp as its default C preprocessor, providing consistent output across all platforms and allowing edje_cc to run on windows (vtorri!!)
fallbacks exist to use old behavior if epp fails. SVN revision: 57210
This commit is contained in:
parent
0c31abb0d4
commit
c7d4e15087
|
@ -14,3 +14,4 @@ Davide Andreoli <dave@gurumeditation.it>
|
|||
Sebastian Dransfeld <sd@tango.flipp.net>
|
||||
Tom Hacohen <tom@stosb.com>
|
||||
Aharon Hillel <a.hillel@partner.samsung.com>
|
||||
Mike Blumenkrantz <mike@zentific.com>
|
||||
|
|
|
@ -25,3 +25,6 @@
|
|||
|
||||
* Fix missing cursor changed signale on backspace
|
||||
|
||||
2011-02-21 Mike Blumenkrantz
|
||||
|
||||
* Add built-in cpp (epp) to provide consistent output on all archs/OSes
|
||||
|
|
|
@ -63,16 +63,16 @@ AC_DEFINE_UNQUOTED([SHARED_LIB_SUFFIX], ["$shrext_cmds"], [Suffix for shared obj
|
|||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
|
||||
have_edje_cc="yes"
|
||||
case "$host_os" in
|
||||
mingw32ce* | cegcc*)
|
||||
MODULE_ARCH="$host_os-$host_cpu"
|
||||
install_vim="no"
|
||||
have_edje_cc="no"
|
||||
;;
|
||||
*)
|
||||
MODULE_ARCH="$host_os-$host_cpu-v_maj.0.0"
|
||||
install_vim="yes"
|
||||
have_edje_cc="yes"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -294,6 +294,12 @@ if test "x$have_edje_cc" = "xyes"; then
|
|||
PKG_CHECK_MODULES([EDJE_CC], [ecore-file >= 1.0.0 ecore-evas >= 1.0.0 ecore >= 1.0.0 evas >= 1.0.0 eet >= 1.0.0 eina >= 1.0.0])
|
||||
EDJE_CC_LIBS="${EDJE_CC_LIBS} ${LUA_LIBS} ${lua_libs}"
|
||||
fi
|
||||
AC_PATH_PROG([EPP], [epp])
|
||||
AM_CONDITIONAL([BUILD_EPP], [test "x$have_edje_cc" = "xyes" -a -z "$EPP"])
|
||||
if test -z "$EPP" ; then
|
||||
EPP=${prefix}/bin/epp
|
||||
AC_SUBST(EPP)
|
||||
fi
|
||||
|
||||
if test "x$have_edje_decc" = "xyes"; then
|
||||
PKG_CHECK_MODULES([EDJE_DECC], [ecore-file >= 1.0.0 ecore-evas >= 1.0.0 ecore >= 1.0.0 evas >= 1.0.0 eet >= 1.0.0 eina >= 1.0.0])
|
||||
|
@ -380,7 +386,9 @@ doc/Makefile
|
|||
doc/edje.dox
|
||||
src/Makefile
|
||||
src/lib/Makefile
|
||||
src/bin/edje_cc_parse.c
|
||||
src/bin/Makefile
|
||||
src/bin/epp/Makefile
|
||||
utils/Makefile
|
||||
])
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = lib bin
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
if BUILD_EPP
|
||||
SUBDIRS = epp
|
||||
endif
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
bin_SCRIPTS = @EDJE_RECC_PRG@
|
||||
|
|
|
@ -692,7 +692,13 @@ compile(void)
|
|||
/*
|
||||
* Run the input through the C pre-processor.
|
||||
*/
|
||||
|
||||
ret = -1;
|
||||
if (ecore_file_exists("@EPP@"))
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "@EPP@ -I%s %s -P -o %s - < %s",
|
||||
inc, def, tmpn, file_in);
|
||||
ret = system(buf);
|
||||
}
|
||||
/*
|
||||
* On OpenSolaris, the default cpp is located in different places.
|
||||
* Alan Coppersmith told me to do what xorg does: using /usr/ccs/lib/cpp
|
||||
|
@ -700,8 +706,7 @@ compile(void)
|
|||
* Also, that preprocessor is not managing C++ comments, so pass the
|
||||
* sun cc preprocessor just after.
|
||||
*/
|
||||
ret = -1;
|
||||
if (ecore_file_exists("/usr/ccs/lib/cpp"))
|
||||
else if (ecore_file_exists("/usr/ccs/lib/cpp"))
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "/usr/ccs/lib/cpp -I%s %s %s %s",
|
||||
inc, def, file_in, tmpn);
|
|
@ -0,0 +1,53 @@
|
|||
# Makefile for GNU C compiler.
|
||||
# Copyright (C) 1987, 88, 90-94, 1995 Free Software Foundation, Inc.
|
||||
|
||||
#This file is part of GNU CC.
|
||||
|
||||
#GNU CC 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, or (at your option)
|
||||
#any later version.
|
||||
|
||||
#GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
bin_PROGRAMS = epp
|
||||
|
||||
epp_SOURCES = \
|
||||
cpplib.h \
|
||||
cpphash.h \
|
||||
cppalloc.c \
|
||||
cpperror.c \
|
||||
cppexp.c \
|
||||
cpphash.c \
|
||||
cpplib.c \
|
||||
cppmain.c
|
||||
|
||||
epp_CPPFLAGS = -I$(top_builddir) $(CWARNFLAGS)
|
||||
|
||||
DEFS= \
|
||||
-DHAVE_STRERROR \
|
||||
-DFATAL_EXIT_CODE=1 \
|
||||
-DSUCCESS_EXIT_CODE=1 \
|
||||
-DGCC_INCLUDE_DIR=\"/usr/include\" \
|
||||
-DGPLUSPLUS_INCLUDE_DIR=\"/usr/include\" \
|
||||
-DTOOL_INCLUDE_DIR=\"/usr/bin\" \
|
||||
-DHOST_BITS_PER_LONG=32 \
|
||||
-DBITS_PER_UNIT=8 \
|
||||
-DHOST_BITS_PER_INT=32 \
|
||||
-DBITS_PER_WORD=16 \
|
||||
-DTARGET_BELL=7 \
|
||||
-DTARGET_BS=8 \
|
||||
-DTARGET_FF=12 \
|
||||
-DTARGET_NEWLINE=10 \
|
||||
-DTARGET_CR=13 \
|
||||
-DTARGET_TAB=9 \
|
||||
-DTARGET_VT=11
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* Part of CPP library. (memory allocation - xmalloc etc)
|
||||
* Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
|
||||
* Written by Per Bothner, 1994.
|
||||
* Based on CCCP program by by Paul Rubin, June 1986
|
||||
* Adapted to ANSI C, Richard Stallman, Jan 1987
|
||||
* Copyright (C) 2003-2011 Kim Woelders
|
||||
*
|
||||
* 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 2, 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, write to the Free Software
|
||||
* Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In other words, you are welcome to use, share and improve this program.
|
||||
* You are forbidden to forbid anyone else to use, share and improve
|
||||
* what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "cpplib.h"
|
||||
|
||||
static void
|
||||
memory_full(void)
|
||||
{
|
||||
cpp_fatal("Memory exhausted.");
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc(unsigned size)
|
||||
{
|
||||
char *ptr = (char *)malloc(size);
|
||||
|
||||
if (ptr)
|
||||
return (ptr);
|
||||
memory_full();
|
||||
/*NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
xrealloc(void *old, unsigned size)
|
||||
{
|
||||
char *ptr = (char *)realloc(old, size);
|
||||
|
||||
if (!ptr)
|
||||
memory_full();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *
|
||||
xcalloc(unsigned number, unsigned size)
|
||||
{
|
||||
char *ptr = (char *)calloc(number, size);
|
||||
|
||||
if (!ptr)
|
||||
memory_full();
|
||||
return ptr;
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/* Default error handlers for CPP Library.
|
||||
* Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
|
||||
* Written by Per Bothner, 1994.
|
||||
* Based on CCCP program by by Paul Rubin, June 1986
|
||||
* Adapted to ANSI C, Richard Stallman, Jan 1987
|
||||
* Copyright (C) 2003-2011 Kim Woelders
|
||||
*
|
||||
* 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 2, 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, write to the Free Software
|
||||
* Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In other words, you are welcome to use, share and improve this program.
|
||||
* You are forbidden to forbid anyone else to use, share and improve
|
||||
* what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "cpplib.h"
|
||||
|
||||
/* Print the file names and line numbers of the #include
|
||||
* commands which led to the current file. */
|
||||
|
||||
void
|
||||
cpp_print_containing_files(cpp_reader * pfile)
|
||||
{
|
||||
cpp_buffer *ip;
|
||||
int first = 1;
|
||||
|
||||
/* If stack of files hasn't changed since we last printed
|
||||
* this info, don't repeat it. */
|
||||
if (pfile->input_stack_listing_current)
|
||||
return;
|
||||
|
||||
ip = cpp_file_buffer(pfile);
|
||||
|
||||
/* Give up if we don't find a source file. */
|
||||
if (!ip)
|
||||
return;
|
||||
|
||||
/* Find the other, outer source files. */
|
||||
while ((ip = CPP_PREV_BUFFER(ip)), ip != CPP_NULL_BUFFER(pfile))
|
||||
{
|
||||
long line, col;
|
||||
|
||||
cpp_buf_line_and_col(ip, &line, &col);
|
||||
if (ip->fname)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
first = 0;
|
||||
fprintf(stderr, "In file included");
|
||||
}
|
||||
else
|
||||
fprintf(stderr, ",\n ");
|
||||
}
|
||||
}
|
||||
if (!first)
|
||||
fprintf(stderr, ":\n");
|
||||
|
||||
/* Record we have printed the status as of this time. */
|
||||
pfile->input_stack_listing_current = 1;
|
||||
}
|
||||
|
||||
void
|
||||
cpp_file_line_for_message(cpp_reader * pfile __UNUSED__, const char *filename,
|
||||
int line, int column)
|
||||
{
|
||||
if (column > 0)
|
||||
{
|
||||
fprintf(stderr, "%s:%d:%d: ", filename, line, column);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s:%d: ", filename, line);
|
||||
}
|
||||
}
|
||||
|
||||
/* IS_ERROR is 1 for error, 0 for warning */
|
||||
void
|
||||
cpp_message_v(cpp_reader * pfile, int is_error, const char *msg, va_list args)
|
||||
{
|
||||
if (is_error)
|
||||
pfile->errors++;
|
||||
else
|
||||
fprintf(stderr, "warning: ");
|
||||
vfprintf(stderr, msg, args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
cpp_message(cpp_reader * pfile, int is_error, const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, msg);
|
||||
|
||||
cpp_message_v(pfile, is_error, msg, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void
|
||||
cpp_fatal_v(const char *msg, va_list args)
|
||||
{
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
vfprintf(stderr, msg, args);
|
||||
fprintf(stderr, "\n");
|
||||
exit(FATAL_EXIT_CODE);
|
||||
}
|
||||
|
||||
void
|
||||
cpp_fatal(const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, msg);
|
||||
|
||||
cpp_fatal_v(msg, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
cpp_pfatal_with_name(cpp_reader * pfile, const char *name)
|
||||
{
|
||||
cpp_perror_with_name(pfile, name);
|
||||
#ifdef VMS
|
||||
exit(vaxc$errno);
|
||||
#else
|
||||
exit(FATAL_EXIT_CODE);
|
||||
#endif
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,195 @@
|
|||
/* Part of CPP library. (Macro hash table support.)
|
||||
* Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
|
||||
* Written by Per Bothner, 1994.
|
||||
* Based on CCCP program by by Paul Rubin, June 1986
|
||||
* Adapted to ANSI C, Richard Stallman, Jan 1987
|
||||
* Copyright (C) 2003-2011 Kim Woelders
|
||||
*
|
||||
* 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 2, 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, write to the Free Software
|
||||
* Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In other words, you are welcome to use, share and improve this program.
|
||||
* You are forbidden to forbid anyone else to use, share and improve
|
||||
* what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
#include "config.h"
|
||||
#include "cpplib.h"
|
||||
#include "cpphash.h"
|
||||
|
||||
static HASHNODE *hashtab[HASHSIZE];
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define IS_IDCHAR(ch) is_idchar[(unsigned char)(ch)]
|
||||
|
||||
/*
|
||||
* return hash function on name. must be compatible with the one
|
||||
* computed a step at a time, elsewhere
|
||||
*/
|
||||
int
|
||||
hashf(const char *name, int len, int hashsize)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
while (len--)
|
||||
r = HASHSTEP(r, *name++);
|
||||
|
||||
return MAKE_POS(r) % hashsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* find the most recent hash node for name name (ending with first
|
||||
* non-identifier char) installed by install
|
||||
*
|
||||
* If LEN is >= 0, it is the length of the name.
|
||||
* Otherwise, compute the length by scanning the entire name.
|
||||
*
|
||||
* If HASH is >= 0, it is the precomputed hash code.
|
||||
* Otherwise, compute the hash code.
|
||||
*/
|
||||
HASHNODE *
|
||||
cpp_lookup(const char *name, int len, int hash)
|
||||
{
|
||||
const char *bp;
|
||||
HASHNODE *bucket;
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
for (bp = name; IS_IDCHAR(*bp); bp++)
|
||||
;
|
||||
len = bp - name;
|
||||
}
|
||||
if (hash < 0)
|
||||
hash = hashf(name, len, HASHSIZE);
|
||||
|
||||
bucket = hashtab[hash];
|
||||
while (bucket)
|
||||
{
|
||||
if (bucket->length == len
|
||||
&& strncmp((const char *)bucket->name, name, len) == 0)
|
||||
return bucket;
|
||||
bucket = bucket->next;
|
||||
}
|
||||
return (HASHNODE *) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a hash node. Some weirdness to free junk from macros.
|
||||
* More such weirdness will have to be added if you define more hash
|
||||
* types that need it.
|
||||
*/
|
||||
|
||||
/* Note that the DEFINITION of a macro is removed from the hash table
|
||||
* but its storage is not freed. This would be a storage leak
|
||||
* except that it is not reasonable to keep undefining and redefining
|
||||
* large numbers of macros many times.
|
||||
* In any case, this is necessary, because a macro can be #undef'd
|
||||
* in the middle of reading the arguments to a call to it.
|
||||
* If #undef freed the DEFINITION, that would crash. */
|
||||
|
||||
void
|
||||
delete_macro(HASHNODE * hp)
|
||||
{
|
||||
|
||||
if (hp->prev)
|
||||
hp->prev->next = hp->next;
|
||||
if (hp->next)
|
||||
hp->next->prev = hp->prev;
|
||||
|
||||
/* make sure that the bucket chain header that
|
||||
* the deleted guy was on points to the right thing afterwards. */
|
||||
if (hp == *hp->bucket_hdr)
|
||||
*hp->bucket_hdr = hp->next;
|
||||
|
||||
if (hp->type == T_MACRO)
|
||||
{
|
||||
DEFINITION *d = hp->value.defn;
|
||||
struct reflist *ap, *nextap;
|
||||
|
||||
for (ap = d->pattern; ap; ap = nextap)
|
||||
{
|
||||
nextap = ap->next;
|
||||
free(ap);
|
||||
}
|
||||
if (d->nargs >= 0)
|
||||
free(d->args.argnames);
|
||||
free(d);
|
||||
}
|
||||
free(hp);
|
||||
}
|
||||
/*
|
||||
* install a name in the main hash table, even if it is already there.
|
||||
* name stops with first non alphanumeric, except leading '#'.
|
||||
* caller must check against redefinition if that is desired.
|
||||
* delete_macro () removes things installed by install () in fifo order.
|
||||
* this is important because of the `defined' special symbol used
|
||||
* in #if, and also if pushdef/popdef directives are ever implemented.
|
||||
*
|
||||
* If LEN is >= 0, it is the length of the name.
|
||||
* Otherwise, compute the length by scanning the entire name.
|
||||
*
|
||||
* If HASH is >= 0, it is the precomputed hash code.
|
||||
* Otherwise, compute the hash code.
|
||||
*/
|
||||
HASHNODE *
|
||||
install(const char *name, int len, enum node_type type, int ivalue, char *value,
|
||||
int hash)
|
||||
{
|
||||
HASHNODE *hp;
|
||||
int i, bucket;
|
||||
const char *p;
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
p = name;
|
||||
while (IS_IDCHAR(*p))
|
||||
p++;
|
||||
len = p - name;
|
||||
}
|
||||
if (hash < 0)
|
||||
hash = hashf(name, len, HASHSIZE);
|
||||
|
||||
i = sizeof(HASHNODE) + len + 1;
|
||||
hp = (HASHNODE *) xmalloc(i);
|
||||
bucket = hash;
|
||||
hp->bucket_hdr = &hashtab[bucket];
|
||||
hp->next = hashtab[bucket];
|
||||
hashtab[bucket] = hp;
|
||||
hp->prev = NULL;
|
||||
if (hp->next)
|
||||
hp->next->prev = hp;
|
||||
hp->type = type;
|
||||
hp->length = len;
|
||||
if (hp->type == T_CONST)
|
||||
hp->value.ival = ivalue;
|
||||
else
|
||||
hp->value.cpval = value;
|
||||
hp->name = ((char *)hp) + sizeof(HASHNODE);
|
||||
memcpy(hp->name, name, len);
|
||||
hp->name[len] = 0;
|
||||
return hp;
|
||||
}
|
||||
|
||||
void
|
||||
cpp_hash_cleanup(cpp_reader * pfile __UNUSED__)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = HASHSIZE; --i >= 0;)
|
||||
{
|
||||
while (hashtab[i])
|
||||
delete_macro(hashtab[i]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
enum node_type;
|
||||
|
||||
/* different kinds of things that can appear in the value field
|
||||
of a hash node. Actually, this may be useless now. */
|
||||
union hashval {
|
||||
int ival;
|
||||
char *cpval;
|
||||
DEFINITION *defn;
|
||||
};
|
||||
|
||||
struct hashnode {
|
||||
struct hashnode *next; /* double links for easy deletion */
|
||||
struct hashnode *prev;
|
||||
struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash
|
||||
* chain is kept, in case the node is the head
|
||||
* of the chain and gets deleted. */
|
||||
enum node_type type; /* type of special token */
|
||||
int length; /* length of token, for quick comparison */
|
||||
char *name; /* the actual name */
|
||||
union hashval value; /* pointer to expansion, or whatever */
|
||||
};
|
||||
|
||||
typedef struct hashnode HASHNODE;
|
||||
|
||||
/* Some definitions for the hash table. The hash function MUST be
|
||||
computed as shown in hashf () below. That is because the rescan
|
||||
loop computes the hash value `on the fly' for most tokens,
|
||||
in order to avoid the overhead of a lot of procedure calls to
|
||||
the hashf () function. Hashf () only exists for the sake of
|
||||
politeness, for use when speed isn't so important. */
|
||||
|
||||
#define HASHSIZE 1403
|
||||
#define HASHSTEP(old, c) ((old << 2) + c)
|
||||
#define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
|
||||
|
||||
extern int hashf(const char *name, int len, int hashsize);
|
||||
extern HASHNODE *cpp_lookup(const char *name, int len, int hash);
|
||||
extern void delete_macro(HASHNODE * hp);
|
||||
extern HASHNODE *install(const char *name, int len, enum node_type type,
|
||||
int ivalue, char *value, int hash);
|
||||
extern void cpp_hash_cleanup(cpp_reader * pfile);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,641 @@
|
|||
/* Definitions for CPP library.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Written by Per Bothner, 1994-95.
|
||||
|
||||
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 2, 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, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef HOST_BITS_PER_WIDE_INT
|
||||
|
||||
#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
|
||||
#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
|
||||
#define HOST_WIDE_INT long
|
||||
#else
|
||||
#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
|
||||
#define HOST_WIDE_INT int
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define STATIC_BUFFERS
|
||||
|
||||
typedef struct cpp_reader cpp_reader;
|
||||
typedef struct cpp_buffer cpp_buffer;
|
||||
typedef struct cpp_options cpp_options;
|
||||
|
||||
enum cpp_token {
|
||||
CPP_EOF = -1,
|
||||
CPP_OTHER = 0,
|
||||
CPP_COMMENT = 1,
|
||||
CPP_HSPACE,
|
||||
CPP_VSPACE, /* newlines and #line directives */
|
||||
CPP_NAME,
|
||||
CPP_NUMBER,
|
||||
CPP_CHAR,
|
||||
CPP_STRING,
|
||||
CPP_DIRECTIVE,
|
||||
CPP_LPAREN, /* "(" */
|
||||
CPP_RPAREN, /* ")" */
|
||||
CPP_LBRACE, /* "{" */
|
||||
CPP_RBRACE, /* "}" */
|
||||
CPP_COMMA, /* "," */
|
||||
CPP_SEMICOLON, /* ";" */
|
||||
CPP_3DOTS, /* "..." */
|
||||
/* POP_TOKEN is returned when we've popped a cpp_buffer. */
|
||||
CPP_POP
|
||||
};
|
||||
|
||||
typedef enum cpp_token (*parse_underflow_t) (cpp_reader *);
|
||||
typedef int (*parse_cleanup_t) (cpp_buffer *, cpp_reader *);
|
||||
|
||||
/* A parse_marker indicates a previous position,
|
||||
which we can backtrack to. */
|
||||
|
||||
struct parse_marker {
|
||||
cpp_buffer *buf;
|
||||
struct parse_marker *next;
|
||||
int position;
|
||||
};
|
||||
|
||||
extern int cpp_handle_options(cpp_reader * pfile, int, char **);
|
||||
extern enum cpp_token cpp_get_token(cpp_reader * pfile);
|
||||
extern void cpp_skip_hspace(cpp_reader * pfile);
|
||||
|
||||
/* Maintain and search list of included files, for #import. */
|
||||
|
||||
#define IMPORT_HASH_SIZE 31
|
||||
|
||||
struct import_file {
|
||||
char *name;
|
||||
ino_t inode;
|
||||
dev_t dev;
|
||||
struct import_file *next;
|
||||
};
|
||||
|
||||
/* If we have a huge buffer, may need to cache more recent counts */
|
||||
#define CPP_LINE_BASE(BUF) ((BUF)->buf + (BUF)->line_base)
|
||||
|
||||
enum dump_type {
|
||||
dump_none = 0, dump_only, dump_names, dump_definitions
|
||||
};
|
||||
|
||||
struct cpp_buffer {
|
||||
unsigned char *buf;
|
||||
unsigned char *cur;
|
||||
unsigned char *rlimit; /* end of valid data */
|
||||
unsigned char *alimit; /* end of allocated buffer */
|
||||
unsigned char *prev; /* start of current token */
|
||||
|
||||
const char *fname;
|
||||
/* Filename specified with #line command. */
|
||||
const char *nominal_fname;
|
||||
|
||||
/* Record where in the search path this file was found.
|
||||
* For #include_next. */
|
||||
struct file_name_list *dir;
|
||||
|
||||
long line_base;
|
||||
long lineno; /* Line number at CPP_LINE_BASE. */
|
||||
long colno; /* Column number at CPP_LINE_BASE. */
|
||||
#ifndef STATIC_BUFFERS
|
||||
cpp_buffer *chain;
|
||||
#endif
|
||||
parse_underflow_t underflow;
|
||||
parse_cleanup_t cleanup;
|
||||
void *data;
|
||||
struct parse_marker *marks;
|
||||
/* Value of if_stack at start of this file.
|
||||
* Used to prohibit unmatched #endif (etc) in an include file. */
|
||||
struct if_stack *if_stack;
|
||||
|
||||
/* True if this is a header file included using <FILENAME>. */
|
||||
char system_header_p;
|
||||
char seen_eof;
|
||||
|
||||
/* True if buffer contains escape sequences.
|
||||
* Currently there are are only two kind:
|
||||
* "@-" means following identifier should not be macro-expanded.
|
||||
* "@ " means a token-separator. This turns into " " in final output
|
||||
* if not stringizing and needed to separate tokens; otherwise nothing.
|
||||
* "@@" means a normal '@'.
|
||||
* (An '@' inside a string stands for itself and is never an escape.) */
|
||||
char has_escapes;
|
||||
};
|
||||
|
||||
struct cpp_pending; /* Forward declaration - for C++. */
|
||||
struct file_name_map_list;
|
||||
|
||||
typedef struct assertion_hashnode ASSERTION_HASHNODE;
|
||||
|
||||
#define ASSERTION_HASHSIZE 37
|
||||
|
||||
#ifdef STATIC_BUFFERS
|
||||
/* Maximum nesting of cpp_buffers. We use a static limit, partly for
|
||||
efficiency, and partly to limit runaway recursion. */
|
||||
#define CPP_STACK_MAX 200
|
||||
#endif
|
||||
|
||||
struct cpp_reader {
|
||||
unsigned char *limit;
|
||||
parse_underflow_t get_token;
|
||||
cpp_buffer *buffer;
|
||||
#ifdef STATIC_BUFFERS
|
||||
cpp_buffer buffer_stack[CPP_STACK_MAX];
|
||||
#endif
|
||||
|
||||
int errors; /* Error counter for exit code */
|
||||
void *data;
|
||||
|
||||
unsigned char *token_buffer;
|
||||
int token_buffer_size;
|
||||
|
||||
/* Line where a newline was first seen in a string constant. */
|
||||
int multiline_string_line;
|
||||
|
||||
/* Current depth in #include directives that use <...>. */
|
||||
int system_include_depth;
|
||||
|
||||
/* List of included files that contained #pragma once. */
|
||||
struct file_name_list *dont_repeat_files;
|
||||
|
||||
/* List of other included files.
|
||||
* If ->control_macro if nonzero, the file had a #ifndef
|
||||
* around the entire contents, and ->control_macro gives the macro name. */
|
||||
struct file_name_list *all_include_files;
|
||||
|
||||
/* Current maximum length of directory names in the search path
|
||||
* for include files. (Altered as we get more of them.) */
|
||||
int max_include_len;
|
||||
|
||||
/* Hash table of files already included with #include or #import. */
|
||||
struct import_file *import_hash_table[IMPORT_HASH_SIZE];
|
||||
|
||||
struct if_stack *if_stack;
|
||||
|
||||
/* Nonzero means we are inside an IF during a -pcp run. In this mode
|
||||
* macro expansion is done, and preconditions are output for all macro
|
||||
* uses requiring them. */
|
||||
char pcp_inside_if;
|
||||
|
||||
/* Nonzero means we have printed (while error reporting) a list of
|
||||
* containing files that matches the current status. */
|
||||
char input_stack_listing_current;
|
||||
|
||||
/* If non-zero, macros are not expanded. */
|
||||
char no_macro_expand;
|
||||
|
||||
/* Print column number in error messages. */
|
||||
char show_column;
|
||||
|
||||
/* We're printed a warning recommending against using #import. */
|
||||
char import_warning;
|
||||
|
||||
/* If true, character between '<' and '>' are a single (string) token. */
|
||||
char parsing_include_directive;
|
||||
|
||||
/* True if escape sequences (as described for has_escapes in
|
||||
* parse_buffer) should be emitted. */
|
||||
char output_escapes;
|
||||
|
||||
/* 0: Have seen non-white-space on this line.
|
||||
* 1: Only seen white space so far on this line.
|
||||
* 2: Only seen white space so far in this file. */
|
||||
char only_seen_white;
|
||||
|
||||
/* Nonzero means this file was included with a -imacros or -include
|
||||
* command line and should not be recorded as an include file. */
|
||||
|
||||
int no_record_file;
|
||||
|
||||
long lineno;
|
||||
|
||||
struct tm *timebuf;
|
||||
|
||||
ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE];
|
||||
|
||||
/* Buffer of -M output. */
|
||||
char *deps_buffer;
|
||||
|
||||
/* Number of bytes allocated in above. */
|
||||
int deps_allocated_size;
|
||||
|
||||
/* Number of bytes used. */
|
||||
int deps_size;
|
||||
|
||||
/* Number of bytes since the last newline. */
|
||||
int deps_column;
|
||||
};
|
||||
|
||||
#define CPP_BUF_PEEK(BUFFER) \
|
||||
((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur : EOF)
|
||||
#define CPP_BUF_GET(BUFFER) \
|
||||
((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)
|
||||
#define CPP_FORWARD(BUFFER, N) ((BUFFER)->cur += (N))
|
||||
|
||||
/* Number of characters currently in PFILE's output buffer. */
|
||||
#define CPP_WRITTEN(PFILE) ((PFILE)->limit - (PFILE)->token_buffer)
|
||||
#define CPP_PWRITTEN(PFILE) ((PFILE)->limit)
|
||||
|
||||
/* Make sure PFILE->token_buffer has space for at least N more characters. */
|
||||
#define CPP_RESERVE(PFILE, N) \
|
||||
((unsigned int)(CPP_WRITTEN (PFILE) + N) > (unsigned int) (PFILE)->token_buffer_size \
|
||||
&& (cpp_grow_buffer (PFILE, N), 0))
|
||||
|
||||
/* Append string STR (of length N) to PFILE's output buffer.
|
||||
Assume there is enough space. */
|
||||
#define CPP_PUTS_Q(PFILE, STR, N) \
|
||||
do { memcpy ((PFILE)->limit, STR, (N)); (PFILE)->limit += (N); } while(0)
|
||||
/* Append string STR (of length N) to PFILE's output buffer. Make space. */
|
||||
#define CPP_PUTS(PFILE, STR, N) \
|
||||
do { CPP_RESERVE(PFILE, N); CPP_PUTS_Q(PFILE, STR,N); } while(0)
|
||||
/* Append character CH to PFILE's output buffer. Assume sufficient space. */
|
||||
#define CPP_PUTC_Q(PFILE, CH) (*(PFILE)->limit++ = (CH))
|
||||
/* Append character CH to PFILE's output buffer. Make space if need be. */
|
||||
#define CPP_PUTC(PFILE, CH) \
|
||||
do { CPP_RESERVE (PFILE, 1); CPP_PUTC_Q (PFILE, CH); } while(0)
|
||||
/* Make sure PFILE->limit is followed by '\0'. */
|
||||
#define CPP_NUL_TERMINATE_Q(PFILE) (*(PFILE)->limit = 0)
|
||||
#define CPP_NUL_TERMINATE(PFILE) \
|
||||
do { CPP_RESERVE(PFILE, 1); *(PFILE)->limit = 0; } while(0)
|
||||
#define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA))
|
||||
#define CPP_SET_WRITTEN(PFILE,N) ((PFILE)->limit = (PFILE)->token_buffer + (N))
|
||||
|
||||
#define CPP_OPTIONS(PFILE) ((cpp_options*)(PFILE)->data)
|
||||
#define CPP_BUFFER(PFILE) ((PFILE)->buffer)
|
||||
#ifdef STATIC_BUFFERS
|
||||
#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)+1)
|
||||
#define CPP_NULL_BUFFER(PFILE) (&(PFILE)->buffer_stack[CPP_STACK_MAX])
|
||||
#else
|
||||
#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)->chain)
|
||||
#define CPP_NULL_BUFFER(PFILE) ((cpp_buffer*)0)
|
||||
#endif
|
||||
|
||||
/* Pointed to by parse_file::data. */
|
||||
struct cpp_options {
|
||||
const char *in_fname;
|
||||
|
||||
/* Name of output file, for error messages. */
|
||||
const char *out_fname;
|
||||
|
||||
struct file_name_map_list *map_list;
|
||||
|
||||
/* Non-0 means -v, so print the full set of include dirs. */
|
||||
char verbose;
|
||||
|
||||
/* Nonzero means use extra default include directories for C++. */
|
||||
|
||||
char cplusplus;
|
||||
|
||||
/* Nonzero means handle cplusplus style comments */
|
||||
|
||||
char cplusplus_comments;
|
||||
|
||||
/* Nonzero means handle #import, for objective C. */
|
||||
|
||||
char objc;
|
||||
|
||||
/* Nonzero means this is an assembly file, and allow
|
||||
* unknown directives, which could be comments. */
|
||||
|
||||
int lang_asm;
|
||||
|
||||
/* Nonzero means turn NOTREACHED into #pragma NOTREACHED etc */
|
||||
|
||||
char for_lint;
|
||||
|
||||
/* Nonzero means handle CHILL comment syntax
|
||||
* and output CHILL string delimiter for __DATE___ etc. */
|
||||
|
||||
char chill;
|
||||
|
||||
/* Nonzero means copy comments into the output file. */
|
||||
|
||||
char put_out_comments;
|
||||
|
||||
/* Nonzero means don't process the ANSI trigraph sequences. */
|
||||
|
||||
char no_trigraphs;
|
||||
|
||||
/* Nonzero means print the names of included files rather than
|
||||
* the preprocessed output. 1 means just the #include "...",
|
||||
* 2 means #include <...> as well. */
|
||||
|
||||
char print_deps;
|
||||
|
||||
/* Nonzero if missing .h files in -M output are assumed to be generated
|
||||
* files and not errors. */
|
||||
|
||||
char print_deps_missing_files;
|
||||
|
||||
/* If true, fopen (deps_file, "a") else fopen (deps_file, "w"). */
|
||||
char print_deps_append;
|
||||
|
||||
/* Nonzero means print names of header files (-H). */
|
||||
|
||||
char print_include_names;
|
||||
|
||||
/* Nonzero means try to make failure to fit ANSI C an error. */
|
||||
|
||||
char pedantic_errors;
|
||||
|
||||
/* Nonzero means don't print warning messages. -w. */
|
||||
|
||||
char inhibit_warnings;
|
||||
|
||||
/* Nonzero means warn if slash-star appears in a comment. */
|
||||
|
||||
char warn_comments;
|
||||
|
||||
/* Nonzero means warn if there are any trigraphs. */
|
||||
|
||||
char warn_trigraphs;
|
||||
|
||||
/* Nonzero means warn if #import is used. */
|
||||
|
||||
char warn_import;
|
||||
|
||||
/* Nonzero means warn if a macro argument is (or would be)
|
||||
* stringified with -traditional. */
|
||||
|
||||
char warn_stringify;
|
||||
|
||||
/* Nonzero means turn warnings into errors. */
|
||||
|
||||
char warnings_are_errors;
|
||||
|
||||
/* Nonzero causes output not to be done,
|
||||
* but directives such as #define that have side effects
|
||||
* are still obeyed. */
|
||||
|
||||
char no_output;
|
||||
|
||||
/* Nonzero means don't output line number information. */
|
||||
|
||||
char no_line_commands;
|
||||
|
||||
/* Nonzero means output the text in failing conditionals,
|
||||
inside #failed ... #endfailed. */
|
||||
|
||||
char output_conditionals;
|
||||
|
||||
/* Nonzero means -I- has been seen,
|
||||
* so don't look for #include "foo" the source-file directory. */
|
||||
char ignore_srcdir;
|
||||
|
||||
/* Zero means dollar signs are punctuation.
|
||||
-$ stores 0; -traditional may store 1. Default is 1 for VMS, 0 otherwise.
|
||||
This must be 0 for correct processing of this ANSI C program:
|
||||
#define foo(a) #a
|
||||
#define lose(b) foo (b)
|
||||
#define test$
|
||||
lose (test) */
|
||||
char dollars_in_ident;
|
||||
#ifndef DOLLARS_IN_IDENTIFIERS
|
||||
#define DOLLARS_IN_IDENTIFIERS 1
|
||||
#endif
|
||||
|
||||
/* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */
|
||||
char traditional;
|
||||
|
||||
/* Nonzero means give all the error messages the ANSI standard requires. */
|
||||
char pedantic;
|
||||
|
||||
char done_initializing;
|
||||
|
||||
struct file_name_list *include; /* First dir to search */
|
||||
/* First dir to search for <file> */
|
||||
/* This is the first element to use for #include <...>.
|
||||
* If it is 0, use the entire chain for such includes. */
|
||||
struct file_name_list *first_bracket_include;
|
||||
/* This is the first element in the chain that corresponds to
|
||||
* a directory of system header files. */
|
||||
struct file_name_list *first_system_include;
|
||||
struct file_name_list *last_include; /* Last in chain */
|
||||
|
||||
/* Chain of include directories to put at the end of the other chain. */
|
||||
struct file_name_list *after_include;
|
||||
struct file_name_list *last_after_include; /* Last in chain */
|
||||
|
||||
/* Chain to put at the start of the system include files. */
|
||||
struct file_name_list *before_system;
|
||||
struct file_name_list *last_before_system; /* Last in chain */
|
||||
|
||||
/* Directory prefix that should replace `/usr' in the standard
|
||||
* include file directories. */
|
||||
char *include_prefix;
|
||||
|
||||
char inhibit_predefs;
|
||||
char no_standard_includes;
|
||||
char no_standard_cplusplus_includes;
|
||||
|
||||
/* dump_only means inhibit output of the preprocessed text
|
||||
and instead output the definitions of all user-defined
|
||||
macros in a form suitable for use as input to cccp.
|
||||
dump_names means pass #define and the macro name through to output.
|
||||
dump_definitions means pass the whole definition (plus #define) through
|
||||
*/
|
||||
|
||||
enum dump_type dump_macros;
|
||||
|
||||
/* Nonzero means pass all #define and #undef directives which we actually
|
||||
process through to the output stream. This feature is used primarily
|
||||
to allow cc1 to record the #defines and #undefs for the sake of
|
||||
debuggers which understand about preprocessor macros, but it may
|
||||
also be useful with -E to figure out how symbols are defined, and
|
||||
where they are defined. */
|
||||
int debug_output;
|
||||
|
||||
/* Pending -D, -U and -A options, in reverse order. */
|
||||
struct cpp_pending *pending;
|
||||
|
||||
/* File name which deps are being written to.
|
||||
* This is 0 if deps are being written to stdout. */
|
||||
char *deps_file;
|
||||
|
||||
/* Target-name to write with the dependency information. */
|
||||
char *deps_target;
|
||||
};
|
||||
|
||||
#define CPP_TRADITIONAL(PFILE) (CPP_OPTIONS(PFILE)-> traditional)
|
||||
#define CPP_PEDANTIC(PFILE) (CPP_OPTIONS (PFILE)->pedantic)
|
||||
#define CPP_PRINT_DEPS(PFILE) (CPP_OPTIONS (PFILE)->print_deps)
|
||||
|
||||
/* Name under which this program was invoked. */
|
||||
|
||||
extern char *progname;
|
||||
|
||||
/* The structure of a node in the hash table. The hash table
|
||||
has entries for all tokens defined by #define commands (type T_MACRO),
|
||||
plus some special tokens like __LINE__ (these each have their own
|
||||
type, and the appropriate code is run when that type of node is seen.
|
||||
It does not contain control words like "#define", which are recognized
|
||||
by a separate piece of code. */
|
||||
|
||||
/* different flavors of hash nodes --- also used in keyword table */
|
||||
enum node_type {
|
||||
T_DEFINE = 1, /* the `#define' keyword */
|
||||
T_INCLUDE, /* the `#include' keyword */
|
||||
T_INCLUDE_NEXT, /* the `#include_next' keyword */
|
||||
T_IMPORT, /* the `#import' keyword */
|
||||
T_IFDEF, /* the `#ifdef' keyword */
|
||||
T_IFNDEF, /* the `#ifndef' keyword */
|
||||
T_IF, /* the `#if' keyword */
|
||||
T_ELSE, /* `#else' */
|
||||
T_PRAGMA, /* `#pragma' */
|
||||
T_ELIF, /* `#elif' */
|
||||
T_UNDEF, /* `#undef' */
|
||||
T_LINE, /* `#line' */
|
||||
T_ERROR, /* `#error' */
|
||||
T_WARNING, /* `#warning' */
|
||||
T_ENDIF, /* `#endif' */
|
||||
T_SCCS, /* `#sccs', used on system V. */
|
||||
T_IDENT, /* `#ident', used on system V. */
|
||||
T_ASSERT, /* `#assert', taken from system V. */
|
||||
T_UNASSERT, /* `#unassert', taken from system V. */
|
||||
T_SPECLINE, /* special symbol `__LINE__' */
|
||||
T_DATE, /* `__DATE__' */
|
||||
T_FILE, /* `__FILE__' */
|
||||
T_BASE_FILE, /* `__BASE_FILE__' */
|
||||
T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
|
||||
T_VERSION, /* `__VERSION__' */
|
||||
T_SIZE_TYPE, /* `__SIZE_TYPE__' */
|
||||
T_PTRDIFF_TYPE, /* `__PTRDIFF_TYPE__' */
|
||||
T_WCHAR_TYPE, /* `__WCHAR_TYPE__' */
|
||||
T_USER_LABEL_PREFIX_TYPE, /* `__USER_LABEL_PREFIX__' */
|
||||
T_REGISTER_PREFIX_TYPE, /* `__REGISTER_PREFIX__' */
|
||||
T_TIME, /* `__TIME__' */
|
||||
T_CONST, /* Constant value, used by `__STDC__' */
|
||||
T_MACRO, /* macro defined by `#define' */
|
||||
T_DISABLED, /* macro temporarily turned off for rescan */
|
||||
T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
|
||||
T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
|
||||
T_UNUSED /* Used for something not defined. */
|
||||
};
|
||||
|
||||
/* Structure allocated for every #define. For a simple replacement
|
||||
such as
|
||||
#define foo bar ,
|
||||
nargs = -1, the `pattern' list is null, and the expansion is just
|
||||
the replacement text. Nargs = 0 means a functionlike macro with no args,
|
||||
e.g.,
|
||||
#define getchar() getc (stdin) .
|
||||
When there are args, the expansion is the replacement text with the
|
||||
args squashed out, and the reflist is a list describing how to
|
||||
build the output from the input: e.g., "3 chars, then the 1st arg,
|
||||
then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg".
|
||||
The chars here come from the expansion. Whatever is left of the
|
||||
expansion after the last arg-occurrence is copied after that arg.
|
||||
Note that the reflist can be arbitrarily long---
|
||||
its length depends on the number of times the arguments appear in
|
||||
the replacement text, not how many args there are. Example:
|
||||
#define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and
|
||||
pattern list
|
||||
{ (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
|
||||
where (x, y) means (nchars, argno). */
|
||||
|
||||
typedef struct reflist reflist;
|
||||
struct reflist {
|
||||
reflist *next;
|
||||
char stringify; /* nonzero if this arg was preceded by a
|
||||
* # operator. */
|
||||
char raw_before; /* Nonzero if a ## operator before arg. */
|
||||
char raw_after; /* Nonzero if a ## operator after arg. */
|
||||
char rest_args; /* Nonzero if this arg. absorbs the rest */
|
||||
int nchars; /* Number of literal chars to copy before
|
||||
* this arg occurrence. */
|
||||
int argno; /* Number of arg to substitute (origin-0) */
|
||||
};
|
||||
|
||||
typedef struct definition DEFINITION;
|
||||
struct definition {
|
||||
int nargs;
|
||||
int length; /* length of expansion string */
|
||||
int predefined; /* True if the macro was builtin or */
|
||||
/* came from the command line */
|
||||
unsigned char *expansion;
|
||||
int line; /* Line number of definition */
|
||||
const char *file; /* File of definition */
|
||||
char rest_args; /* Nonzero if last arg. absorbs the rest */
|
||||
reflist *pattern;
|
||||
union {
|
||||
/* Names of macro args, concatenated in reverse order
|
||||
* with comma-space between them.
|
||||
* The only use of this is that we warn on redefinition
|
||||
* if this differs between the old and new definitions. */
|
||||
unsigned char *argnames;
|
||||
} args;
|
||||
};
|
||||
|
||||
extern unsigned char is_idchar[256];
|
||||
|
||||
/* Stack of conditionals currently in progress
|
||||
(including both successful and failing conditionals). */
|
||||
|
||||
struct if_stack {
|
||||
struct if_stack *next; /* for chaining to the next stack frame */
|
||||
const char *fname; /* copied from input when frame is made */
|
||||
int lineno; /* similarly */
|
||||
int if_succeeded; /* true if a leg of this if-group
|
||||
* has been passed through rescan */
|
||||
unsigned char *control_macro; /* For #ifndef at start of file,
|
||||
* this is the macro name tested. */
|
||||
enum node_type type; /* type of last directive seen in this group */
|
||||
};
|
||||
typedef struct if_stack IF_STACK_FRAME;
|
||||
|
||||
extern void cpp_buf_line_and_col(cpp_buffer *, long *, long *);
|
||||
extern cpp_buffer *cpp_file_buffer(cpp_reader *);
|
||||
extern void cpp_define(cpp_reader *, unsigned char *);
|
||||
|
||||
extern void cpp_error(cpp_reader * pfile, const char *msg, ...);
|
||||
extern void cpp_warning(cpp_reader * pfile, const char *msg, ...);
|
||||
extern void cpp_pedwarn(cpp_reader * pfile, const char *msg, ...);
|
||||
extern void cpp_fatal(const char *msg, ...);
|
||||
extern void cpp_file_line_for_message(cpp_reader * pfile,
|
||||
const char *filename, int line,
|
||||
int column);
|
||||
extern void cpp_perror_with_name(cpp_reader * pfile, const char *name);
|
||||
extern void cpp_pfatal_with_name(cpp_reader * pfile, const char *name);
|
||||
extern void cpp_message(cpp_reader * pfile, int is_error,
|
||||
const char *msg, ...);
|
||||
extern void cpp_message_v(cpp_reader * pfile, int is_error,
|
||||
const char *msg, va_list args);
|
||||
|
||||
extern void cpp_grow_buffer(cpp_reader * pfile, long n);
|
||||
extern int cpp_parse_escape(cpp_reader * pfile, char **string_ptr);
|
||||
|
||||
void cpp_print_containing_files(cpp_reader * pfile);
|
||||
HOST_WIDE_INT cpp_parse_expr(cpp_reader * pfile);
|
||||
void skip_rest_of_line(cpp_reader * pfile);
|
||||
void init_parse_file(cpp_reader * pfile);
|
||||
void init_parse_options(struct cpp_options *opts);
|
||||
int push_parse_file(cpp_reader * pfile, const char *fname);
|
||||
void cpp_finish(cpp_reader * pfile);
|
||||
int cpp_read_check_assertion(cpp_reader * pfile);
|
||||
|
||||
void *xmalloc(unsigned size);
|
||||
void *xrealloc(void *old, unsigned size);
|
||||
void *xcalloc(unsigned number, unsigned size);
|
||||
|
||||
#ifdef __EMX__
|
||||
#define PATH_SEPARATOR ';'
|
||||
#endif
|
|
@ -0,0 +1,142 @@
|
|||
/* CPP main program, using CPP Library.
|
||||
* Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
* Written by Per Bothner, 1994-95.
|
||||
* Copyright (C) 2003-2011 Kim Woelders
|
||||
*
|
||||
* 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 2, 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, write to the Free Software
|
||||
* Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In other words, you are welcome to use, share and improve this program.
|
||||
* You are forbidden to forbid anyone else to use, share and improve
|
||||
* what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "cpplib.h"
|
||||
|
||||
#define EPP_DEBUG 0
|
||||
|
||||
cpp_reader parse_in;
|
||||
cpp_options options;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
int argi = 1; /* Next argument to handle. */
|
||||
struct cpp_options *opts = &options;
|
||||
enum cpp_token kind;
|
||||
int got_text;
|
||||
|
||||
p = argv[0] + strlen(argv[0]);
|
||||
#ifndef __EMX__
|
||||
while (p != argv[0] && p[-1] != '/')
|
||||
#else
|
||||
while (p != argv[0] && p[-1] != '/' && p[-1] != '\\')
|
||||
#endif
|
||||
--p;
|
||||
progname = p;
|
||||
|
||||
init_parse_file(&parse_in);
|
||||
parse_in.data = opts;
|
||||
|
||||
init_parse_options(opts);
|
||||
|
||||
argi += cpp_handle_options(&parse_in, argc - argi, argv + argi);
|
||||
if (argi < argc)
|
||||
cpp_fatal("Invalid option `%s'", argv[argi]);
|
||||
parse_in.show_column = 1;
|
||||
|
||||
i = push_parse_file(&parse_in, opts->in_fname);
|
||||
if (i != SUCCESS_EXIT_CODE)
|
||||
return i;
|
||||
|
||||
/* Now that we know the input file is valid, open the output. */
|
||||
|
||||
if (!opts->out_fname || !strcmp(opts->out_fname, ""))
|
||||
opts->out_fname = "stdout";
|
||||
else if (!freopen(opts->out_fname, "w", stdout))
|
||||
cpp_pfatal_with_name(&parse_in, opts->out_fname);
|
||||
|
||||
got_text = 0;
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
kind = cpp_get_token(&parse_in);
|
||||
#if EPP_DEBUG
|
||||
fprintf(stderr, "%03d: kind=%d len=%d out=%d text=%d\n", i,
|
||||
kind, CPP_WRITTEN(&parse_in), !opts->no_output, got_text);
|
||||
#endif
|
||||
switch (kind)
|
||||
{
|
||||
case CPP_EOF:
|
||||
goto done;
|
||||
|
||||
case CPP_HSPACE:
|
||||
continue;
|
||||
|
||||
case CPP_VSPACE:
|
||||
if (!got_text)
|
||||
goto next;
|
||||
break;
|
||||
|
||||
default:
|
||||
case CPP_OTHER:
|
||||
case CPP_NAME:
|
||||
case CPP_NUMBER:
|
||||
case CPP_CHAR:
|
||||
case CPP_STRING:
|
||||
case CPP_LPAREN:
|
||||
case CPP_RPAREN:
|
||||
case CPP_LBRACE:
|
||||
case CPP_RBRACE:
|
||||
case CPP_COMMA:
|
||||
case CPP_SEMICOLON:
|
||||
case CPP_3DOTS:
|
||||
got_text = 1;
|
||||
continue;
|
||||
|
||||
case CPP_COMMENT:
|
||||
case CPP_DIRECTIVE:
|
||||
case CPP_POP:
|
||||
continue;
|
||||
}
|
||||
#if EPP_DEBUG
|
||||
fprintf(stderr, "'");
|
||||
fwrite(parse_in.token_buffer, 1, CPP_WRITTEN(&parse_in), stderr);
|
||||
fprintf(stderr, "'\n");
|
||||
#endif
|
||||
if (!opts->no_output)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
n = CPP_WRITTEN(&parse_in);
|
||||
if (fwrite(parse_in.token_buffer, 1, n, stdout) != n)
|
||||
exit(FATAL_EXIT_CODE);
|
||||
}
|
||||
next:
|
||||
parse_in.limit = parse_in.token_buffer;
|
||||
got_text = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
cpp_finish(&parse_in);
|
||||
|
||||
if (parse_in.errors)
|
||||
exit(FATAL_EXIT_CODE);
|
||||
exit(SUCCESS_EXIT_CODE);
|
||||
}
|
Loading…
Reference in New Issue