mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Add tradcpp to the repository, and use it as GENCPP (generic preprocessor)
With lots of experimenting, tradcpp (0.4) seems to work way better than gcc, and it's output is actually valid. We'll go with that for now.
This commit is contained in:
parent
25e98da92e
commit
215be15f16
105 changed files with 6772 additions and 1 deletions
|
@ -8,5 +8,5 @@ MAINTAINERCLEANFILES = Makefile.in \
|
|||
config.h.in \
|
||||
install-sh
|
||||
|
||||
SUBDIRS = lib programs doc
|
||||
SUBDIRS = util lib programs doc
|
||||
|
||||
|
|
5
cde/util/Makefile.am
Normal file
5
cde/util/Makefile.am
Normal file
|
@ -0,0 +1,5 @@
|
|||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
SUBDIRS = tradcpp
|
||||
|
||||
|
41
cde/util/tradcpp/CHANGES
Normal file
41
cde/util/tradcpp/CHANGES
Normal file
|
@ -0,0 +1,41 @@
|
|||
release 0.4 (20130713)
|
||||
- Fix stupid build problem introduced in 0.3.1.
|
||||
- Accept and ignore -m32, which imake issues willy-nilly on a bunch
|
||||
of platforms. I thought this had already been done, but apparently
|
||||
not.
|
||||
- Don't use the <err.h> functions. There are still people out there
|
||||
using legacy systems missing them.
|
||||
- Sort out some more issues pertaining to handling quoted strings.
|
||||
- Add some more tests.
|
||||
|
||||
release 0.3.1 (20130709)
|
||||
- Don't leak memory and assert if a bad command-line option comes
|
||||
after a -D or a -include foo.
|
||||
- Since imake is a principal application for tradcpp and imake carefully
|
||||
hides what it's doing when you run it, when rejecting an invalid option
|
||||
be sure to report *what* that option is.
|
||||
|
||||
release 0.3 (20130616)
|
||||
- Don't eval the control expression of the first #if of a block when
|
||||
already in a false block; it might not be valid. Reported by
|
||||
Baptiste Daroussin.
|
||||
- Don't recognize comments within character constants.
|
||||
- Don't recognize macro argument parentheses or commas within strings,
|
||||
or within character constants either.
|
||||
|
||||
release 0.2 (20130611)
|
||||
- auto-recognize more builtin PowerPC and mips macros
|
||||
- pass -Wunused (partly from Baptiste Daroussin)
|
||||
- allow absolute paths in include files (partly from Baptiste Daroussin)
|
||||
- don't use getprogname() in the name of portability
|
||||
- add tests arising from December 2010 tech-toolchain thread (one
|
||||
from der Mouse, one of mine)
|
||||
- clean out usage of sys/cdefs.h macros and don't use the implementation
|
||||
namespace
|
||||
- make -Wcomment work again
|
||||
- fix handling of relative includes
|
||||
- provide a man page
|
||||
- other minor improvements
|
||||
|
||||
release 0.1 (20130610)
|
||||
- first release, works with at least some imake templates
|
26
cde/util/tradcpp/Makefile.am
Normal file
26
cde/util/tradcpp/Makefile.am
Normal file
|
@ -0,0 +1,26 @@
|
|||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
bin_PROGRAMS = tradcpp
|
||||
|
||||
tradcpp_SOURCES = array.c \
|
||||
array.h \
|
||||
config.h \
|
||||
directive.c \
|
||||
directive.h \
|
||||
eval.c \
|
||||
eval.h \
|
||||
files.c \
|
||||
files.h \
|
||||
inlinedefs.h \
|
||||
macro.c \
|
||||
macro.h \
|
||||
main.c \
|
||||
mode.h \
|
||||
output.c \
|
||||
output.h \
|
||||
place.c \
|
||||
place.h \
|
||||
utils.c \
|
||||
utils.h \
|
||||
version.h
|
||||
|
12
cde/util/tradcpp/Makefile.org
Normal file
12
cde/util/tradcpp/Makefile.org
Normal file
|
@ -0,0 +1,12 @@
|
|||
# $NetBSD$
|
||||
|
||||
PROG= tradcpp
|
||||
SRCS= main.c \
|
||||
files.c directive.c eval.c macro.c output.c \
|
||||
place.c array.c utils.c
|
||||
WARNS= 5
|
||||
|
||||
#DBG=-g
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
33
cde/util/tradcpp/TODO
Normal file
33
cde/util/tradcpp/TODO
Normal file
|
@ -0,0 +1,33 @@
|
|||
not implemented:
|
||||
- mode.input_allow_dollars.
|
||||
- column counts do not take tabstops into account.
|
||||
- mode.output_linenumbers.
|
||||
- mode.do_depend.
|
||||
- mode.do_macrolist.
|
||||
- mode.do_trace.
|
||||
- warns.endiflabels. (they cause errors)
|
||||
- warns.unused.
|
||||
- the -iremap option.
|
||||
- #line directives.
|
||||
- $CPP_RESTRICTED
|
||||
- other environment variables
|
||||
|
||||
tidy up:
|
||||
- get rid of inlinedefs.h
|
||||
- use of places in and below macro.c is pretty bogus.
|
||||
- macro code should be reworked.
|
||||
|
||||
fix:
|
||||
- "#if 0 && 1/0" should not crash; fix eval method.
|
||||
- an unterminated comment is reported as "no newline at end of file"
|
||||
(which isn't fatal by default)
|
||||
- quote characters and comment delimiters that are emitted by
|
||||
macros are not recognized. See:
|
||||
t34 (should produce a quote and FOO Q)
|
||||
t35 (similarly, this test may be redundant once it's fixed)
|
||||
t36 (C(3) should produce nothing)
|
||||
t37 (BC foo EC should produce nothing)
|
||||
Joerg says comments like in t36 should be stripped exactly
|
||||
twice, once when the macro is defined and again when it's
|
||||
expanded. Note that gcc's cpp -traditional is getting t37
|
||||
wrong, and it gets t36 wrong with -C.
|
115
cde/util/tradcpp/array.c
Normal file
115
cde/util/tradcpp/array.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*-
|
||||
* Copyright (c) 2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ARRAYINLINE
|
||||
#include "array.h"
|
||||
|
||||
struct array *
|
||||
array_create(void)
|
||||
{
|
||||
struct array *a;
|
||||
|
||||
a = domalloc(sizeof(*a));
|
||||
array_init(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
array_destroy(struct array *a)
|
||||
{
|
||||
array_cleanup(a);
|
||||
dofree(a, sizeof(*a));
|
||||
}
|
||||
|
||||
void
|
||||
array_init(struct array *a)
|
||||
{
|
||||
a->num = a->max = 0;
|
||||
a->v = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
array_cleanup(struct array *a)
|
||||
{
|
||||
arrayassert(a->num == 0);
|
||||
dofree(a->v, a->max * sizeof(a->v[0]));
|
||||
#ifdef ARRAYS_CHECKED
|
||||
a->v = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
array_setsize(struct array *a, unsigned num)
|
||||
{
|
||||
unsigned newmax;
|
||||
void **newptr;
|
||||
|
||||
if (num > a->max) {
|
||||
newmax = a->max;
|
||||
while (num > newmax) {
|
||||
newmax = newmax ? newmax*2 : 4;
|
||||
}
|
||||
newptr = dorealloc(a->v, a->max * sizeof(a->v[0]),
|
||||
newmax * sizeof(a->v[0]));
|
||||
a->v = newptr;
|
||||
a->max = newmax;
|
||||
}
|
||||
a->num = num;
|
||||
}
|
||||
|
||||
void
|
||||
array_insert(struct array *a, unsigned index_)
|
||||
{
|
||||
unsigned movers;
|
||||
|
||||
arrayassert(a->num <= a->max);
|
||||
arrayassert(index_ < a->num);
|
||||
|
||||
movers = a->num - index_;
|
||||
|
||||
array_setsize(a, a->num + 1);
|
||||
|
||||
memmove(a->v + index_+1, a->v + index_, movers*sizeof(*a->v));
|
||||
}
|
||||
|
||||
void
|
||||
array_remove(struct array *a, unsigned index_)
|
||||
{
|
||||
unsigned movers;
|
||||
|
||||
arrayassert(a->num <= a->max);
|
||||
arrayassert(index_ < a->num);
|
||||
|
||||
movers = a->num - (index_ + 1);
|
||||
memmove(a->v + index_, a->v + index_+1, movers*sizeof(*a->v));
|
||||
a->num--;
|
||||
}
|
279
cde/util/tradcpp/array.h
Normal file
279
cde/util/tradcpp/array.h
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*-
|
||||
* Copyright (c) 2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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 ARRAY_H
|
||||
#define ARRAY_H
|
||||
|
||||
#include "inlinedefs.h" // XXX
|
||||
#include "utils.h"
|
||||
|
||||
#define ARRAYS_CHECKED
|
||||
|
||||
#ifdef ARRAYS_CHECKED
|
||||
#include <assert.h>
|
||||
#define arrayassert assert
|
||||
#else
|
||||
#define arrayassert(x) ((void)(x))
|
||||
#endif
|
||||
|
||||
#ifndef ARRAYINLINE
|
||||
#define ARRAYINLINE C99INLINE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// type and base operations
|
||||
|
||||
struct array {
|
||||
void **v;
|
||||
unsigned num, max;
|
||||
};
|
||||
|
||||
struct array *array_create(void);
|
||||
void array_destroy(struct array *);
|
||||
void array_init(struct array *);
|
||||
void array_cleanup(struct array *);
|
||||
ARRAYINLINE unsigned array_num(const struct array *);
|
||||
ARRAYINLINE void *array_get(const struct array *, unsigned index_);
|
||||
ARRAYINLINE void array_set(const struct array *, unsigned index_, void *val);
|
||||
void array_setsize(struct array *, unsigned num);
|
||||
ARRAYINLINE void array_add(struct array *, void *val, unsigned *index_ret);
|
||||
void array_insert(struct array *a, unsigned index_);
|
||||
void array_remove(struct array *a, unsigned index_);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// inlining for base operations
|
||||
|
||||
ARRAYINLINE unsigned
|
||||
array_num(const struct array *a)
|
||||
{
|
||||
return a->num;
|
||||
}
|
||||
|
||||
ARRAYINLINE void *
|
||||
array_get(const struct array *a, unsigned index_)
|
||||
{
|
||||
arrayassert(index_ < a->num);
|
||||
return a->v[index_];
|
||||
}
|
||||
|
||||
ARRAYINLINE void
|
||||
array_set(const struct array *a, unsigned index_, void *val)
|
||||
{
|
||||
arrayassert(index_ < a->num);
|
||||
a->v[index_] = val;
|
||||
}
|
||||
|
||||
ARRAYINLINE void
|
||||
array_add(struct array *a, void *val, unsigned *index_ret)
|
||||
{
|
||||
unsigned index_ = a->num;
|
||||
array_setsize(a, index_+1);
|
||||
a->v[index_] = val;
|
||||
if (index_ret != NULL) {
|
||||
*index_ret = index_;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// bits for declaring and defining typed arrays
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
*
|
||||
* DECLARRAY_BYTYPE(foo, bar, INLINE) declares "struct foo", which is
|
||||
* an array of pointers to "bar", plus the operations on it.
|
||||
*
|
||||
* DECLARRAY(foo, INLINE) is equivalent to
|
||||
* DECLARRAY_BYTYPE(fooarray, struct foo, INLINE).
|
||||
*
|
||||
* DEFARRAY_BYTYPE and DEFARRAY are the same as DECLARRAY except that
|
||||
* they define the operations.
|
||||
*
|
||||
* The argument INLINE can be used as follows:
|
||||
*
|
||||
* 1. For no inlining:
|
||||
* In foo.h:
|
||||
* DECLARRAY(foo, );
|
||||
* In foo.c:
|
||||
* DEFARRAY(foo, );
|
||||
*
|
||||
* 2. To be file-static:
|
||||
* In foo.c:
|
||||
* DECLARRAY(foo, static);
|
||||
* DEFARRAY(foo, static);
|
||||
*
|
||||
* 3. To inline using C99:
|
||||
* In foo.h:
|
||||
* DECLARRAY(foo, inline);
|
||||
* DEFARRAY(foo, inline);
|
||||
*
|
||||
* 4. To inline with old gcc:
|
||||
* In foo.h:
|
||||
* #ifndef FOO_INLINE
|
||||
* #define FOO_INLINE extern inline
|
||||
* #endif
|
||||
* DECLARRAY(foo, );
|
||||
* DEFARRAY(foo, FOO_INLINE);
|
||||
* In foo.c:
|
||||
* #define FOO_INLINE
|
||||
* #include "foo.h"
|
||||
*
|
||||
* 5. To inline such that it works both with old gcc and C99:
|
||||
* In foo.h:
|
||||
* #ifndef FOO_INLINE
|
||||
* #define FOO_INLINE extern inline
|
||||
* #endif
|
||||
* DECLARRAY(foo, FOO_INLINE);
|
||||
* DEFARRAY(foo, FOO_INLINE);
|
||||
* In foo.c:
|
||||
* #define FOO_INLINE
|
||||
* #include "foo.h"
|
||||
*
|
||||
* The mechanism in case (4) ensures that an externally linkable
|
||||
* definition exists.
|
||||
*/
|
||||
|
||||
#define DECLARRAY_BYTYPE(ARRAY, T, INLINE) \
|
||||
struct ARRAY { \
|
||||
struct array arr; \
|
||||
}; \
|
||||
\
|
||||
INLINE struct ARRAY *ARRAY##_create(void); \
|
||||
INLINE void ARRAY##_destroy(struct ARRAY *a); \
|
||||
INLINE void ARRAY##_init(struct ARRAY *a); \
|
||||
INLINE void ARRAY##_cleanup(struct ARRAY *a); \
|
||||
INLINE unsigned ARRAY##_num(const struct ARRAY *a); \
|
||||
INLINE T *ARRAY##_get(const struct ARRAY *a, unsigned index_); \
|
||||
INLINE void ARRAY##_set(struct ARRAY *a, unsigned index_, T *val); \
|
||||
INLINE void ARRAY##_setsize(struct ARRAY *a, unsigned num); \
|
||||
INLINE void ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret);\
|
||||
INLINE void ARRAY##_insert(struct ARRAY *a, unsigned index_); \
|
||||
INLINE void ARRAY##_remove(struct ARRAY *a, unsigned index_)
|
||||
|
||||
|
||||
#define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \
|
||||
INLINE void \
|
||||
ARRAY##_init(struct ARRAY *a) \
|
||||
{ \
|
||||
array_init(&a->arr); \
|
||||
} \
|
||||
\
|
||||
INLINE void \
|
||||
ARRAY##_cleanup(struct ARRAY *a) \
|
||||
{ \
|
||||
array_cleanup(&a->arr); \
|
||||
} \
|
||||
\
|
||||
INLINE struct \
|
||||
ARRAY *ARRAY##_create(void) \
|
||||
{ \
|
||||
struct ARRAY *a; \
|
||||
\
|
||||
a = domalloc(sizeof(*a)); \
|
||||
ARRAY##_init(a); \
|
||||
return a; \
|
||||
} \
|
||||
\
|
||||
INLINE void \
|
||||
ARRAY##_destroy(struct ARRAY *a) \
|
||||
{ \
|
||||
ARRAY##_cleanup(a); \
|
||||
dofree(a, sizeof(*a)); \
|
||||
} \
|
||||
\
|
||||
INLINE unsigned \
|
||||
ARRAY##_num(const struct ARRAY *a) \
|
||||
{ \
|
||||
return array_num(&a->arr); \
|
||||
} \
|
||||
\
|
||||
INLINE T * \
|
||||
ARRAY##_get(const struct ARRAY *a, unsigned index_) \
|
||||
{ \
|
||||
return (T *)array_get(&a->arr, index_); \
|
||||
} \
|
||||
\
|
||||
INLINE void \
|
||||
ARRAY##_set(struct ARRAY *a, unsigned index_, T *val) \
|
||||
{ \
|
||||
array_set(&a->arr, index_, (void *)val); \
|
||||
} \
|
||||
\
|
||||
INLINE void \
|
||||
ARRAY##_setsize(struct ARRAY *a, unsigned num) \
|
||||
{ \
|
||||
array_setsize(&a->arr, num); \
|
||||
} \
|
||||
\
|
||||
INLINE void \
|
||||
ARRAY##_add(struct ARRAY *a, T *val, unsigned *ret) \
|
||||
{ \
|
||||
array_add(&a->arr, (void *)val, ret); \
|
||||
} \
|
||||
\
|
||||
INLINE void \
|
||||
ARRAY##_insert(struct ARRAY *a, unsigned index_) \
|
||||
{ \
|
||||
array_insert(&a->arr, index_); \
|
||||
} \
|
||||
\
|
||||
INLINE void \
|
||||
ARRAY##_remove(struct ARRAY *a, unsigned index_) \
|
||||
{ \
|
||||
array_remove(&a->arr, index_); \
|
||||
}
|
||||
|
||||
#define DECLARRAY(T, INLINE) DECLARRAY_BYTYPE(T##array, struct T, INLINE)
|
||||
#define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
|
||||
|
||||
#define DESTROYALL_ARRAY(T, INLINE) \
|
||||
void T##array_destroyall(struct T##array *arr); \
|
||||
\
|
||||
INLINE void \
|
||||
T##array_destroyall(struct T##array *arr) \
|
||||
{ \
|
||||
unsigned i, num; \
|
||||
struct T *t; \
|
||||
\
|
||||
num = T##array_num(arr); \
|
||||
for (i=0; i<num; i++) { \
|
||||
t = T##array_get(arr, i); \
|
||||
T##_destroy(t); \
|
||||
} \
|
||||
T##array_setsize(arr, 0); \
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// basic array types
|
||||
|
||||
DECLARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
|
||||
DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
|
||||
|
||||
#endif /* ARRAY_H */
|
158
cde/util/tradcpp/config.h
Normal file
158
cde/util/tradcpp/config.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*-
|
||||
* Copyright (c) 2010, 2013 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Config for predefined macros. If this doesn't do what you want you
|
||||
* can set any or all of the CONFIG_ defines from the compiler command
|
||||
* line; or patch the list in main.c; or both.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Paths
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_LOCALINCLUDE
|
||||
#define CONFIG_LOCALINCLUDE "/usr/local/include"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYSTEMINCLUDE
|
||||
#define CONFIG_SYSTEMINCLUDE "/usr/include"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Operating system
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_OS
|
||||
#if defined(__NetBSD__)
|
||||
#define CONFIG_OS "__NetBSD__"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__FreeBSD__)
|
||||
#define CONFIG_OS "__FreeBSD__"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__OpenBSD__)
|
||||
#define CONFIG_OS "__OpenBSD__"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__DragonFly__)
|
||||
#define CONFIG_OS "__DragonFly__"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__bsdi__)
|
||||
#define CONFIG_OS "__bsdi__"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__sun)
|
||||
#define CONFIG_OS "__sun"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__sgi)
|
||||
#define CONFIG_OS "__sgi"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__SVR4)
|
||||
#define CONFIG_OS "__SVR4"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__APPLE__)
|
||||
#define CONFIG_OS "__APPLE__"
|
||||
#define CONFIG_OS_2 "__unix__"
|
||||
#elif defined(__linux__)
|
||||
#define CONFIG_OS "__linux__"
|
||||
#elif defined(__CYGWIN__)
|
||||
#define CONFIG_OS "__CYGWIN__"
|
||||
#elif defined(__INTERIX)
|
||||
#define CONFIG_OS "__INTERIX"
|
||||
#elif defined(__MINGW32)
|
||||
#define CONFIG_OS "__MINGW32"
|
||||
#else
|
||||
/* we could error... but let's instead assume generic unix */
|
||||
#define CONFIG_OS "__unix__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CPU
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CPU
|
||||
#if defined(__x86_64__)
|
||||
#define CONFIG_CPU "__x86_64__"
|
||||
#define CONFIG_CPU_2 "__amd64__"
|
||||
#elif defined(__i386__) || defined(__i386)
|
||||
#define CONFIG_CPU "__i386__"
|
||||
#define CONFIG_CPU_2 "__i386"
|
||||
#elif defined(__sparc)
|
||||
#define CONFIG_CPU "__sparc"
|
||||
#elif defined(__mips)
|
||||
#define CONFIG_CPU "__mips"
|
||||
#elif defined(__mips__)
|
||||
#define CONFIG_CPU "__mips__"
|
||||
#elif defined(__mipsel__)
|
||||
#define CONFIG_CPU "__mipsel__"
|
||||
#elif defined(__POWERPC__)
|
||||
#define CONFIG_CPU "__POWERPC__"
|
||||
#elif defined(__POWERPC__)
|
||||
#define CONFIG_CPU "__powerpc__"
|
||||
#elif defined(__PPC__)
|
||||
#define CONFIG_CPU "__PPC__"
|
||||
#elif defined(__ppc__)
|
||||
#define CONFIG_CPU "__ppc__"
|
||||
#elif defined(__PPC64__)
|
||||
#define CONFIG_CPU "__PPC64__"
|
||||
#elif defined(__ppc64__)
|
||||
#define CONFIG_CPU "__ppc64__"
|
||||
#elif defined(__ARM__)
|
||||
#define CONFIG_CPU "__ARM__"
|
||||
#else
|
||||
/* let it go */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Other stuff
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SIZE
|
||||
#ifdef __LP64__
|
||||
#define CONFIG_SIZE "__LP64__"
|
||||
#else
|
||||
#define CONFIG_SIZE "__ILP32__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BINFMT
|
||||
#ifdef __ELF__
|
||||
#define CONFIG_BINFMT "__ELF__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We are __TRADCPP__ by default, but if you want to masquerade as
|
||||
* some other compiler this is a convenient place to change it.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_COMPILER
|
||||
#define CONFIG_COMPILER "__TRADCPP__"
|
||||
#define CONFIG_COMPILER_MINOR "__TRADCPP_MINOR__"
|
||||
#endif
|
626
cde/util/tradcpp/directive.c
Normal file
626
cde/util/tradcpp/directive.c
Normal file
|
@ -0,0 +1,626 @@
|
|||
/*-
|
||||
* Copyright (c) 2010, 2013 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "mode.h"
|
||||
#include "place.h"
|
||||
#include "files.h"
|
||||
#include "directive.h"
|
||||
#include "macro.h"
|
||||
#include "eval.h"
|
||||
#include "output.h"
|
||||
|
||||
struct ifstate {
|
||||
struct ifstate *prev;
|
||||
struct place startplace;
|
||||
bool curtrue;
|
||||
bool evertrue;
|
||||
bool seenelse;
|
||||
};
|
||||
|
||||
static struct ifstate *ifstate;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// common parsing bits
|
||||
|
||||
static
|
||||
void
|
||||
uncomment(char *buf)
|
||||
{
|
||||
char *s, *t, *u = NULL;
|
||||
bool incomment = false;
|
||||
bool inesc = false;
|
||||
bool inquote = false;
|
||||
char quote = '\0';
|
||||
|
||||
for (s = t = buf; *s; s++) {
|
||||
if (incomment) {
|
||||
if (s[0] == '*' && s[1] == '/') {
|
||||
s++;
|
||||
incomment = false;
|
||||
}
|
||||
} else {
|
||||
if (!inquote && s[0] == '/' && s[1] == '*') {
|
||||
incomment = true;
|
||||
} else {
|
||||
if (inesc) {
|
||||
inesc = false;
|
||||
} else if (s[0] == '\\') {
|
||||
inesc = true;
|
||||
} else if (!inquote &&
|
||||
(s[0] == '"' || s[0] == '\'')) {
|
||||
inquote = true;
|
||||
quote = s[0];
|
||||
} else if (inquote && s[0] == quote) {
|
||||
inquote = false;
|
||||
}
|
||||
|
||||
if (t != s) {
|
||||
*t = *s;
|
||||
}
|
||||
if (!strchr(ws, *t)) {
|
||||
u = t;
|
||||
}
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (u) {
|
||||
/* end string after last non-whitespace char */
|
||||
u[1] = '\0';
|
||||
} else {
|
||||
*t = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
oneword(const char *what, struct place *p2, char *line)
|
||||
{
|
||||
size_t pos;
|
||||
|
||||
pos = strcspn(line, ws);
|
||||
if (line[pos] != '\0') {
|
||||
p2->column += pos;
|
||||
complain(p2, "Garbage after %s argument", what);
|
||||
complain_fail();
|
||||
line[pos] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// if handling
|
||||
|
||||
static
|
||||
struct ifstate *
|
||||
ifstate_create(struct ifstate *prev, struct place *p, bool startstate)
|
||||
{
|
||||
struct ifstate *is;
|
||||
|
||||
is = domalloc(sizeof(*is));
|
||||
is->prev = prev;
|
||||
if (p != NULL) {
|
||||
is->startplace = *p;
|
||||
} else {
|
||||
place_setbuiltin(&is->startplace, 1);
|
||||
}
|
||||
is->curtrue = startstate;
|
||||
is->evertrue = is->curtrue;
|
||||
is->seenelse = false;
|
||||
return is;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ifstate_destroy(struct ifstate *is)
|
||||
{
|
||||
dofree(is, sizeof(*is));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ifstate_push(struct place *p, bool startstate)
|
||||
{
|
||||
struct ifstate *newstate;
|
||||
|
||||
newstate = ifstate_create(ifstate, p, startstate);
|
||||
if (!ifstate->curtrue) {
|
||||
newstate->curtrue = false;
|
||||
newstate->evertrue = true;
|
||||
}
|
||||
ifstate = newstate;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ifstate_pop(void)
|
||||
{
|
||||
struct ifstate *is;
|
||||
|
||||
is = ifstate;
|
||||
ifstate = ifstate->prev;
|
||||
ifstate_destroy(is);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_if(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
char *expr;
|
||||
bool val;
|
||||
struct place p3 = *p2;
|
||||
size_t oldlen;
|
||||
|
||||
expr = macroexpand(p2, line, strlen(line), true);
|
||||
|
||||
oldlen = strlen(expr);
|
||||
uncomment(expr);
|
||||
/* trim to fit, so the malloc debugging won't complain */
|
||||
expr = dorealloc(expr, oldlen + 1, strlen(expr) + 1);
|
||||
|
||||
if (ifstate->curtrue) {
|
||||
val = eval(&p3, expr);
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
ifstate_push(p, val);
|
||||
dostrfree(expr);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_ifdef(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
uncomment(line);
|
||||
oneword("#ifdef", p2, line);
|
||||
ifstate_push(p, macro_isdefined(line));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_ifndef(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
uncomment(line);
|
||||
oneword("#ifndef", p2, line);
|
||||
ifstate_push(p, !macro_isdefined(line));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_elif(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
char *expr;
|
||||
struct place p3 = *p2;
|
||||
size_t oldlen;
|
||||
|
||||
if (ifstate->seenelse) {
|
||||
complain(p, "#elif after #else");
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
if (ifstate->evertrue) {
|
||||
ifstate->curtrue = false;
|
||||
} else {
|
||||
expr = macroexpand(p2, line, strlen(line), true);
|
||||
|
||||
oldlen = strlen(expr);
|
||||
uncomment(expr);
|
||||
/* trim to fit, so the malloc debugging won't complain */
|
||||
expr = dorealloc(expr, oldlen + 1, strlen(expr) + 1);
|
||||
|
||||
ifstate->curtrue = eval(&p3, expr);
|
||||
ifstate->evertrue = ifstate->curtrue;
|
||||
dostrfree(expr);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_else(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
(void)p2;
|
||||
(void)line;
|
||||
|
||||
if (ifstate->seenelse) {
|
||||
complain(p, "Multiple #else directives in one conditional");
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
ifstate->curtrue = !ifstate->evertrue;
|
||||
ifstate->evertrue = true;
|
||||
ifstate->seenelse = true;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_endif(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
(void)p2;
|
||||
(void)line;
|
||||
|
||||
if (ifstate->prev == NULL) {
|
||||
complain(p, "Unmatched #endif");
|
||||
complain_fail();
|
||||
} else {
|
||||
ifstate_pop();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// macros
|
||||
|
||||
static
|
||||
void
|
||||
d_define(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
size_t pos, argpos;
|
||||
struct place p3, p4;
|
||||
|
||||
(void)p;
|
||||
|
||||
/*
|
||||
* line may be:
|
||||
* macro expansion
|
||||
* macro(arg, arg, ...) expansion
|
||||
*/
|
||||
|
||||
pos = strcspn(line, " \t\f\v(");
|
||||
if (line[pos] == '(') {
|
||||
line[pos++] = '\0';
|
||||
argpos = pos;
|
||||
pos = pos + strcspn(line+pos, "()");
|
||||
if (line[pos] == '(') {
|
||||
p2->column += pos;
|
||||
complain(p2, "Left parenthesis in macro parameters");
|
||||
complain_fail();
|
||||
return;
|
||||
}
|
||||
if (line[pos] != ')') {
|
||||
p2->column += pos;
|
||||
complain(p2, "Unclosed macro parameter list");
|
||||
complain_fail();
|
||||
return;
|
||||
}
|
||||
line[pos++] = '\0';
|
||||
#if 0
|
||||
if (!strchr(ws, line[pos])) {
|
||||
p2->column += pos;
|
||||
complain(p2, "Trash after macro parameter list");
|
||||
complain_fail();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
} else if (line[pos] == '\0') {
|
||||
argpos = 0;
|
||||
} else {
|
||||
line[pos++] = '\0';
|
||||
argpos = 0;
|
||||
}
|
||||
|
||||
pos += strspn(line+pos, ws);
|
||||
|
||||
p3 = *p2;
|
||||
p3.column += argpos;
|
||||
|
||||
p4 = *p2;
|
||||
p4.column += pos;
|
||||
|
||||
if (argpos) {
|
||||
macro_define_params(p2, line, &p3,
|
||||
line + argpos, &p4,
|
||||
line + pos);
|
||||
} else {
|
||||
macro_define_plain(p2, line, &p4, line + pos);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_undef(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
(void)p;
|
||||
|
||||
uncomment(line);
|
||||
oneword("#undef", p2, line);
|
||||
macro_undef(line);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// includes
|
||||
|
||||
static
|
||||
bool
|
||||
tryinclude(struct place *p, char *line)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(line);
|
||||
if (len > 2 && line[0] == '"' && line[len-1] == '"') {
|
||||
line[len-1] = '\0';
|
||||
file_readquote(p, line+1);
|
||||
line[len-1] = '"';
|
||||
return true;
|
||||
}
|
||||
if (len > 2 && line[0] == '<' && line[len-1] == '>') {
|
||||
line[len-1] = '\0';
|
||||
file_readbracket(p, line+1);
|
||||
line[len-1] = '>';
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_include(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
char *text;
|
||||
size_t oldlen;
|
||||
|
||||
uncomment(line);
|
||||
if (tryinclude(p, line)) {
|
||||
return;
|
||||
}
|
||||
text = macroexpand(p2, line, strlen(line), false);
|
||||
|
||||
oldlen = strlen(text);
|
||||
uncomment(text);
|
||||
/* trim to fit, so the malloc debugging won't complain */
|
||||
text = dorealloc(text, oldlen + 1, strlen(text) + 1);
|
||||
|
||||
if (tryinclude(p, text)) {
|
||||
dostrfree(text);
|
||||
return;
|
||||
}
|
||||
complain(p, "Illegal #include directive");
|
||||
complain(p, "Before macro expansion: #include %s", line);
|
||||
complain(p, "After macro expansion: #include %s", text);
|
||||
dostrfree(text);
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_line(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
(void)p2;
|
||||
(void)line;
|
||||
|
||||
/* XXX */
|
||||
complain(p, "Sorry, no #line yet");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// messages
|
||||
|
||||
static
|
||||
void
|
||||
d_warning(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
msg = macroexpand(p2, line, strlen(line), false);
|
||||
complain(p, "#warning: %s", msg);
|
||||
if (mode.werror) {
|
||||
complain_fail();
|
||||
}
|
||||
dostrfree(msg);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_error(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
msg = macroexpand(p2, line, strlen(line), false);
|
||||
complain(p, "#error: %s", msg);
|
||||
complain_fail();
|
||||
dostrfree(msg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// other
|
||||
|
||||
static
|
||||
void
|
||||
d_pragma(struct place *p, struct place *p2, char *line)
|
||||
{
|
||||
(void)p2;
|
||||
|
||||
complain(p, "#pragma %s", line);
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// directive table
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
bool ifskip;
|
||||
void (*func)(struct place *, struct place *, char *line);
|
||||
} directives[] = {
|
||||
{ "define", true, d_define },
|
||||
{ "elif", false, d_elif },
|
||||
{ "else", false, d_else },
|
||||
{ "endif", false, d_endif },
|
||||
{ "error", true, d_error },
|
||||
{ "if", false, d_if },
|
||||
{ "ifdef", false, d_ifdef },
|
||||
{ "ifndef", false, d_ifndef },
|
||||
{ "include", true, d_include },
|
||||
{ "line", true, d_line },
|
||||
{ "pragma", true, d_pragma },
|
||||
{ "undef", true, d_undef },
|
||||
{ "warning", true, d_warning },
|
||||
};
|
||||
static const unsigned numdirectives = HOWMANY(directives);
|
||||
|
||||
static
|
||||
void
|
||||
directive_gotdirective(struct place *p, char *line)
|
||||
{
|
||||
struct place p2;
|
||||
size_t len, skip;
|
||||
unsigned i;
|
||||
|
||||
p2 = *p;
|
||||
for (i=0; i<numdirectives; i++) {
|
||||
len = strlen(directives[i].name);
|
||||
if (!strncmp(line, directives[i].name, len) &&
|
||||
strchr(ws, line[len])) {
|
||||
if (directives[i].ifskip && !ifstate->curtrue) {
|
||||
return;
|
||||
}
|
||||
skip = len + strspn(line+len, ws);
|
||||
p2.column += skip;
|
||||
line += skip;
|
||||
|
||||
len = strlen(line);
|
||||
len = notrailingws(line, len);
|
||||
if (len < strlen(line)) {
|
||||
line[len] = '\0';
|
||||
}
|
||||
directives[i].func(p, &p2, line);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* ugh. allow # by itself, including with a comment after it */
|
||||
uncomment(line);
|
||||
if (line[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
skip = strcspn(line, ws);
|
||||
complain(p, "Unknown directive #%.*s", (int)skip, line);
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for nested comment delimiters in LINE.
|
||||
*/
|
||||
static
|
||||
size_t
|
||||
directive_scancomments(const struct place *p, char *line, size_t len)
|
||||
{
|
||||
size_t pos;
|
||||
bool incomment;
|
||||
struct place p2;
|
||||
|
||||
p2 = *p;
|
||||
incomment = 0;
|
||||
for (pos = 0; pos+1 < len; pos++) {
|
||||
if (line[pos] == '/' && line[pos+1] == '*') {
|
||||
if (incomment) {
|
||||
complain(&p2, "Warning: %c%c within comment",
|
||||
'/', '*');
|
||||
if (mode.werror) {
|
||||
complain_failed();
|
||||
}
|
||||
} else {
|
||||
incomment = true;
|
||||
}
|
||||
pos++;
|
||||
} else if (line[pos] == '*' && line[pos+1] == '/') {
|
||||
if (incomment) {
|
||||
incomment = false;
|
||||
} else {
|
||||
/* stray end-comment; should we care? */
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (line[pos] == '\n') {
|
||||
p2.line++;
|
||||
p2.column = 0;
|
||||
} else {
|
||||
p2.column++;
|
||||
}
|
||||
}
|
||||
|
||||
/* multiline comments are supposed to arrive in a single buffer */
|
||||
assert(!incomment);
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
directive_gotline(struct place *p, char *line, size_t len)
|
||||
{
|
||||
size_t skip;
|
||||
|
||||
if (warns.nestcomment) {
|
||||
directive_scancomments(p, line, len);
|
||||
}
|
||||
|
||||
/* check if we have a directive line (# exactly in column 0) */
|
||||
if (line[0] == '#') {
|
||||
skip = 1 + strspn(line + 1, ws);
|
||||
assert(skip <= len);
|
||||
p->column += skip;
|
||||
assert(line[len] == '\0');
|
||||
directive_gotdirective(p, line+skip /*, length = len-skip */);
|
||||
p->column += len-skip;
|
||||
} else if (ifstate->curtrue) {
|
||||
macro_sendline(p, line, len);
|
||||
p->column += len;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
directive_goteof(struct place *p)
|
||||
{
|
||||
while (ifstate->prev != NULL) {
|
||||
complain(p, "Missing #endif");
|
||||
complain(&ifstate->startplace, "...opened at this point");
|
||||
complain_failed();
|
||||
ifstate_pop();
|
||||
}
|
||||
macro_sendeof(p);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// module initialization
|
||||
|
||||
void
|
||||
directive_init(void)
|
||||
{
|
||||
ifstate = ifstate_create(NULL, NULL, true);
|
||||
}
|
||||
|
||||
void
|
||||
directive_cleanup(void)
|
||||
{
|
||||
assert(ifstate->prev == NULL);
|
||||
ifstate_destroy(ifstate);
|
||||
ifstate = NULL;
|
||||
}
|
39
cde/util/tradcpp/directive.h
Normal file
39
cde/util/tradcpp/directive.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct place;
|
||||
|
||||
void directive_init(void);
|
||||
void directive_cleanup(void);
|
||||
|
||||
void directive_gotline(struct place *p, char *line, size_t len);
|
||||
void directive_goteof(struct place *p);
|
||||
|
765
cde/util/tradcpp/eval.c
Normal file
765
cde/util/tradcpp/eval.c
Normal file
|
@ -0,0 +1,765 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "utils.h"
|
||||
#include "array.h"
|
||||
#include "mode.h"
|
||||
#include "place.h"
|
||||
#include "eval.h"
|
||||
|
||||
/*
|
||||
* e ::=
|
||||
* e1 ? e2 : e3
|
||||
* e1 || e2
|
||||
* e1 && e2
|
||||
* e1 | e2
|
||||
* e1 ^ e2
|
||||
* e1 & e2
|
||||
* e1 == e2 | e1 != e2
|
||||
* e1 < e2 | e1 <= e2 | e1 > e2 | e1 >= e2
|
||||
* e1 << e2 | e1 >> e2
|
||||
* e1 + e2 | e1 - e2
|
||||
* e1 * e2 | e1 / e2 | e1 % e2
|
||||
* !e | ~e | -e | +e
|
||||
* ( e ) | ident
|
||||
*/
|
||||
|
||||
enum tokens {
|
||||
T_EOF, /* end of input */
|
||||
T_VAL, /* value */
|
||||
T_LPAREN, /* parens */
|
||||
T_RPAREN,
|
||||
T_PIPEPIPE, /* operators */
|
||||
T_AMPAMP,
|
||||
T_EQEQ,
|
||||
T_BANGEQ,
|
||||
T_LTEQ,
|
||||
T_GTEQ,
|
||||
T_LTLT,
|
||||
T_GTGT,
|
||||
T_QUES,
|
||||
T_COLON,
|
||||
T_PIPE,
|
||||
T_CARET,
|
||||
T_AMP,
|
||||
T_LT,
|
||||
T_GT,
|
||||
T_PLUS,
|
||||
T_MINUS,
|
||||
T_STAR,
|
||||
T_SLASH,
|
||||
T_PCT,
|
||||
T_BANG,
|
||||
T_TILDE,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char c1, c2;
|
||||
enum tokens tok;
|
||||
} tokens_2[] = {
|
||||
{ '|', '|', T_PIPEPIPE },
|
||||
{ '&', '&', T_AMPAMP },
|
||||
{ '=', '=', T_EQEQ },
|
||||
{ '!', '=', T_BANGEQ },
|
||||
{ '<', '=', T_LTEQ },
|
||||
{ '>', '=', T_GTEQ },
|
||||
{ '<', '<', T_LTLT },
|
||||
{ '>', '>', T_GTGT },
|
||||
};
|
||||
static const unsigned num_tokens_2 = HOWMANY(tokens_2);
|
||||
|
||||
static const struct {
|
||||
char c1;
|
||||
enum tokens tok;
|
||||
} tokens_1[] = {
|
||||
{ '?', T_QUES },
|
||||
{ ':', T_COLON },
|
||||
{ '|', T_PIPE },
|
||||
{ '^', T_CARET },
|
||||
{ '&', T_AMP },
|
||||
{ '<', T_LT },
|
||||
{ '>', T_GT },
|
||||
{ '+', T_PLUS },
|
||||
{ '-', T_MINUS },
|
||||
{ '*', T_STAR },
|
||||
{ '/', T_SLASH },
|
||||
{ '%', T_PCT },
|
||||
{ '!', T_BANG },
|
||||
{ '~', T_TILDE },
|
||||
{ '(', T_LPAREN },
|
||||
{ ')', T_RPAREN },
|
||||
};
|
||||
static const unsigned num_tokens_1 = HOWMANY(tokens_1);
|
||||
|
||||
struct token {
|
||||
struct place place;
|
||||
enum tokens tok;
|
||||
int val;
|
||||
};
|
||||
DECLARRAY(token, static UNUSED);
|
||||
DEFARRAY(token, static);
|
||||
|
||||
static struct tokenarray tokens;
|
||||
|
||||
static
|
||||
struct token *
|
||||
token_create(const struct place *p, enum tokens tok, int val)
|
||||
{
|
||||
struct token *t;
|
||||
|
||||
t = domalloc(sizeof(*t));
|
||||
t->place = *p;
|
||||
t->tok = tok;
|
||||
t->val = val;
|
||||
return t;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
token_destroy(struct token *t)
|
||||
{
|
||||
dofree(t, sizeof(*t));
|
||||
}
|
||||
|
||||
DESTROYALL_ARRAY(token, );
|
||||
|
||||
#ifdef DEBUG
|
||||
static
|
||||
void
|
||||
printtokens(void)
|
||||
{
|
||||
unsigned i, num;
|
||||
struct token *t;
|
||||
|
||||
fprintf(stderr, "tokens:");
|
||||
num = tokenarray_num(&tokens);
|
||||
for (i=0; i<num; i++) {
|
||||
t = tokenarray_get(&tokens, i);
|
||||
switch (t->tok) {
|
||||
case T_EOF: fprintf(stderr, " <eof>"); break;
|
||||
case T_VAL: fprintf(stderr, " %d", t->val); break;
|
||||
case T_LPAREN: fprintf(stderr, " ("); break;
|
||||
case T_RPAREN: fprintf(stderr, " )"); break;
|
||||
case T_PIPEPIPE: fprintf(stderr, " ||"); break;
|
||||
case T_AMPAMP: fprintf(stderr, " &&"); break;
|
||||
case T_EQEQ: fprintf(stderr, " =="); break;
|
||||
case T_BANGEQ: fprintf(stderr, " !="); break;
|
||||
case T_LTEQ: fprintf(stderr, " <="); break;
|
||||
case T_GTEQ: fprintf(stderr, " >="); break;
|
||||
case T_LTLT: fprintf(stderr, " <<"); break;
|
||||
case T_GTGT: fprintf(stderr, " >>"); break;
|
||||
case T_QUES: fprintf(stderr, " ?"); break;
|
||||
case T_COLON: fprintf(stderr, " :"); break;
|
||||
case T_PIPE: fprintf(stderr, " |"); break;
|
||||
case T_CARET: fprintf(stderr, " ^"); break;
|
||||
case T_AMP: fprintf(stderr, " &"); break;
|
||||
case T_LT: fprintf(stderr, " <"); break;
|
||||
case T_GT: fprintf(stderr, " >"); break;
|
||||
case T_PLUS: fprintf(stderr, " +"); break;
|
||||
case T_MINUS: fprintf(stderr, " -"); break;
|
||||
case T_STAR: fprintf(stderr, " *"); break;
|
||||
case T_SLASH: fprintf(stderr, " /"); break;
|
||||
case T_PCT: fprintf(stderr, " %%"); break;
|
||||
case T_BANG: fprintf(stderr, " !"); break;
|
||||
case T_TILDE: fprintf(stderr, " ~"); break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
bool
|
||||
isuop(enum tokens tok)
|
||||
{
|
||||
switch (tok) {
|
||||
case T_BANG:
|
||||
case T_TILDE:
|
||||
case T_MINUS:
|
||||
case T_PLUS:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
isbop(enum tokens tok)
|
||||
{
|
||||
switch (tok) {
|
||||
case T_EOF:
|
||||
case T_VAL:
|
||||
case T_LPAREN:
|
||||
case T_RPAREN:
|
||||
case T_COLON:
|
||||
case T_QUES:
|
||||
case T_BANG:
|
||||
case T_TILDE:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
isop(enum tokens tok)
|
||||
{
|
||||
switch (tok) {
|
||||
case T_EOF:
|
||||
case T_VAL:
|
||||
case T_LPAREN:
|
||||
case T_RPAREN:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
getprec(enum tokens tok)
|
||||
{
|
||||
switch (tok) {
|
||||
case T_BANG: case T_TILDE: return -1;
|
||||
case T_STAR: case T_SLASH: case T_PCT: return 0;
|
||||
case T_PLUS: case T_MINUS: return 1;
|
||||
case T_LTLT: case T_GTGT: return 2;
|
||||
case T_LT: case T_LTEQ: case T_GT: case T_GTEQ: return 3;
|
||||
case T_EQEQ: case T_BANGEQ: return 4;
|
||||
case T_AMP: return 5;
|
||||
case T_CARET: return 6;
|
||||
case T_PIPE: return 7;
|
||||
case T_AMPAMP: return 8;
|
||||
case T_PIPEPIPE: return 9;
|
||||
default: break;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
looser(enum tokens t1, enum tokens t2)
|
||||
{
|
||||
return getprec(t1) >= getprec(t2);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
eval_uop(enum tokens op, int val)
|
||||
{
|
||||
switch (op) {
|
||||
case T_BANG: val = !val; break;
|
||||
case T_TILDE: val = (int)~(unsigned)val; break;
|
||||
case T_MINUS: val = -val; break;
|
||||
case T_PLUS: break;
|
||||
default: assert(0); break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
eval_bop(struct place *p, int lv, enum tokens op, int rv)
|
||||
{
|
||||
unsigned mask;
|
||||
|
||||
switch (op) {
|
||||
case T_PIPEPIPE: return lv || rv;
|
||||
case T_AMPAMP: return lv && rv;
|
||||
case T_PIPE: return (int)((unsigned)lv | (unsigned)rv);
|
||||
case T_CARET: return (int)((unsigned)lv ^ (unsigned)rv);
|
||||
case T_AMP: return (int)((unsigned)lv & (unsigned)rv);
|
||||
case T_EQEQ: return lv == rv;
|
||||
case T_BANGEQ: return lv != rv;
|
||||
case T_LT: return lv < rv;
|
||||
case T_GT: return lv > rv;
|
||||
case T_LTEQ: return lv <= rv;
|
||||
case T_GTEQ: return lv >= rv;
|
||||
|
||||
case T_LTLT:
|
||||
case T_GTGT:
|
||||
if (rv < 0) {
|
||||
complain(p, "Negative bit-shift");
|
||||
complain_fail();
|
||||
rv = 0;
|
||||
}
|
||||
if ((unsigned)rv >= CHAR_BIT * sizeof(unsigned)) {
|
||||
complain(p, "Bit-shift farther than type width");
|
||||
complain_fail();
|
||||
rv = 0;
|
||||
}
|
||||
if (op == T_LTLT) {
|
||||
return (int)((unsigned)lv << (unsigned)rv);
|
||||
}
|
||||
mask = ((unsigned)-1) << (CHAR_BIT * sizeof(unsigned) - rv);
|
||||
lv = (int)(((unsigned)lv >> (unsigned)rv) | mask);
|
||||
return lv;
|
||||
|
||||
case T_MINUS:
|
||||
if (rv == INT_MIN) {
|
||||
if (lv == INT_MIN) {
|
||||
return 0;
|
||||
}
|
||||
lv--;
|
||||
rv++;
|
||||
}
|
||||
rv = -rv;
|
||||
/* FALLTHROUGH */
|
||||
case T_PLUS:
|
||||
if (rv > 0 && lv > (INT_MAX - rv)) {
|
||||
complain(p, "Integer overflow");
|
||||
complain_fail();
|
||||
return INT_MAX;
|
||||
}
|
||||
if (rv < 0 && lv < (INT_MIN - rv)) {
|
||||
complain(p, "Integer underflow");
|
||||
complain_fail();
|
||||
return INT_MIN;
|
||||
}
|
||||
return lv + rv;
|
||||
|
||||
case T_STAR:
|
||||
if (rv == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (rv == 1) {
|
||||
return lv;
|
||||
}
|
||||
if (rv == -1 && lv == INT_MIN) {
|
||||
lv++;
|
||||
lv = -lv;
|
||||
if (lv == INT_MAX) {
|
||||
complain(p, "Integer overflow");
|
||||
complain_fail();
|
||||
return INT_MAX;
|
||||
}
|
||||
lv++;
|
||||
return lv;
|
||||
}
|
||||
if (lv == INT_MIN && rv < 0) {
|
||||
complain(p, "Integer overflow");
|
||||
complain_fail();
|
||||
return INT_MAX;
|
||||
}
|
||||
if (lv == INT_MIN && rv > 0) {
|
||||
complain(p, "Integer underflow");
|
||||
complain_fail();
|
||||
return INT_MIN;
|
||||
}
|
||||
if (rv < 0) {
|
||||
rv = -rv;
|
||||
lv = -lv;
|
||||
}
|
||||
if (lv > 0 && lv > INT_MAX / rv) {
|
||||
complain(p, "Integer overflow");
|
||||
complain_fail();
|
||||
return INT_MAX;
|
||||
}
|
||||
if (lv < 0 && lv < INT_MIN / rv) {
|
||||
complain(p, "Integer underflow");
|
||||
complain_fail();
|
||||
return INT_MIN;
|
||||
}
|
||||
return lv * rv;
|
||||
|
||||
case T_SLASH:
|
||||
if (rv == 0) {
|
||||
complain(p, "Division by zero");
|
||||
complain_fail();
|
||||
return 0;
|
||||
}
|
||||
return lv / rv;
|
||||
|
||||
case T_PCT:
|
||||
if (rv == 0) {
|
||||
complain(p, "Modulus by zero");
|
||||
complain_fail();
|
||||
return 0;
|
||||
}
|
||||
return lv % rv;
|
||||
|
||||
default: assert(0); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
tryreduce(void)
|
||||
{
|
||||
unsigned num;
|
||||
struct token *t1, *t2, *t3, *t4, *t5, *t6;
|
||||
|
||||
while (1) {
|
||||
#ifdef DEBUG
|
||||
printtokens();
|
||||
#endif
|
||||
num = tokenarray_num(&tokens);
|
||||
t1 = (num >= 1) ? tokenarray_get(&tokens, num-1) : NULL;
|
||||
t2 = (num >= 2) ? tokenarray_get(&tokens, num-2) : NULL;
|
||||
t3 = (num >= 3) ? tokenarray_get(&tokens, num-3) : NULL;
|
||||
|
||||
if (num >= 3 &&
|
||||
t3->tok == T_LPAREN &&
|
||||
t2->tok == T_VAL &&
|
||||
t1->tok == T_RPAREN) {
|
||||
/* (x) -> x */
|
||||
t2->place = t3->place;
|
||||
token_destroy(t1);
|
||||
token_destroy(t3);
|
||||
tokenarray_remove(&tokens, num-1);
|
||||
tokenarray_remove(&tokens, num-3);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num >= 2 &&
|
||||
(num == 2 || isop(t3->tok) || t3->tok == T_LPAREN) &&
|
||||
isuop(t2->tok) &&
|
||||
t1->tok == T_VAL) {
|
||||
/* unary operator */
|
||||
t1->val = eval_uop(t2->tok, t1->val);
|
||||
t1->place = t2->place;
|
||||
token_destroy(t2);
|
||||
tokenarray_remove(&tokens, num-2);
|
||||
continue;
|
||||
}
|
||||
if (num >= 2 &&
|
||||
(num == 2 || isop(t3->tok) || t3->tok == T_LPAREN) &&
|
||||
t2->tok != T_LPAREN && t2->tok != T_VAL &&
|
||||
t1->tok == T_VAL) {
|
||||
complain(&t2->place, "Invalid unary operator");
|
||||
complain_fail();
|
||||
token_destroy(t2);
|
||||
tokenarray_remove(&tokens, num-2);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
t4 = (num >= 4) ? tokenarray_get(&tokens, num-4) : NULL;
|
||||
|
||||
if (num >= 4 &&
|
||||
t4->tok == T_VAL &&
|
||||
isbop(t3->tok) &&
|
||||
t2->tok == T_VAL) {
|
||||
/* binary operator */
|
||||
if (looser(t1->tok, t3->tok)) {
|
||||
t4->val = eval_bop(&t3->place,
|
||||
t4->val, t3->tok, t2->val);
|
||||
token_destroy(t2);
|
||||
token_destroy(t3);
|
||||
tokenarray_remove(&tokens, num-2);
|
||||
tokenarray_remove(&tokens, num-3);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
t5 = (num >= 5) ? tokenarray_get(&tokens, num-5) : NULL;
|
||||
t6 = (num >= 6) ? tokenarray_get(&tokens, num-6) : NULL;
|
||||
|
||||
if (num >= 6 &&
|
||||
t6->tok == T_VAL &&
|
||||
t5->tok == T_QUES &&
|
||||
t4->tok == T_VAL &&
|
||||
t3->tok == T_COLON &&
|
||||
t2->tok == T_VAL &&
|
||||
!isop(t1->tok)) {
|
||||
/* conditional expression */
|
||||
t6->val = t6->val ? t4->val : t2->val;
|
||||
token_destroy(t2);
|
||||
token_destroy(t3);
|
||||
token_destroy(t4);
|
||||
token_destroy(t5);
|
||||
tokenarray_remove(&tokens, num-2);
|
||||
tokenarray_remove(&tokens, num-3);
|
||||
tokenarray_remove(&tokens, num-4);
|
||||
tokenarray_remove(&tokens, num-5);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num >= 2 &&
|
||||
t2->tok == T_LPAREN &&
|
||||
t1->tok == T_RPAREN) {
|
||||
complain(&t1->place, "Value expected within ()");
|
||||
complain_fail();
|
||||
t1->tok = T_VAL;
|
||||
t1->val = 0;
|
||||
token_destroy(t1);
|
||||
tokenarray_remove(&tokens, num-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num >= 2 &&
|
||||
t2->tok == T_VAL &&
|
||||
t1->tok == T_VAL) {
|
||||
complain(&t1->place, "Operator expected");
|
||||
complain_fail();
|
||||
token_destroy(t1);
|
||||
tokenarray_remove(&tokens, num-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num >= 2 &&
|
||||
isop(t2->tok) &&
|
||||
t1->tok == T_EOF) {
|
||||
complain(&t1->place, "Value expected after operator");
|
||||
complain_fail();
|
||||
token_destroy(t2);
|
||||
tokenarray_remove(&tokens, num-2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num == 2 &&
|
||||
t2->tok == T_VAL &&
|
||||
t1->tok == T_RPAREN) {
|
||||
complain(&t1->place, "Excess right parenthesis");
|
||||
complain_fail();
|
||||
token_destroy(t1);
|
||||
tokenarray_remove(&tokens, num-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num == 3 &&
|
||||
t3->tok == T_LPAREN &&
|
||||
t2->tok == T_VAL &&
|
||||
t1->tok == T_EOF) {
|
||||
complain(&t1->place, "Unclosed left parenthesis");
|
||||
complain_fail();
|
||||
token_destroy(t3);
|
||||
tokenarray_remove(&tokens, num-3);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num == 2 &&
|
||||
t2->tok == T_VAL &&
|
||||
t1->tok == T_EOF) {
|
||||
/* accepting state */
|
||||
break;
|
||||
}
|
||||
|
||||
if (num >= 1 &&
|
||||
t1->tok == T_EOF) {
|
||||
/* any other configuration at eof is an error */
|
||||
complain(&t1->place, "Parse error");
|
||||
complain_fail();
|
||||
break;
|
||||
}
|
||||
|
||||
/* otherwise, wait for more input */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
token(struct place *p, enum tokens tok, int val)
|
||||
{
|
||||
struct token *t;
|
||||
|
||||
t = token_create(p, tok, val);
|
||||
|
||||
tokenarray_add(&tokens, t, NULL);
|
||||
tryreduce();
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
wordval(struct place *p, char *word)
|
||||
{
|
||||
unsigned long val;
|
||||
char *t;
|
||||
|
||||
if (word[0] >= '0' && word[0] <= '9') {
|
||||
errno = 0;
|
||||
val = strtoul(word, &t, 0);
|
||||
if (errno) {
|
||||
complain(p, "Invalid integer constant");
|
||||
complain_fail();
|
||||
return 0;
|
||||
}
|
||||
while (*t == 'U' || *t == 'L') {
|
||||
t++;
|
||||
}
|
||||
if (*t != '\0') {
|
||||
complain(p, "Trailing garbage after integer constant");
|
||||
complain_fail();
|
||||
return 0;
|
||||
}
|
||||
if (val > INT_MAX) {
|
||||
complain(p, "Integer constant too large");
|
||||
complain_fail();
|
||||
return INT_MAX;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/* if it's a symbol, warn and substitute 0. */
|
||||
if (warns.undef) {
|
||||
complain(p, "Warning: value of undefined symbol %s is 0",
|
||||
word);
|
||||
if (mode.werror) {
|
||||
complain_fail();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
check_word(struct place *p, char *expr, size_t pos, size_t *len_ret)
|
||||
{
|
||||
size_t len;
|
||||
int val;
|
||||
char tmp;
|
||||
|
||||
if (!strchr(alnum, expr[pos])) {
|
||||
return false;
|
||||
}
|
||||
len = strspn(expr + pos, alnum);
|
||||
tmp = expr[pos + len];
|
||||
expr[pos + len] = '\0';
|
||||
val = wordval(p, expr + pos);
|
||||
expr[pos + len] = tmp;
|
||||
token(p, T_VAL, val);
|
||||
*len_ret = len;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
check_tokens_2(struct place *p, char *expr, size_t pos)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i=0; i<num_tokens_2; i++) {
|
||||
if (expr[pos] == tokens_2[i].c1 &&
|
||||
expr[pos+1] == tokens_2[i].c2) {
|
||||
token(p, tokens_2[i].tok, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
check_tokens_1(struct place *p, char *expr, size_t pos)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i=0; i<num_tokens_1; i++) {
|
||||
if (expr[pos] == tokens_1[i].c1) {
|
||||
token(p, tokens_1[i].tok, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
tokenize(struct place *p, char *expr)
|
||||
{
|
||||
size_t pos, len;
|
||||
|
||||
pos = 0;
|
||||
while (expr[pos] != '\0') {
|
||||
len = strspn(expr+pos, ws);
|
||||
pos += len;
|
||||
p->column += len;
|
||||
/* trailing whitespace is supposed to have been pruned */
|
||||
assert(expr[pos] != '\0');
|
||||
if (check_word(p, expr, pos, &len)) {
|
||||
pos += len;
|
||||
p->column += len;
|
||||
continue;
|
||||
}
|
||||
if (check_tokens_2(p, expr, pos)) {
|
||||
pos += 2;
|
||||
p->column += 2;
|
||||
continue;
|
||||
}
|
||||
if (check_tokens_1(p, expr, pos)) {
|
||||
pos++;
|
||||
p->column++;
|
||||
continue;
|
||||
}
|
||||
complain(p, "Invalid character %u in #if-expression",
|
||||
(unsigned char)expr[pos]);
|
||||
complain_fail();
|
||||
pos++;
|
||||
p->column++;
|
||||
}
|
||||
token(p, T_EOF, 0);
|
||||
}
|
||||
|
||||
bool
|
||||
eval(struct place *p, char *expr)
|
||||
{
|
||||
struct token *t1, *t2;
|
||||
unsigned num;
|
||||
bool result;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "eval: %s\n", expr);
|
||||
#endif
|
||||
|
||||
tokenarray_init(&tokens);
|
||||
tokenize(p, expr);
|
||||
|
||||
result = false;
|
||||
num = tokenarray_num(&tokens);
|
||||
if (num == 2) {
|
||||
t1 = tokenarray_get(&tokens, num-1);
|
||||
t2 = tokenarray_get(&tokens, num-2);
|
||||
if (t2->tok == T_VAL &&
|
||||
t1->tok == T_EOF) {
|
||||
result = t2->val != 0;
|
||||
}
|
||||
}
|
||||
|
||||
tokenarray_destroyall(&tokens);
|
||||
tokenarray_cleanup(&tokens);
|
||||
return result;
|
||||
}
|
32
cde/util/tradcpp/eval.h
Normal file
32
cde/util/tradcpp/eval.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool eval(struct place *p, char *expr);
|
420
cde/util/tradcpp/files.c
Normal file
420
cde/util/tradcpp/files.c
Normal file
|
@ -0,0 +1,420 @@
|
|||
/*-
|
||||
* Copyright (c) 2010, 2013 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "array.h"
|
||||
#include "mode.h"
|
||||
#include "place.h"
|
||||
#include "files.h"
|
||||
#include "directive.h"
|
||||
|
||||
struct incdir {
|
||||
const char *name;
|
||||
bool issystem;
|
||||
};
|
||||
|
||||
DECLARRAY(incdir, static UNUSED);
|
||||
DEFARRAY(incdir, static);
|
||||
|
||||
static struct incdirarray quotepath, bracketpath;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// management
|
||||
|
||||
static
|
||||
struct incdir *
|
||||
incdir_create(const char *name, bool issystem)
|
||||
{
|
||||
struct incdir *id;
|
||||
|
||||
id = domalloc(sizeof(*id));
|
||||
id->name = name;
|
||||
id->issystem = issystem;
|
||||
return id;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
incdir_destroy(struct incdir *id)
|
||||
{
|
||||
dofree(id, sizeof(*id));
|
||||
}
|
||||
|
||||
void
|
||||
files_init(void)
|
||||
{
|
||||
incdirarray_init("epath);
|
||||
incdirarray_init(&bracketpath);
|
||||
}
|
||||
|
||||
DESTROYALL_ARRAY(incdir, );
|
||||
|
||||
void
|
||||
files_cleanup(void)
|
||||
{
|
||||
incdirarray_destroyall("epath);
|
||||
incdirarray_cleanup("epath);
|
||||
incdirarray_destroyall(&bracketpath);
|
||||
incdirarray_cleanup(&bracketpath);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// path setup
|
||||
|
||||
void
|
||||
files_addquotepath(const char *dir, bool issystem)
|
||||
{
|
||||
struct incdir *id;
|
||||
|
||||
id = incdir_create(dir, issystem);
|
||||
incdirarray_add("epath, id, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
files_addbracketpath(const char *dir, bool issystem)
|
||||
{
|
||||
struct incdir *id;
|
||||
|
||||
id = incdir_create(dir, issystem);
|
||||
incdirarray_add(&bracketpath, id, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// parsing
|
||||
|
||||
/*
|
||||
* Find the end of the logical line. End of line characters that are
|
||||
* commented out do not count.
|
||||
*/
|
||||
static
|
||||
size_t
|
||||
findeol(const char *buf, size_t start, size_t limit)
|
||||
{
|
||||
size_t i;
|
||||
int incomment = 0;
|
||||
bool inquote = false;
|
||||
char quote = '\0';
|
||||
|
||||
for (i=start; i<limit; i++) {
|
||||
if (incomment) {
|
||||
if (i+1 < limit && buf[i] == '*' && buf[i+1] == '/') {
|
||||
i++;
|
||||
incomment = 0;
|
||||
}
|
||||
} else if (!inquote && i+1 < limit &&
|
||||
buf[i] == '/' && buf[i+1] == '*') {
|
||||
i++;
|
||||
incomment = 1;
|
||||
} else if (i+1 < limit &&
|
||||
buf[i] == '\\' && buf[i+1] != '\n') {
|
||||
i++;
|
||||
} else if (!inquote && (buf[i] == '"' || buf[i] == '\'')) {
|
||||
inquote = true;
|
||||
quote = buf[i];
|
||||
} else if (inquote && buf[i] == quote) {
|
||||
inquote = false;
|
||||
} else if (buf[i] == '\n') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned
|
||||
countnls(const char *buf, size_t start, size_t limit)
|
||||
{
|
||||
size_t i;
|
||||
unsigned count = 0;
|
||||
|
||||
for (i=start; i<limit; i++) {
|
||||
if (buf[i] == '\n') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
|
||||
{
|
||||
struct place linestartplace, nextlinestartplace, ptmp;
|
||||
size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp;
|
||||
ssize_t result;
|
||||
bool ateof = false;
|
||||
char *buf;
|
||||
|
||||
place_setfilestart(&linestartplace, pf);
|
||||
nextlinestartplace = linestartplace;
|
||||
|
||||
bufmax = 128;
|
||||
bufend = 0;
|
||||
linestart = 0;
|
||||
lineend = 0;
|
||||
buf = domalloc(bufmax);
|
||||
|
||||
while (1) {
|
||||
if (lineend >= bufend) {
|
||||
/* do not have a whole line in the buffer; read more */
|
||||
assert(bufend >= linestart);
|
||||
if (linestart > 0 && bufend > linestart) {
|
||||
/* slide to beginning of buffer */
|
||||
memmove(buf, buf+linestart, bufend-linestart);
|
||||
bufend -= linestart;
|
||||
lineend -= linestart;
|
||||
linestart = 0;
|
||||
}
|
||||
if (bufend >= bufmax) {
|
||||
/* need bigger buffer */
|
||||
buf = dorealloc(buf, bufmax, bufmax*2);
|
||||
bufmax = bufmax*2;
|
||||
}
|
||||
|
||||
if (ateof) {
|
||||
/* don't read again, in case it's a socket */
|
||||
result = 0;
|
||||
} else {
|
||||
result = read(fd, buf+bufend, bufmax - bufend);
|
||||
}
|
||||
|
||||
if (result == -1) {
|
||||
/* read error */
|
||||
complain(NULL, "%s: %s",
|
||||
name, strerror(errno));
|
||||
complain_fail();
|
||||
} else if (result == 0 && bufend == linestart) {
|
||||
/* eof */
|
||||
ateof = true;
|
||||
break;
|
||||
} else if (result == 0) {
|
||||
/* eof in middle of line */
|
||||
ateof = true;
|
||||
ptmp = linestartplace;
|
||||
ptmp.column += bufend - linestart;
|
||||
complain(&ptmp, "No newline at end of file");
|
||||
if (mode.werror) {
|
||||
complain_fail();
|
||||
}
|
||||
assert(bufend < bufmax);
|
||||
lineend = bufend++;
|
||||
buf[lineend] = '\n';
|
||||
} else {
|
||||
bufend += (size_t)result;
|
||||
lineend = findeol(buf, linestart, bufend);
|
||||
}
|
||||
/* loop in case we still don't have a whole line */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* have a line */
|
||||
assert(buf[lineend] == '\n');
|
||||
buf[lineend] = '\0';
|
||||
nextlinestart = lineend+1;
|
||||
nextlinestartplace.line++;
|
||||
|
||||
/* check for CR/NL */
|
||||
if (lineend > 0 && buf[lineend-1] == '\r') {
|
||||
buf[lineend-1] = '\0';
|
||||
lineend--;
|
||||
}
|
||||
|
||||
/* check for continuation line */
|
||||
if (lineend > 0 && buf[lineend-1]=='\\') {
|
||||
lineend--;
|
||||
tmp = nextlinestart - lineend;
|
||||
if (bufend > nextlinestart) {
|
||||
memmove(buf+lineend, buf+nextlinestart,
|
||||
bufend - nextlinestart);
|
||||
}
|
||||
bufend -= tmp;
|
||||
nextlinestart -= tmp;
|
||||
lineend = findeol(buf, linestart, bufend);
|
||||
/* might not have a whole line, so loop */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* line now goes from linestart to lineend */
|
||||
assert(buf[lineend] == '\0');
|
||||
|
||||
/* count how many commented-out newlines we swallowed */
|
||||
nextlinestartplace.line += countnls(buf, linestart, lineend);
|
||||
|
||||
/* if the line isn't empty, process it */
|
||||
if (lineend > linestart) {
|
||||
directive_gotline(&linestartplace,
|
||||
buf+linestart, lineend-linestart);
|
||||
}
|
||||
|
||||
linestart = nextlinestart;
|
||||
lineend = findeol(buf, linestart, bufend);
|
||||
linestartplace = nextlinestartplace;
|
||||
}
|
||||
|
||||
if (toplevel) {
|
||||
directive_goteof(&linestartplace);
|
||||
}
|
||||
dofree(buf, bufmax);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// path search
|
||||
|
||||
static
|
||||
char *
|
||||
mkfilename(struct place *place, const char *dir, const char *file)
|
||||
{
|
||||
size_t dlen, flen, rlen;
|
||||
char *ret;
|
||||
bool needslash = false;
|
||||
|
||||
if (dir == NULL) {
|
||||
dir = place_getparsedir(place);
|
||||
}
|
||||
|
||||
dlen = strlen(dir);
|
||||
flen = strlen(file);
|
||||
if (dlen > 0 && dir[dlen-1] != '/') {
|
||||
needslash = true;
|
||||
}
|
||||
|
||||
rlen = dlen + (needslash ? 1 : 0) + flen;
|
||||
ret = domalloc(rlen + 1);
|
||||
strcpy(ret, dir);
|
||||
if (needslash) {
|
||||
strcat(ret, "/");
|
||||
}
|
||||
strcat(ret, file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
file_tryopen(const char *file)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/* XXX check for non-regular files */
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
if (errno != ENOENT && errno != ENOTDIR) {
|
||||
complain(NULL, "%s: %s", file, strerror(errno));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
file_search(struct place *place, struct incdirarray *path, const char *name)
|
||||
{
|
||||
unsigned i, num;
|
||||
struct incdir *id;
|
||||
const struct placefile *pf;
|
||||
char *file;
|
||||
int fd;
|
||||
|
||||
assert(place != NULL);
|
||||
|
||||
if (name[0] == '/') {
|
||||
fd = file_tryopen(name);
|
||||
if (fd >= 0) {
|
||||
pf = place_addfile(place, name, true);
|
||||
file_read(pf, fd, name, false);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
num = incdirarray_num(path);
|
||||
for (i=0; i<num; i++) {
|
||||
id = incdirarray_get(path, i);
|
||||
file = mkfilename(place, id->name, name);
|
||||
fd = file_tryopen(file);
|
||||
if (fd >= 0) {
|
||||
pf = place_addfile(place, file, id->issystem);
|
||||
file_read(pf, fd, file, false);
|
||||
dostrfree(file);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
dostrfree(file);
|
||||
}
|
||||
}
|
||||
complain(place, "Include file %s not found", name);
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
void
|
||||
file_readquote(struct place *place, const char *name)
|
||||
{
|
||||
file_search(place, "epath, name);
|
||||
}
|
||||
|
||||
void
|
||||
file_readbracket(struct place *place, const char *name)
|
||||
{
|
||||
file_search(place, &bracketpath, name);
|
||||
}
|
||||
|
||||
void
|
||||
file_readabsolute(struct place *place, const char *name)
|
||||
{
|
||||
const struct placefile *pf;
|
||||
int fd;
|
||||
|
||||
assert(place != NULL);
|
||||
|
||||
if (name == NULL) {
|
||||
fd = STDIN_FILENO;
|
||||
pf = place_addfile(place, "<standard-input>", false);
|
||||
} else {
|
||||
fd = file_tryopen(name);
|
||||
if (fd < 0) {
|
||||
complain(NULL, "%s: %s", name, strerror(errno));
|
||||
die();
|
||||
}
|
||||
pf = place_addfile(place, name, false);
|
||||
}
|
||||
|
||||
file_read(pf, fd, name, true);
|
||||
|
||||
if (name != NULL) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
40
cde/util/tradcpp/files.h
Normal file
40
cde/util/tradcpp/files.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
struct place;
|
||||
|
||||
void files_init(void);
|
||||
void files_cleanup(void);
|
||||
|
||||
void files_addquotepath(const char *dir, bool issystem);
|
||||
void files_addbracketpath(const char *dir, bool issystem);
|
||||
|
||||
void file_readquote(struct place *, const char *name);
|
||||
void file_readbracket(struct place *, const char *name);
|
||||
void file_readabsolute(struct place *, const char *name);
|
39
cde/util/tradcpp/inlinedefs.h
Normal file
39
cde/util/tradcpp/inlinedefs.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2009 David A. Holland.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the Author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* 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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__)
|
||||
/* gcc's non-C99 inline semantics */
|
||||
#define C99INLINE extern inline
|
||||
#elif defined(__STDC__) && __STDC_VERSION__ >= 199901L
|
||||
/* C99 */
|
||||
#define C99INLINE inline
|
||||
#else
|
||||
/* something else; static inline is safest */
|
||||
#define C99INLINE static inline
|
||||
#endif
|
1202
cde/util/tradcpp/macro.c
Normal file
1202
cde/util/tradcpp/macro.c
Normal file
File diff suppressed because it is too large
Load diff
49
cde/util/tradcpp/macro.h
Normal file
49
cde/util/tradcpp/macro.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct place;
|
||||
|
||||
void macros_init(void);
|
||||
void macros_cleanup(void);
|
||||
|
||||
void macro_define_plain(struct place *, const char *macro,
|
||||
struct place *, const char *expansion);
|
||||
void macro_define_params(struct place *, const char *macro,
|
||||
struct place *, const char *params,
|
||||
struct place *, const char *expansion);
|
||||
void macro_undef(const char *macro);
|
||||
bool macro_isdefined(const char *macro);
|
||||
|
||||
char *macroexpand(struct place *, char *buf, size_t len, bool honordefined);
|
||||
|
||||
void macro_sendline(struct place *, char *buf, size_t len);
|
||||
void macro_sendeof(struct place *);
|
1090
cde/util/tradcpp/main.c
Normal file
1090
cde/util/tradcpp/main.c
Normal file
File diff suppressed because it is too large
Load diff
1
cde/util/tradcpp/make.jon.sh
Normal file
1
cde/util/tradcpp/make.jon.sh
Normal file
|
@ -0,0 +1 @@
|
|||
gcc -o tradcpp main.c files.c directive.c eval.c macro.c output.c place.c array.c utils.c
|
65
cde/util/tradcpp/mode.h
Normal file
65
cde/util/tradcpp/mode.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct mode {
|
||||
bool werror;
|
||||
bool input_allow_dollars;
|
||||
unsigned input_tabstop;
|
||||
bool do_stdinc;
|
||||
bool do_stddef;
|
||||
bool do_output;
|
||||
bool output_linenumbers;
|
||||
bool output_retain_comments;
|
||||
const char *output_file;
|
||||
bool do_depend;
|
||||
bool depend_report_system;
|
||||
bool depend_assume_generated;
|
||||
bool depend_issue_fakerules;
|
||||
bool depend_quote_target;
|
||||
const char *depend_target;
|
||||
const char *depend_file;
|
||||
bool do_macrolist;
|
||||
bool macrolist_include_stddef;
|
||||
bool macrolist_include_expansions;
|
||||
bool do_trace;
|
||||
bool trace_namesonly;
|
||||
bool trace_indented;
|
||||
};
|
||||
|
||||
struct warns {
|
||||
bool endiflabels;
|
||||
bool nestcomment;
|
||||
bool undef;
|
||||
bool unused;
|
||||
};
|
||||
|
||||
extern struct mode mode;
|
||||
extern struct warns warns;
|
193
cde/util/tradcpp/output.c
Normal file
193
cde/util/tradcpp/output.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "mode.h"
|
||||
#include "place.h"
|
||||
#include "output.h"
|
||||
|
||||
static int outputfd = -1;
|
||||
static bool incomment = false;
|
||||
static char *linebuf;
|
||||
static size_t linebufpos, linebufmax;
|
||||
static struct place linebufplace;
|
||||
|
||||
static
|
||||
void
|
||||
output_open(void)
|
||||
{
|
||||
if (mode.output_file == NULL) {
|
||||
outputfd = STDOUT_FILENO;
|
||||
} else {
|
||||
outputfd = open(mode.output_file, O_WRONLY|O_CREAT|O_TRUNC,
|
||||
0664);
|
||||
if (outputfd < 0) {
|
||||
complain(NULL, "%s: %s",
|
||||
mode.output_file, strerror(errno));
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
dowrite(const char *buf, size_t len)
|
||||
{
|
||||
size_t done;
|
||||
ssize_t result;
|
||||
static unsigned write_errors = 0;
|
||||
|
||||
if (!mode.do_output) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (outputfd < 0) {
|
||||
output_open();
|
||||
}
|
||||
|
||||
done = 0;
|
||||
while (done < len) {
|
||||
result = write(outputfd, buf+done, len-done);
|
||||
if (result == -1) {
|
||||
complain(NULL, "%s: write: %s",
|
||||
mode.output_file, strerror(errno));
|
||||
complain_failed();
|
||||
write_errors++;
|
||||
if (write_errors > 5) {
|
||||
complain(NULL, "%s: giving up",
|
||||
mode.output_file);
|
||||
die();
|
||||
}
|
||||
/* XXX is this really a good idea? */
|
||||
sleep(1);
|
||||
}
|
||||
done += (size_t)result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
filter_output(const char *buf, size_t len)
|
||||
{
|
||||
size_t pos, start;
|
||||
bool inesc = false;
|
||||
bool inquote = false;
|
||||
char quote = '\0';
|
||||
|
||||
start = 0;
|
||||
for (pos = 0; pos < len - 1; pos++) {
|
||||
if (!inquote && buf[pos] == '/' && buf[pos+1] == '*') {
|
||||
if (!incomment) {
|
||||
if (pos > start) {
|
||||
dowrite(buf + start, pos - start);
|
||||
}
|
||||
start = pos;
|
||||
pos += 2;
|
||||
incomment = true;
|
||||
/* cancel out the loop's pos++ */
|
||||
pos--;
|
||||
continue;
|
||||
}
|
||||
} else if (buf[pos] == '*' && buf[pos+1] == '/') {
|
||||
if (incomment) {
|
||||
pos += 2;
|
||||
if (mode.output_retain_comments) {
|
||||
dowrite(buf + start, pos - start);
|
||||
}
|
||||
start = pos;
|
||||
incomment = false;
|
||||
/* cancel out the loop's pos++ */
|
||||
pos--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (incomment) {
|
||||
/* nothing */
|
||||
} else if (inesc) {
|
||||
inesc = false;
|
||||
} else if (buf[pos] == '\\') {
|
||||
inesc = true;
|
||||
} else if (!inquote && (buf[pos] == '"' || buf[pos] == '\'')) {
|
||||
inquote = true;
|
||||
quote = buf[pos];
|
||||
} else if (inquote && buf[pos] == quote) {
|
||||
inquote = false;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
|
||||
if (pos > start) {
|
||||
if (!incomment || mode.output_retain_comments) {
|
||||
dowrite(buf + start, pos - start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
output(const struct place *p, const char *buf, size_t len)
|
||||
{
|
||||
size_t oldmax;
|
||||
|
||||
if (linebufpos + len > linebufmax) {
|
||||
oldmax = linebufmax;
|
||||
if (linebufmax == 0) {
|
||||
linebufmax = 64;
|
||||
}
|
||||
while (linebufpos + len > linebufmax) {
|
||||
linebufmax *= 2;
|
||||
}
|
||||
linebuf = dorealloc(linebuf, oldmax, linebufmax);
|
||||
}
|
||||
if (linebufpos == 0) {
|
||||
linebufplace = *p;
|
||||
}
|
||||
memcpy(linebuf + linebufpos, buf, len);
|
||||
linebufpos += len;
|
||||
|
||||
if (len == 1 && buf[0] == '\n') {
|
||||
filter_output(linebuf, linebufpos);
|
||||
linebufpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
output_eof(void)
|
||||
{
|
||||
if (mode.output_file != NULL && outputfd >= 0) {
|
||||
close(outputfd);
|
||||
}
|
||||
outputfd = -1;
|
||||
}
|
31
cde/util/tradcpp/output.h
Normal file
31
cde/util/tradcpp/output.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
void output(const struct place *p, const char *buf, size_t len);
|
||||
void output_eof(void);
|
241
cde/util/tradcpp/place.c
Normal file
241
cde/util/tradcpp/place.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "array.h"
|
||||
#include "place.h"
|
||||
|
||||
struct placefile {
|
||||
struct place includedfrom;
|
||||
char *dir;
|
||||
char *name;
|
||||
int depth;
|
||||
bool fromsystemdir;
|
||||
};
|
||||
DECLARRAY(placefile, static UNUSED);
|
||||
DEFARRAY(placefile, static);
|
||||
|
||||
static struct placefilearray placefiles;
|
||||
static bool overall_failure;
|
||||
|
||||
static const char *myprogname;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// seenfiles
|
||||
|
||||
static
|
||||
struct placefile *
|
||||
placefile_create(const struct place *from, const char *name,
|
||||
bool fromsystemdir)
|
||||
{
|
||||
struct placefile *pf;
|
||||
const char *s;
|
||||
size_t len;
|
||||
|
||||
pf = domalloc(sizeof(*pf));
|
||||
pf->includedfrom = *from;
|
||||
|
||||
s = strrchr(name, '/');
|
||||
len = (s == NULL) ? 0 : s - name;
|
||||
pf->dir = dostrndup(name, len);
|
||||
|
||||
pf->name = dostrdup(name);
|
||||
pf->fromsystemdir = fromsystemdir;
|
||||
|
||||
if (from->file != NULL) {
|
||||
pf->depth = from->file->depth + 1;
|
||||
} else {
|
||||
pf->depth = 1;
|
||||
}
|
||||
return pf;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
placefile_destroy(struct placefile *pf)
|
||||
{
|
||||
dostrfree(pf->name);
|
||||
dofree(pf, sizeof(*pf));
|
||||
}
|
||||
|
||||
DESTROYALL_ARRAY(placefile, );
|
||||
|
||||
const char *
|
||||
place_getparsedir(const struct place *place)
|
||||
{
|
||||
if (place->file == NULL) {
|
||||
return ".";
|
||||
}
|
||||
return place->file->dir;
|
||||
}
|
||||
|
||||
const struct placefile *
|
||||
place_addfile(const struct place *place, const char *file, bool issystem)
|
||||
{
|
||||
struct placefile *pf;
|
||||
|
||||
pf = placefile_create(place, file, issystem);
|
||||
placefilearray_add(&placefiles, pf, NULL);
|
||||
if (pf->depth > 120) {
|
||||
complain(place, "Maximum include nesting depth exceeded");
|
||||
die();
|
||||
}
|
||||
return pf;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// places
|
||||
|
||||
void
|
||||
place_setnowhere(struct place *p)
|
||||
{
|
||||
p->type = P_NOWHERE;
|
||||
p->file = NULL;
|
||||
p->line = 0;
|
||||
p->column = 0;
|
||||
}
|
||||
|
||||
void
|
||||
place_setbuiltin(struct place *p, unsigned num)
|
||||
{
|
||||
p->type = P_BUILTIN;
|
||||
p->file = NULL;
|
||||
p->line = num;
|
||||
p->column = 1;
|
||||
}
|
||||
|
||||
void
|
||||
place_setcommandline(struct place *p, unsigned line, unsigned column)
|
||||
{
|
||||
p->type = P_COMMANDLINE;
|
||||
p->file = NULL;
|
||||
p->line = line;
|
||||
p->column = column;
|
||||
}
|
||||
|
||||
void
|
||||
place_setfilestart(struct place *p, const struct placefile *pf)
|
||||
{
|
||||
p->type = P_FILE;
|
||||
p->file = pf;
|
||||
p->line = 1;
|
||||
p->column = 1;
|
||||
}
|
||||
|
||||
static
|
||||
const char *
|
||||
place_getname(const struct place *p)
|
||||
{
|
||||
switch (p->type) {
|
||||
case P_NOWHERE: return "<nowhere>";
|
||||
case P_BUILTIN: return "<built-in>";
|
||||
case P_COMMANDLINE: return "<command-line>";
|
||||
case P_FILE: return p->file->name;
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
place_printfrom(const struct place *p)
|
||||
{
|
||||
const struct place *from;
|
||||
|
||||
if (p->file == NULL) {
|
||||
return;
|
||||
}
|
||||
from = &p->file->includedfrom;
|
||||
if (from->type != P_NOWHERE) {
|
||||
place_printfrom(from);
|
||||
fprintf(stderr, "In file included from %s:%u:%u:\n",
|
||||
place_getname(from), from->line, from->column);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// complaints
|
||||
|
||||
void
|
||||
complain_init(const char *pn)
|
||||
{
|
||||
myprogname = pn;
|
||||
}
|
||||
|
||||
void
|
||||
complain(const struct place *p, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (p != NULL) {
|
||||
place_printfrom(p);
|
||||
fprintf(stderr, "%s:%u:%u: ", place_getname(p),
|
||||
p->line, p->column);
|
||||
} else {
|
||||
fprintf(stderr, "%s: ", myprogname);
|
||||
}
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
complain_fail(void)
|
||||
{
|
||||
overall_failure = true;
|
||||
}
|
||||
|
||||
bool
|
||||
complain_failed(void)
|
||||
{
|
||||
return overall_failure;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// module init and cleanup
|
||||
|
||||
void
|
||||
place_init(void)
|
||||
{
|
||||
placefilearray_init(&placefiles);
|
||||
}
|
||||
|
||||
void
|
||||
place_cleanup(void)
|
||||
{
|
||||
placefilearray_destroyall(&placefiles);
|
||||
placefilearray_cleanup(&placefiles);
|
||||
}
|
56
cde/util/tradcpp/place.h
Normal file
56
cde/util/tradcpp/place.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David A. Holland.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
enum places {
|
||||
P_NOWHERE,
|
||||
P_BUILTIN,
|
||||
P_COMMANDLINE,
|
||||
P_FILE,
|
||||
};
|
||||
struct place {
|
||||
enum places type;
|
||||
const struct placefile *file;
|
||||
unsigned line;
|
||||
unsigned column;
|
||||
};
|
||||
|
||||
void place_init(void);
|
||||
void place_cleanup(void);
|
||||
|
||||
void place_setnowhere(struct place *p);
|
||||
void place_setbuiltin(struct place *p, unsigned num);
|
||||
void place_setcommandline(struct place *p, unsigned word, unsigned column);
|
||||
void place_setfilestart(struct place *p, const struct placefile *pf);
|
||||
|
||||
const char *place_getparsedir(const struct place *incplace);
|
||||
|
||||
const struct placefile *place_addfile(const struct place *incplace,
|
||||
const char *name, bool fromsystemdir);
|
1
cde/util/tradcpp/tests/subdir/test.h
Normal file
1
cde/util/tradcpp/tests/subdir/test.h
Normal file
|
@ -0,0 +1 @@
|
|||
hello
|
1
cde/util/tradcpp/tests/t01.c
Normal file
1
cde/util/tradcpp/tests/t01.c
Normal file
|
@ -0,0 +1 @@
|
|||
glop.
|
1
cde/util/tradcpp/tests/t01.good
Normal file
1
cde/util/tradcpp/tests/t01.good
Normal file
|
@ -0,0 +1 @@
|
|||
glop.
|
2
cde/util/tradcpp/tests/t02.c
Normal file
2
cde/util/tradcpp/tests/t02.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define glop flop
|
||||
glop
|
1
cde/util/tradcpp/tests/t02.good
Normal file
1
cde/util/tradcpp/tests/t02.good
Normal file
|
@ -0,0 +1 @@
|
|||
flop
|
2
cde/util/tradcpp/tests/t03.c
Normal file
2
cde/util/tradcpp/tests/t03.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define glop(x) flop x
|
||||
glop(boo)
|
1
cde/util/tradcpp/tests/t03.good
Normal file
1
cde/util/tradcpp/tests/t03.good
Normal file
|
@ -0,0 +1 @@
|
|||
flop boo
|
2
cde/util/tradcpp/tests/t04.c
Normal file
2
cde/util/tradcpp/tests/t04.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define string(x) "x"
|
||||
string(abc)
|
1
cde/util/tradcpp/tests/t04.good
Normal file
1
cde/util/tradcpp/tests/t04.good
Normal file
|
@ -0,0 +1 @@
|
|||
"abc"
|
2
cde/util/tradcpp/tests/t05.c
Normal file
2
cde/util/tradcpp/tests/t05.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define concat(a, b) a/**/b
|
||||
concat(abc,def)
|
1
cde/util/tradcpp/tests/t05.good
Normal file
1
cde/util/tradcpp/tests/t05.good
Normal file
|
@ -0,0 +1 @@
|
|||
abcdef
|
2
cde/util/tradcpp/tests/t06.c
Normal file
2
cde/util/tradcpp/tests/t06.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
/*glop*/
|
||||
|
1
cde/util/tradcpp/tests/t06.good
Normal file
1
cde/util/tradcpp/tests/t06.good
Normal file
|
@ -0,0 +1 @@
|
|||
|
3
cde/util/tradcpp/tests/t07.c
Normal file
3
cde/util/tradcpp/tests/t07.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
/*
|
||||
* gloop
|
||||
*/
|
1
cde/util/tradcpp/tests/t07.good
Normal file
1
cde/util/tradcpp/tests/t07.good
Normal file
|
@ -0,0 +1 @@
|
|||
|
41
cde/util/tradcpp/tests/t08.c
Normal file
41
cde/util/tradcpp/tests/t08.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*#include <stdio.h>*/
|
||||
|
||||
int d =
|
||||
#if 2 > 1 ? 0 : 0 ? 1 : 1
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
|
||||
int e =
|
||||
#if (2 > 1 ? 0 : 0) ? 1 : 1
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
|
||||
int f =
|
||||
#if 2 > 1 ? 0 : (0 ? 1 : 1)
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int a, b, c;
|
||||
|
||||
a = 2 > 1 ? 0 : 0 ? 1 : 1;
|
||||
b = (2 > 1 ? 0 : 0) ? 1 : 1;
|
||||
c = 2 > 1 ? 0 : (0 ? 1 : 1);
|
||||
|
||||
printf("%d %d %d\n", a, b, c);
|
||||
printf("%d %d %d\n", d, e, f);
|
||||
|
||||
return 0;
|
||||
}
|
21
cde/util/tradcpp/tests/t08.good
Normal file
21
cde/util/tradcpp/tests/t08.good
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
int d =
|
||||
0
|
||||
;
|
||||
int e =
|
||||
1
|
||||
;
|
||||
int f =
|
||||
0
|
||||
;
|
||||
int
|
||||
main()
|
||||
{
|
||||
int a, b, c;
|
||||
a = 2 > 1 ? 0 : 0 ? 1 : 1;
|
||||
b = (2 > 1 ? 0 : 0) ? 1 : 1;
|
||||
c = 2 > 1 ? 0 : (0 ? 1 : 1);
|
||||
printf("%d %d %d\n", a, b, c);
|
||||
printf("%d %d %d\n", d, e, f);
|
||||
return 0;
|
||||
}
|
6
cde/util/tradcpp/tests/t09.c
Normal file
6
cde/util/tradcpp/tests/t09.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define STOP */
|
||||
#define START /*
|
||||
|
||||
/*
|
||||
* blah blah blah STOP fnord START goop moop
|
||||
*/
|
0
cde/util/tradcpp/tests/t09.good
Normal file
0
cde/util/tradcpp/tests/t09.good
Normal file
3
cde/util/tradcpp/tests/t10.c
Normal file
3
cde/util/tradcpp/tests/t10.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define mac(r)o
|
||||
mac(3)
|
||||
mac()
|
2
cde/util/tradcpp/tests/t10.good
Normal file
2
cde/util/tradcpp/tests/t10.good
Normal file
|
@ -0,0 +1,2 @@
|
|||
o
|
||||
o
|
2
cde/util/tradcpp/tests/t11.c
Normal file
2
cde/util/tradcpp/tests/t11.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define BOO BOO
|
||||
BOO
|
1
cde/util/tradcpp/tests/t11.good
Normal file
1
cde/util/tradcpp/tests/t11.good
Normal file
|
@ -0,0 +1 @@
|
|||
BOO
|
2
cde/util/tradcpp/tests/t12.c
Normal file
2
cde/util/tradcpp/tests/t12.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define BOO(yah) BOO(yah)
|
||||
BOO(yah)
|
1
cde/util/tradcpp/tests/t12.good
Normal file
1
cde/util/tradcpp/tests/t12.good
Normal file
|
@ -0,0 +1 @@
|
|||
BOO(yah)
|
4
cde/util/tradcpp/tests/t13.c
Normal file
4
cde/util/tradcpp/tests/t13.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
#define FOO BAR
|
||||
*/
|
||||
FOO
|
2
cde/util/tradcpp/tests/t13.good
Normal file
2
cde/util/tradcpp/tests/t13.good
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
FOO
|
4
cde/util/tradcpp/tests/t14.c
Normal file
4
cde/util/tradcpp/tests/t14.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
#define FOO BAR */
|
||||
FOO
|
||||
FOO
|
3
cde/util/tradcpp/tests/t14.good
Normal file
3
cde/util/tradcpp/tests/t14.good
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
FOO
|
||||
FOO
|
3
cde/util/tradcpp/tests/t15.c
Normal file
3
cde/util/tradcpp/tests/t15.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define FOO /* BAR */ BAZ
|
||||
FOO
|
||||
FOO
|
2
cde/util/tradcpp/tests/t15.good
Normal file
2
cde/util/tradcpp/tests/t15.good
Normal file
|
@ -0,0 +1,2 @@
|
|||
BAZ
|
||||
BAZ
|
11
cde/util/tradcpp/tests/t16.c
Normal file
11
cde/util/tradcpp/tests/t16.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#define a() x
|
||||
a()
|
||||
a ()
|
||||
#define b(p) p
|
||||
x/**/b(1)/**/x
|
||||
x/**/b (1)/**/x
|
||||
x/**/b()/**/x
|
||||
#define c(p,q) p/**/q
|
||||
x/**/c(1,2)/**/x
|
||||
x/**/c(1)/**/x
|
||||
x/**/c()/**/x
|
11
cde/util/tradcpp/tests/t16.good
Normal file
11
cde/util/tradcpp/tests/t16.good
Normal file
|
@ -0,0 +1,11 @@
|
|||
x
|
||||
x
|
||||
x1x
|
||||
x1x
|
||||
xx
|
||||
x12x
|
||||
t16.c:10:1: Wrong number of arguments for macro c; found 1, expected 2
|
||||
x1x
|
||||
t16.c:11:1: Wrong number of arguments for macro c; found 0, expected 2
|
||||
xx
|
||||
FAILED
|
2
cde/util/tradcpp/tests/t17.c
Normal file
2
cde/util/tradcpp/tests/t17.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define file "subdir/test.h"
|
||||
#include file
|
1
cde/util/tradcpp/tests/t17.good
Normal file
1
cde/util/tradcpp/tests/t17.good
Normal file
|
@ -0,0 +1 @@
|
|||
hello
|
2
cde/util/tradcpp/tests/t18.c
Normal file
2
cde/util/tradcpp/tests/t18.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#if FOO /* ignore me */
|
||||
#endif
|
0
cde/util/tradcpp/tests/t18.good
Normal file
0
cde/util/tradcpp/tests/t18.good
Normal file
3
cde/util/tradcpp/tests/t19.c
Normal file
3
cde/util/tradcpp/tests/t19.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define foo /* comment continues
|
||||
into the next line */ baz
|
||||
baz
|
1
cde/util/tradcpp/tests/t19.good
Normal file
1
cde/util/tradcpp/tests/t19.good
Normal file
|
@ -0,0 +1 @@
|
|||
baz
|
1
cde/util/tradcpp/tests/t20.c
Normal file
1
cde/util/tradcpp/tests/t20.c
Normal file
|
@ -0,0 +1 @@
|
|||
#undef foo /* blah */
|
0
cde/util/tradcpp/tests/t20.good
Normal file
0
cde/util/tradcpp/tests/t20.good
Normal file
3
cde/util/tradcpp/tests/t21.c
Normal file
3
cde/util/tradcpp/tests/t21.c
Normal file
|
@ -0,0 +1,3 @@
|
|||
# define FOO BAR
|
||||
#undef FOO /* would be wrong */
|
||||
FOO
|
2
cde/util/tradcpp/tests/t21.good
Normal file
2
cde/util/tradcpp/tests/t21.good
Normal file
|
@ -0,0 +1,2 @@
|
|||
#undef BAR
|
||||
BAR
|
2
cde/util/tradcpp/tests/t22.c
Normal file
2
cde/util/tradcpp/tests/t22.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
pa/*
|
||||
*/ste
|
1
cde/util/tradcpp/tests/t22.good
Normal file
1
cde/util/tradcpp/tests/t22.good
Normal file
|
@ -0,0 +1 @@
|
|||
paste
|
8
cde/util/tradcpp/tests/t23.c
Normal file
8
cde/util/tradcpp/tests/t23.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
fnord1
|
||||
/*
|
||||
fnord2
|
||||
*/
|
||||
foo
|
||||
*/
|
||||
bar
|
4
cde/util/tradcpp/tests/t23.good
Normal file
4
cde/util/tradcpp/tests/t23.good
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
foo
|
||||
*/
|
||||
bar
|
67
cde/util/tradcpp/tests/t24.c
Normal file
67
cde/util/tradcpp/tests/t24.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
#if 0
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
right
|
||||
#endif
|
||||
|
||||
#if -1
|
||||
right
|
||||
#endif
|
||||
|
||||
#if 0 + 0
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 1 + 1
|
||||
right
|
||||
#endif
|
||||
|
||||
#if 1 - 1
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if -1 + 1
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 3 - 2 - 1
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 3 * 2 - 6
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 6 - 2 * 3
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 3 - 3 && 1
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 3 - 3 || 0
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 1 && 0
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 0 && 1
|
||||
wrong
|
||||
#endif
|
||||
|
||||
#if 1 || 0
|
||||
right
|
||||
#endif
|
||||
|
||||
#if 0 || 1
|
||||
right
|
||||
#endif
|
||||
|
||||
#if (0 || 1) && (0 || 0)
|
||||
wrong
|
||||
#endif
|
5
cde/util/tradcpp/tests/t24.good
Normal file
5
cde/util/tradcpp/tests/t24.good
Normal file
|
@ -0,0 +1,5 @@
|
|||
right
|
||||
right
|
||||
right
|
||||
right
|
||||
right
|
4
cde/util/tradcpp/tests/t25.c
Normal file
4
cde/util/tradcpp/tests/t25.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
#define FOO foo /*
|
||||
#undef FOO
|
||||
#define FOO bar */
|
||||
FOO
|
1
cde/util/tradcpp/tests/t25.good
Normal file
1
cde/util/tradcpp/tests/t25.good
Normal file
|
@ -0,0 +1 @@
|
|||
foo
|
4
cde/util/tradcpp/tests/t26.c
Normal file
4
cde/util/tradcpp/tests/t26.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
#define FOO foo
|
||||
FOO
|
||||
"FOO"
|
||||
'FOO'
|
3
cde/util/tradcpp/tests/t26.good
Normal file
3
cde/util/tradcpp/tests/t26.good
Normal file
|
@ -0,0 +1,3 @@
|
|||
foo
|
||||
"FOO"
|
||||
'FOO'
|
29
cde/util/tradcpp/tests/t27.c
Normal file
29
cde/util/tradcpp/tests/t27.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
1.
|
||||
#define A(a) a
|
||||
A();
|
||||
|
||||
2.
|
||||
#define B(a, b) (a,b)
|
||||
B(a, );
|
||||
B(, b);
|
||||
B( , );
|
||||
B(a,);
|
||||
B(,b);
|
||||
B(,);
|
||||
|
||||
3.
|
||||
#define C(a, b, c) (a,b,c)
|
||||
C(a, b, );
|
||||
C(a, , c);
|
||||
C(, , c);
|
||||
C(a, , );
|
||||
C(, b, );
|
||||
C(, , c);
|
||||
C(, , )
|
||||
C(a,b,);
|
||||
C(a,,c);
|
||||
C(,,c);
|
||||
C(a,,);
|
||||
C(,b,);
|
||||
C(,,c);
|
||||
C(,,)
|
24
cde/util/tradcpp/tests/t27.good
Normal file
24
cde/util/tradcpp/tests/t27.good
Normal file
|
@ -0,0 +1,24 @@
|
|||
1.
|
||||
;
|
||||
2.
|
||||
(a, );
|
||||
(, b);
|
||||
( , );
|
||||
(a,);
|
||||
(,b);
|
||||
(,);
|
||||
3.
|
||||
(a, b, );
|
||||
(a, , c);
|
||||
(, , c);
|
||||
(a, , );
|
||||
(, b, );
|
||||
(, , c);
|
||||
(, , )
|
||||
(a,b,);
|
||||
(a,,c);
|
||||
(,,c);
|
||||
(a,,);
|
||||
(,b,);
|
||||
(,,c);
|
||||
(,,)
|
53
cde/util/tradcpp/tests/t28.c
Normal file
53
cde/util/tradcpp/tests/t28.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
#if 1
|
||||
. right
|
||||
|
||||
# if 1
|
||||
.. right
|
||||
# elif 1
|
||||
.. wrong
|
||||
# elif 0
|
||||
.. wrong
|
||||
# else
|
||||
.. wrong
|
||||
# endif
|
||||
|
||||
#elif 1
|
||||
. wrong
|
||||
|
||||
# if 1
|
||||
.. wrong
|
||||
# elif 1
|
||||
.. wrong
|
||||
# elif 0
|
||||
.. wrong
|
||||
# else
|
||||
.. wrong
|
||||
# endif
|
||||
|
||||
#elif 0
|
||||
. wrong
|
||||
|
||||
# if 1
|
||||
.. wrong
|
||||
# elif 1
|
||||
.. wrong
|
||||
# elif 0
|
||||
.. wrong
|
||||
# else
|
||||
.. wrong
|
||||
# endif
|
||||
|
||||
#else
|
||||
. wrong
|
||||
|
||||
# if 1
|
||||
.. wrong
|
||||
# elif 1
|
||||
.. wrong
|
||||
# elif 0
|
||||
.. wrong
|
||||
# else
|
||||
.. wrong
|
||||
# endif
|
||||
|
||||
#endif
|
2
cde/util/tradcpp/tests/t28.good
Normal file
2
cde/util/tradcpp/tests/t28.good
Normal file
|
@ -0,0 +1,2 @@
|
|||
. right
|
||||
.. right
|
4
cde/util/tradcpp/tests/t29.c
Normal file
4
cde/util/tradcpp/tests/t29.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
#if 0
|
||||
# if this is a syntax error
|
||||
# endif
|
||||
#endif
|
0
cde/util/tradcpp/tests/t29.good
Normal file
0
cde/util/tradcpp/tests/t29.good
Normal file
2
cde/util/tradcpp/tests/t30.c
Normal file
2
cde/util/tradcpp/tests/t30.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define x(a,b,c) a;b;c;
|
||||
x((,),x,",")
|
1
cde/util/tradcpp/tests/t30.good
Normal file
1
cde/util/tradcpp/tests/t30.good
Normal file
|
@ -0,0 +1 @@
|
|||
(,);x;",";
|
6
cde/util/tradcpp/tests/t31.c
Normal file
6
cde/util/tradcpp/tests/t31.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
this line 'has /* no' comment */ in it
|
||||
|
||||
#define BELCH(x) 'x'
|
||||
"BELCH(123)": BELCH(123)
|
||||
'BELCH(123)': BELCH(123)
|
||||
|
3
cde/util/tradcpp/tests/t31.good
Normal file
3
cde/util/tradcpp/tests/t31.good
Normal file
|
@ -0,0 +1,3 @@
|
|||
this line 'has /* no' comment */ in it
|
||||
"BELCH(123)": '123'
|
||||
'BELCH(123)': '123'
|
21
cde/util/tradcpp/tests/t32.c
Normal file
21
cde/util/tradcpp/tests/t32.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
#define foo(x) "x"
|
||||
#define bar(x) 'x'
|
||||
#define baz frob
|
||||
foo(3)
|
||||
bar(3)
|
||||
foo(baz)
|
||||
bar(baz)
|
||||
"baz"
|
||||
'baz'
|
||||
"foo(baz)"
|
||||
"bar(baz)"
|
||||
|
||||
#define foo2(x) foo(x)
|
||||
#define bar2(x) bar(x)
|
||||
foo2(baz)
|
||||
bar2(baz)
|
||||
|
||||
#define foo3(x) foo2(x)
|
||||
#define bar3(x) bar2(x)
|
||||
foo3(baz)
|
||||
bar3(baz)
|
12
cde/util/tradcpp/tests/t32.good
Normal file
12
cde/util/tradcpp/tests/t32.good
Normal file
|
@ -0,0 +1,12 @@
|
|||
"3"
|
||||
'3'
|
||||
"baz"
|
||||
'baz'
|
||||
"baz"
|
||||
'baz'
|
||||
"foo(baz)"
|
||||
"bar(baz)"
|
||||
"baz"
|
||||
'baz'
|
||||
"baz"
|
||||
'baz'
|
6
cde/util/tradcpp/tests/t33.c
Normal file
6
cde/util/tradcpp/tests/t33.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* make sure that R gets defined and doesn't end up part of a string */
|
||||
#define Q "
|
||||
#define R r
|
||||
#define S "
|
||||
R
|
||||
Q
|
3
cde/util/tradcpp/tests/t33.good
Normal file
3
cde/util/tradcpp/tests/t33.good
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
r
|
||||
"
|
5
cde/util/tradcpp/tests/t34.c
Normal file
5
cde/util/tradcpp/tests/t34.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define Q "
|
||||
#define FOO foo
|
||||
Q FOO Q
|
||||
|
||||
|
1
cde/util/tradcpp/tests/t34.good
Normal file
1
cde/util/tradcpp/tests/t34.good
Normal file
|
@ -0,0 +1 @@
|
|||
" foo "
|
6
cde/util/tradcpp/tests/t35.c
Normal file
6
cde/util/tradcpp/tests/t35.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define Q "
|
||||
#define FOO foo
|
||||
|
||||
Q FOO Q 'I like "FOO" and "BAR"'
|
||||
|
||||
|
1
cde/util/tradcpp/tests/t35.good
Normal file
1
cde/util/tradcpp/tests/t35.good
Normal file
|
@ -0,0 +1 @@
|
|||
" foo " 'I like "FOO" and "BAR"'
|
7
cde/util/tradcpp/tests/t36.c
Normal file
7
cde/util/tradcpp/tests/t36.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
#define C(x) //**/* x */**//
|
||||
C(3)
|
||||
C(abc /* def */ ghi)
|
||||
|
||||
#define D(x) ///**/**/**///**/* x */**///**/**/**///
|
||||
D(3)
|
||||
D(abc /* def */ ghi)
|
4
cde/util/tradcpp/tests/t36.good
Normal file
4
cde/util/tradcpp/tests/t36.good
Normal file
|
@ -0,0 +1,4 @@
|
|||
/* 3 */
|
||||
/* abc ghi */
|
||||
//**/* 3 */**//
|
||||
//**/* abc ghi */**//
|
19
cde/util/tradcpp/tests/t37.c
Normal file
19
cde/util/tradcpp/tests/t37.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#define BC //**/*
|
||||
#define EC */**//
|
||||
|
||||
BC
|
||||
comment?
|
||||
EC
|
||||
|
||||
BC comment? EC
|
||||
|
||||
#define FOO(x) x
|
||||
FOO(abc BC def EC ghi)
|
||||
|
||||
#define BAR(x, y) x y
|
||||
BAR(abc BC def, ghi EC jkl)
|
||||
|
||||
BC
|
||||
#define BAZ baz
|
||||
EC
|
||||
BAZ
|
9
cde/util/tradcpp/tests/t37.good
Normal file
9
cde/util/tradcpp/tests/t37.good
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
comment?
|
||||
*/
|
||||
/* comment? */
|
||||
abc /* def */ ghi
|
||||
abc /* def ghi */ jkl
|
||||
/*
|
||||
*/
|
||||
baz
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue