mirror of
https://github.com/ptitSeb/box64.git
synced 2024-11-27 00:30:32 +00:00
[WRAPPERHELPER] Added box32 and line number support in the wrapperhelper (#1890)
This commit is contained in:
parent
703d19b256
commit
4715ef2633
1
.gitignore
vendored
1
.gitignore
vendored
@ -69,6 +69,7 @@ backup/
|
||||
/wrapperhelper/sanundefined
|
||||
/wrapperhelper/src/machine.gen
|
||||
/wrapperhelper/*.h
|
||||
!/wrapperhelper/example-libc.h
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
@ -25,7 +25,9 @@ To use the wrapper helper, run the following command in the folder containing th
|
||||
bin/wrapperhelper -I/path/to/system/include "path_to_support_file" "path_to_private.h" "path_to_private.h"
|
||||
```
|
||||
|
||||
You may add as many `-I` options as needed.
|
||||
You may add as many `-I` options as needed. The folders `include-override/<arch>` and `include-override/common` are always prioritized, as if they appeared first in the command line.
|
||||
|
||||
You may also use the `-32` and `-64` switches to generate `box32` or `box64` files respectively. Alterately, you can use the `--emu arch` and `--target arch` options to select more precisely the emlated and executing platforms, though only `x86`, `x86_64` and `aarch64` are supported for now. By default, everything is as if `-64` was supplied.
|
||||
|
||||
The first file is a `C` file containing every declaration required. The second file is the "requests" input. The third file is the output file, which may be a different file.
|
||||
|
||||
@ -100,30 +102,25 @@ The reading and writing of the `_private.h` files is implemented in `generator.c
|
||||
|
||||
## Known issues
|
||||
|
||||
This project only works for `box64`; more work is required for this to be compatible with `box32`.
|
||||
|
||||
Only native structures are read. This means that the current version of `wrapperhelper` does not detect an issue when a structure has different members or alignments in two different architectures.
|
||||
|
||||
No checking of signatures under `#ifdef`s is made.
|
||||
|
||||
Line numbers are missing entirely. For most errors, the corresponding file is not written with the error message.
|
||||
|
||||
Phase 5 is partially implemented, but could be greatly improved.
|
||||
|
||||
The following features are missing from the generator:
|
||||
- Large structures as a parameter
|
||||
- Large structure as a return type (more than 16 bytes)
|
||||
- Structures with at least two elements as a parameter
|
||||
- Large structure as a return type (more than 16 bytes on 64bits, or 8 bytes on 32bits)
|
||||
- Atomic types
|
||||
|
||||
The following features are missing from the preprocessor:
|
||||
- General token concatenation (though the concatenation of two `PTOK_IDENT` works without issue)
|
||||
- Stringify
|
||||
- Skipped unexpected token warnings
|
||||
- Proper out-of-memory error handling
|
||||
|
||||
The following features are missing from the parser:
|
||||
- `_Atomic(type-name)`
|
||||
- `_Alignas(type-name)` and `_Alignas(constant-expression)`
|
||||
- `(type-name){initializer-list}`
|
||||
- Old style function declarations
|
||||
- Function definitions are ignored, not parsed
|
||||
- Attributes are ignored everywhere (with a `#define __attribute__(_)`)
|
||||
|
@ -123,16 +123,16 @@
|
||||
//#define __BITINT_MAXWIDTH__ 65535
|
||||
//#define __CHAR16_TYPE__ short unsigned int
|
||||
//#define __CHAR32_TYPE__ unsigned int
|
||||
#define __INT8_C(c) c
|
||||
//#define __INT8_C(c) c
|
||||
#define __INT8_MAX__ 0x7f
|
||||
//#define __INT8_TYPE__ signed char
|
||||
#define __INT16_C(c) c
|
||||
//#define __INT16_C(c) c
|
||||
#define __INT16_MAX__ 0x7fff
|
||||
//#define __INT16_TYPE__ short int
|
||||
#define __INT32_C(c) c
|
||||
//#define __INT32_C(c) c
|
||||
#define __INT32_MAX__ 0x7fffffff
|
||||
//#define __INT32_TYPE__ int
|
||||
#define __INT64_C(c) c ## L
|
||||
//#define __INT64_C(c) c ## L
|
||||
#define __INT64_MAX__ 0x7fffffffffffffffL
|
||||
//#define __INT64_TYPE__ long int
|
||||
#define __INT_FAST8_MAX__ 0x7f
|
||||
|
@ -1,4 +1,2 @@
|
||||
// Ignore all attributes
|
||||
#define __attribute__(_)
|
||||
|
||||
#include_next "stdc-predef.h"
|
||||
|
55
wrapperhelper/include-override/x86/bits/pthreadtypes-arch.h
Normal file
55
wrapperhelper/include-override/x86/bits/pthreadtypes-arch.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* Copyright (C) 2002-2024 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _BITS_PTHREADTYPES_ARCH_H
|
||||
#define _BITS_PTHREADTYPES_ARCH_H 1
|
||||
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
#ifdef __x86_64__
|
||||
# if __WORDSIZE == 64
|
||||
# define __SIZEOF_PTHREAD_MUTEX_T 40
|
||||
# define __SIZEOF_PTHREAD_ATTR_T 56
|
||||
# define __SIZEOF_PTHREAD_RWLOCK_T 56
|
||||
# define __SIZEOF_PTHREAD_BARRIER_T 32
|
||||
# else
|
||||
# define __SIZEOF_PTHREAD_MUTEX_T 32
|
||||
# define __SIZEOF_PTHREAD_ATTR_T 32
|
||||
# define __SIZEOF_PTHREAD_RWLOCK_T 44
|
||||
# define __SIZEOF_PTHREAD_BARRIER_T 20
|
||||
# endif
|
||||
#else
|
||||
# define __SIZEOF_PTHREAD_MUTEX_T 24
|
||||
# define __SIZEOF_PTHREAD_ATTR_T 36
|
||||
# define __SIZEOF_PTHREAD_RWLOCK_T 32
|
||||
# define __SIZEOF_PTHREAD_BARRIER_T 20
|
||||
#endif
|
||||
#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
|
||||
#define __SIZEOF_PTHREAD_COND_T 48
|
||||
#define __SIZEOF_PTHREAD_CONDATTR_T 4
|
||||
#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
|
||||
#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
|
||||
|
||||
#define __LOCK_ALIGNMENT
|
||||
#define __ONCE_ALIGNMENT
|
||||
|
||||
#ifndef __x86_64__
|
||||
/* Extra attributes for the cleanup functions. */
|
||||
# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
|
||||
#endif
|
||||
|
||||
#endif /* bits/pthreadtypes.h */
|
401
wrapperhelper/include-override/x86/stdc-predef.h
Normal file
401
wrapperhelper/include-override/x86/stdc-predef.h
Normal file
@ -0,0 +1,401 @@
|
||||
// C standard
|
||||
#define __STDC__ 1
|
||||
#define __STDC_HOSTED__ 1
|
||||
#define __STDC_UTF_16__ 1
|
||||
#define __STDC_UTF_32__ 1
|
||||
#define __STDC_VERSION__ 201710L
|
||||
// Generic x86_64 infos
|
||||
#define __ELF__ 1
|
||||
#define __NO_INLINE__ 1
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#define __ORDER_PDP_ENDIAN__ 3412
|
||||
#define __PIC__ 2
|
||||
#define __pic__ 2
|
||||
#define __PIE__ 2
|
||||
#define __pie__ 2
|
||||
#define __USER_LABEL_PREFIX__
|
||||
#define __gnu_linux__ 1
|
||||
#define __linux__ 1
|
||||
#define __linux 1
|
||||
#define linux 1
|
||||
#define __unix__ 1
|
||||
#define __unix 1
|
||||
#define unix 1
|
||||
// GCC
|
||||
//#define __GCC_ASM_FLAG_OUTPUTS__ 1
|
||||
//#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_INT_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_LONG_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
|
||||
//#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
|
||||
//#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||
//#define __GCC_CONSTRUCTIVE_SIZE 64
|
||||
//#define __GCC_DESTRUCTIVE_SIZE 64
|
||||
//#define __GCC_HAVE_DWARF2_CFI_ASM 1
|
||||
//#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
|
||||
//#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
|
||||
//#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
|
||||
//#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
|
||||
//#define __GCC_IEC_559 2
|
||||
//#define __GCC_IEC_559_COMPLEX 2
|
||||
//#define __GNUC__ 14
|
||||
//#define __GNUC_EXECUTION_CHARSET_NAME "UTF-8"
|
||||
//#define __GNUC_MINOR__ 2
|
||||
//#define __GNUC_PATCHLEVEL__ 1
|
||||
//#define __GNUC_STDC_INLINE__ 1
|
||||
//#define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
|
||||
//#define __GXX_ABI_VERSION 1019
|
||||
//#define __PRAGMA_REDEFINE_EXTNAME 1
|
||||
//#define __VERSION__ "14.2.1 20240805"
|
||||
// Specific x86_64 architecture
|
||||
#define __FINITE_MATH_ONLY__ 0
|
||||
#define __HAVE_SPECULATION_SAFE_VALUE 1
|
||||
#define __ILP32__ 1
|
||||
#define _ILP32 1
|
||||
#define __REGISTER_PREFIX__
|
||||
#define __FXSR__ 1
|
||||
#define __LAHF_SAHF__ 1
|
||||
#define __MMX__ 1
|
||||
#define __SEG_FS 1
|
||||
#define __SEG_GS 1
|
||||
#define __SSE__ 1
|
||||
#define __SSE2__ 1
|
||||
#define __SSP_STRONG__ 3
|
||||
#define __code_model_32__ 1
|
||||
#define __i386__ 1
|
||||
#define __i386 1
|
||||
#define i386 1
|
||||
#define __k8__ 1
|
||||
#define __k8 1
|
||||
// Atomic
|
||||
#define __ATOMIC_RELAXED 0
|
||||
#define __ATOMIC_CONSUME 1
|
||||
#define __ATOMIC_ACQUIRE 2
|
||||
#define __ATOMIC_RELEASE 3
|
||||
#define __ATOMIC_ACQ_REL 4
|
||||
#define __ATOMIC_SEQ_CST 5
|
||||
#define __ATOMIC_HLE_ACQUIRE 65536
|
||||
#define __ATOMIC_HLE_RELEASE 131072
|
||||
// Metainfo on types
|
||||
#define __BIGGEST_ALIGNMENT__ 16
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __CHAR_BIT__ 8
|
||||
#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#define __SIZEOF_SHORT__ 2
|
||||
#define __SIZEOF_WCHAR_T__ 4
|
||||
#define __SIZEOF_INT__ 4
|
||||
#define __SIZEOF_WINT_T__ 4
|
||||
#define __SIZEOF_LONG__ 4
|
||||
#define __SIZEOF_LONG_LONG__ 8
|
||||
#define __SIZEOF_POINTER__ 4
|
||||
#define __SIZEOF_PTRDIFF_T__ 4
|
||||
#define __SIZEOF_SIZE_T__ 4
|
||||
#define __SIZEOF_FLOAT__ 4
|
||||
#define __SIZEOF_DOUBLE__ 8
|
||||
#define __SIZEOF_LONG_DOUBLE__ 12
|
||||
#define __SIZEOF_FLOAT80__ 12
|
||||
#define __SIZEOF_FLOAT128__ 16
|
||||
// Integers
|
||||
//#define __BITINT_MAXWIDTH__ 65535
|
||||
//#define __CHAR16_TYPE__ short unsigned int
|
||||
//#define __CHAR32_TYPE__ unsigned int
|
||||
//#define __INT8_C(c) c
|
||||
#define __INT8_MAX__ 0x7f
|
||||
//#define __INT8_TYPE__ signed char
|
||||
//#define __INT16_C(c) c
|
||||
#define __INT16_MAX__ 0x7fff
|
||||
//#define __INT16_TYPE__ short int
|
||||
//#define __INT32_C(c) c
|
||||
#define __INT32_MAX__ 0x7fffffff
|
||||
//#define __INT32_TYPE__ int
|
||||
//#define __INT64_C(c) c ## LL
|
||||
#define __INT64_MAX__ 0x7fffffffffffffffLL
|
||||
//#define __INT64_TYPE__ long long int
|
||||
#define __INT_FAST8_MAX__ 0x7f
|
||||
//#define __INT_FAST8_TYPE__ signed char
|
||||
#define __INT_FAST8_WIDTH__ 8
|
||||
#define __INT_FAST16_MAX__ 0x7fffffff
|
||||
//#define __INT_FAST16_TYPE__ int
|
||||
#define __INT_FAST16_WIDTH__ 32
|
||||
#define __INT_FAST32_MAX__ 0x7fffffff
|
||||
//#define __INT_FAST32_TYPE__ int
|
||||
#define __INT_FAST32_WIDTH__ 32
|
||||
#define __INT_FAST64_MAX__ 0x7fffffffffffffffLL
|
||||
//#define __INT_FAST64_TYPE__ long long int
|
||||
#define __INT_FAST64_WIDTH__ 64
|
||||
#define __INT_LEAST8_MAX__ 0x7f
|
||||
//#define __INT_LEAST8_TYPE__ signed char
|
||||
#define __INT_LEAST8_WIDTH__ 8
|
||||
#define __INT_LEAST16_MAX__ 0x7fff
|
||||
//#define __INT_LEAST16_TYPE__ short int
|
||||
#define __INT_LEAST16_WIDTH__ 16
|
||||
#define __INT_LEAST32_MAX__ 0x7fffffff
|
||||
//#define __INT_LEAST32_TYPE__ int
|
||||
#define __INT_LEAST32_WIDTH__ 32
|
||||
#define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL
|
||||
//#define __INT_LEAST64_TYPE__ long long int
|
||||
#define __INT_LEAST64_WIDTH__ 64
|
||||
#define __INT_MAX__ 0x7fffffff
|
||||
#define __INT_WIDTH__ 32
|
||||
#define __INTMAX_C(c) c ## LL
|
||||
#define __INTMAX_MAX__ 0x7fffffffffffffffLL
|
||||
//#define __INTMAX_TYPE__ long long int
|
||||
#define __INTMAX_WIDTH__ 64
|
||||
#define __INTPTR_MAX__ 0x7fffffff
|
||||
//#define __INTPTR_TYPE__ int
|
||||
#define __INTPTR_WIDTH__ 32
|
||||
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
|
||||
#define __LONG_LONG_WIDTH__ 64
|
||||
#define __LONG_MAX__ 0x7fffffffL
|
||||
#define __LONG_WIDTH__ 32
|
||||
#define __PTRDIFF_MAX__ 0x7fffffff
|
||||
//#define __PTRDIFF_TYPE__ int
|
||||
#define __PTRDIFF_WIDTH__ 32
|
||||
#define __SCHAR_MAX__ 0x7f
|
||||
#define __SCHAR_WIDTH__ 8
|
||||
#define __SHRT_MAX__ 0x7fff
|
||||
#define __SHRT_WIDTH__ 16
|
||||
#define __SIG_ATOMIC_MAX__ 0x7fffffff
|
||||
#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
|
||||
//#define __SIG_ATOMIC_TYPE__ int
|
||||
#define __SIG_ATOMIC_WIDTH__ 32
|
||||
#define __SIZE_MAX__ 0xffffffffU
|
||||
//#define __SIZE_TYPE__ unsigned int
|
||||
#define __SIZE_WIDTH__ 32
|
||||
#define __UINT8_C(c) c
|
||||
#define __UINT8_MAX__ 0xff
|
||||
//#define __UINT8_TYPE__ unsigned char
|
||||
#define __UINT16_C(c) c
|
||||
#define __UINT16_MAX__ 0xffff
|
||||
//#define __UINT16_TYPE__ short unsigned int
|
||||
#define __UINT32_C(c) c ## U
|
||||
#define __UINT32_MAX__ 0xffffffffU
|
||||
//#define __UINT32_TYPE__ unsigned int
|
||||
#define __UINT64_C(c) c ## ULL
|
||||
#define __UINT64_MAX__ 0xffffffffffffffffULL
|
||||
//#define __UINT64_TYPE__ long long unsigned int
|
||||
#define __UINT_FAST8_MAX__ 0xff
|
||||
//#define __UINT_FAST8_TYPE__ unsigned char
|
||||
#define __UINT_FAST16_MAX__ 0xffffffffU
|
||||
//#define __UINT_FAST16_TYPE__ unsigned int
|
||||
#define __UINT_FAST32_MAX__ 0xffffffffU
|
||||
//#define __UINT_FAST32_TYPE__ unsigned int
|
||||
#define __UINT_FAST64_MAX__ 0xffffffffffffffffULL
|
||||
//#define __UINT_FAST64_TYPE__ long long unsigned int
|
||||
#define __UINT_LEAST8_MAX__ 0xff
|
||||
//#define __UINT_LEAST8_TYPE__ unsigned char
|
||||
#define __UINT_LEAST16_MAX__ 0xffff
|
||||
//#define __UINT_LEAST16_TYPE__ short unsigned int
|
||||
#define __UINT_LEAST32_MAX__ 0xffffffffU
|
||||
//#define __UINT_LEAST32_TYPE__ unsigned int
|
||||
#define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL
|
||||
//#define __UINT_LEAST64_TYPE__ long long unsigned int
|
||||
#define __UINTMAX_C(c) c ## ULL
|
||||
#define __UINTMAX_MAX__ 0xffffffffffffffffULL
|
||||
//#define __UINTMAX_TYPE__ long long unsigned int
|
||||
#define __UINTPTR_MAX__ 0xffffffffU
|
||||
//#define __UINTPTR_TYPE__ unsigned int
|
||||
#define __WCHAR_MAX__ 0x7fffffffL
|
||||
#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
|
||||
//#define __WCHAR_TYPE__ long int
|
||||
#define __WCHAR_WIDTH__ 32
|
||||
#define __WINT_MAX__ 0xffffffffU
|
||||
#define __WINT_MIN__ 0U
|
||||
//#define __WINT_TYPE__ unsigned int
|
||||
#define __WINT_WIDTH__ 32
|
||||
// Floats
|
||||
//#define __BFLT16_DECIMAL_DIG__ 4
|
||||
//#define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
|
||||
//#define __BFLT16_DIG__ 2
|
||||
//#define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
|
||||
//#define __BFLT16_HAS_DENORM__ 1
|
||||
//#define __BFLT16_HAS_INFINITY__ 1
|
||||
//#define __BFLT16_HAS_QUIET_NAN__ 1
|
||||
//#define __BFLT16_IS_IEC_60559__ 0
|
||||
//#define __BFLT16_MANT_DIG__ 8
|
||||
//#define __BFLT16_MAX_10_EXP__ 38
|
||||
//#define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
|
||||
//#define __BFLT16_MAX_EXP__ 128
|
||||
//#define __BFLT16_MIN_10_EXP__ (-37)
|
||||
//#define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
|
||||
//#define __BFLT16_MIN_EXP__ (-125)
|
||||
//#define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
|
||||
#define __DBL_DECIMAL_DIG__ 17
|
||||
#define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L)
|
||||
#define __DBL_DIG__ 15
|
||||
#define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L)
|
||||
#define __DBL_HAS_DENORM__ 1
|
||||
#define __DBL_HAS_INFINITY__ 1
|
||||
#define __DBL_HAS_QUIET_NAN__ 1
|
||||
#define __DBL_IS_IEC_60559__ 1
|
||||
#define __DBL_MANT_DIG__ 53
|
||||
#define __DBL_MAX_10_EXP__ 308
|
||||
#define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
|
||||
#define __DBL_MAX_EXP__ 1024
|
||||
#define __DBL_MIN_10_EXP__ (-307)
|
||||
#define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L)
|
||||
#define __DBL_MIN_EXP__ (-1021)
|
||||
#define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L)
|
||||
//#define __DEC32_EPSILON__ 1E-6DF
|
||||
//#define __DEC32_MANT_DIG__ 7
|
||||
//#define __DEC32_MAX__ 9.999999E96DF
|
||||
//#define __DEC32_MAX_EXP__ 97
|
||||
//#define __DEC32_MIN__ 1E-95DF
|
||||
//#define __DEC32_MIN_EXP__ (-94)
|
||||
//#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
|
||||
//#define __DEC64_EPSILON__ 1E-15DD
|
||||
//#define __DEC64_MANT_DIG__ 16
|
||||
//#define __DEC64_MAX__ 9.999999999999999E384DD
|
||||
//#define __DEC64_MAX_EXP__ 385
|
||||
//#define __DEC64_MIN__ 1E-383DD
|
||||
//#define __DEC64_MIN_EXP__ (-382)
|
||||
//#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
|
||||
//#define __DEC128_EPSILON__ 1E-33DL
|
||||
//#define __DEC128_MANT_DIG__ 34
|
||||
//#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
|
||||
//#define __DEC128_MAX_EXP__ 6145
|
||||
//#define __DEC128_MIN__ 1E-6143DL
|
||||
//#define __DEC128_MIN_EXP__ (-6142)
|
||||
//#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
|
||||
//#define __DEC_EVAL_METHOD__ 2
|
||||
//#define __DECIMAL_BID_FORMAT__ 1
|
||||
//#define __DECIMAL_DIG__ 21
|
||||
//#define __FLT16_DECIMAL_DIG__ 5
|
||||
//#define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
|
||||
//#define __FLT16_DIG__ 3
|
||||
//#define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
|
||||
//#define __FLT16_HAS_DENORM__ 1
|
||||
//#define __FLT16_HAS_INFINITY__ 1
|
||||
//#define __FLT16_HAS_QUIET_NAN__ 1
|
||||
//#define __FLT16_IS_IEC_60559__ 1
|
||||
//#define __FLT16_MANT_DIG__ 11
|
||||
//#define __FLT16_MAX_10_EXP__ 4
|
||||
//#define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
|
||||
//#define __FLT16_MAX_EXP__ 16
|
||||
//#define __FLT16_MIN_10_EXP__ (-4)
|
||||
//#define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
|
||||
//#define __FLT16_MIN_EXP__ (-13)
|
||||
//#define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
|
||||
//#define __FLT32_DECIMAL_DIG__ 9
|
||||
//#define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
|
||||
//#define __FLT32_DIG__ 6
|
||||
//#define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
|
||||
//#define __FLT32_HAS_DENORM__ 1
|
||||
//#define __FLT32_HAS_INFINITY__ 1
|
||||
//#define __FLT32_HAS_QUIET_NAN__ 1
|
||||
//#define __FLT32_IS_IEC_60559__ 1
|
||||
//#define __FLT32_MANT_DIG__ 24
|
||||
//#define __FLT32_MAX_10_EXP__ 38
|
||||
//#define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
|
||||
//#define __FLT32_MAX_EXP__ 128
|
||||
//#define __FLT32_MIN_10_EXP__ (-37)
|
||||
//#define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
|
||||
//#define __FLT32_MIN_EXP__ (-125)
|
||||
//#define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
|
||||
//#define __FLT32X_DECIMAL_DIG__ 17
|
||||
//#define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
|
||||
//#define __FLT32X_DIG__ 15
|
||||
//#define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
|
||||
//#define __FLT32X_HAS_DENORM__ 1
|
||||
//#define __FLT32X_HAS_INFINITY__ 1
|
||||
//#define __FLT32X_HAS_QUIET_NAN__ 1
|
||||
//#define __FLT32X_IS_IEC_60559__ 1
|
||||
//#define __FLT32X_MANT_DIG__ 53
|
||||
//#define __FLT32X_MAX_10_EXP__ 308
|
||||
//#define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
|
||||
//#define __FLT32X_MAX_EXP__ 1024
|
||||
//#define __FLT32X_MIN_10_EXP__ (-307)
|
||||
//#define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
|
||||
//#define __FLT32X_MIN_EXP__ (-1021)
|
||||
//#define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
|
||||
//#define __FLT64_DECIMAL_DIG__ 17
|
||||
//#define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
|
||||
//#define __FLT64_DIG__ 15
|
||||
//#define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
|
||||
//#define __FLT64_HAS_DENORM__ 1
|
||||
//#define __FLT64_HAS_INFINITY__ 1
|
||||
//#define __FLT64_HAS_QUIET_NAN__ 1
|
||||
//#define __FLT64_IS_IEC_60559__ 1
|
||||
//#define __FLT64_MANT_DIG__ 53
|
||||
//#define __FLT64_MAX_10_EXP__ 308
|
||||
//#define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
|
||||
//#define __FLT64_MAX_EXP__ 1024
|
||||
//#define __FLT64_MIN_10_EXP__ (-307)
|
||||
//#define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
|
||||
//#define __FLT64_MIN_EXP__ (-1021)
|
||||
//#define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
|
||||
//#define __FLT64X_DECIMAL_DIG__ 21
|
||||
//#define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
|
||||
//#define __FLT64X_DIG__ 18
|
||||
//#define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
|
||||
//#define __FLT64X_HAS_DENORM__ 1
|
||||
//#define __FLT64X_HAS_INFINITY__ 1
|
||||
//#define __FLT64X_HAS_QUIET_NAN__ 1
|
||||
//#define __FLT64X_IS_IEC_60559__ 1
|
||||
//#define __FLT64X_MANT_DIG__ 64
|
||||
//#define __FLT64X_MAX_10_EXP__ 4932
|
||||
//#define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
|
||||
//#define __FLT64X_MAX_EXP__ 16384
|
||||
//#define __FLT64X_MIN_10_EXP__ (-4931)
|
||||
//#define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
|
||||
//#define __FLT64X_MIN_EXP__ (-16381)
|
||||
//#define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
|
||||
//#define __FLT128_DECIMAL_DIG__ 36
|
||||
//#define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
|
||||
//#define __FLT128_DIG__ 33
|
||||
//#define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
|
||||
//#define __FLT128_HAS_DENORM__ 1
|
||||
//#define __FLT128_HAS_INFINITY__ 1
|
||||
//#define __FLT128_HAS_QUIET_NAN__ 1
|
||||
//#define __FLT128_IS_IEC_60559__ 1
|
||||
//#define __FLT128_MANT_DIG__ 113
|
||||
//#define __FLT128_MAX_10_EXP__ 4932
|
||||
//#define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
|
||||
//#define __FLT128_MAX_EXP__ 16384
|
||||
//#define __FLT128_MIN_10_EXP__ (-4931)
|
||||
//#define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
|
||||
//#define __FLT128_MIN_EXP__ (-16381)
|
||||
//#define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
|
||||
#define __FLT_DECIMAL_DIG__ 9
|
||||
#define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
|
||||
#define __FLT_DIG__ 6
|
||||
#define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
|
||||
#define __FLT_EVAL_METHOD__ 2
|
||||
#define __FLT_EVAL_METHOD_TS_18661_3__ 2
|
||||
#define __FLT_HAS_DENORM__ 1
|
||||
#define __FLT_HAS_INFINITY__ 1
|
||||
#define __FLT_HAS_QUIET_NAN__ 1
|
||||
#define __FLT_IS_IEC_60559__ 1
|
||||
#define __FLT_MANT_DIG__ 24
|
||||
#define __FLT_MAX_10_EXP__ 38
|
||||
#define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F
|
||||
#define __FLT_MAX_EXP__ 128
|
||||
#define __FLT_MIN_10_EXP__ (-37)
|
||||
#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
|
||||
#define __FLT_MIN_EXP__ (-125)
|
||||
#define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
|
||||
#define __FLT_RADIX__ 2
|
||||
#define __LDBL_DECIMAL_DIG__ 21
|
||||
#define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
|
||||
#define __LDBL_DIG__ 18
|
||||
#define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
|
||||
#define __LDBL_HAS_DENORM__ 1
|
||||
#define __LDBL_HAS_INFINITY__ 1
|
||||
#define __LDBL_HAS_QUIET_NAN__ 1
|
||||
#define __LDBL_IS_IEC_60559__ 1
|
||||
#define __LDBL_MANT_DIG__ 64
|
||||
#define __LDBL_MAX_10_EXP__ 4932
|
||||
#define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
|
||||
#define __LDBL_MAX_EXP__ 16384
|
||||
#define __LDBL_MIN_10_EXP__ (-4931)
|
||||
#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
|
||||
#define __LDBL_MIN_EXP__ (-16381)
|
||||
#define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
|
||||
|
||||
#include_next "stdc-predef.h"
|
@ -109,16 +109,16 @@
|
||||
//#define __BITINT_MAXWIDTH__ 65535
|
||||
//#define __CHAR16_TYPE__ short unsigned int
|
||||
//#define __CHAR32_TYPE__ unsigned int
|
||||
#define __INT8_C(c) c
|
||||
//#define __INT8_C(c) c
|
||||
#define __INT8_MAX__ 0x7f
|
||||
//#define __INT8_TYPE__ signed char
|
||||
#define __INT16_C(c) c
|
||||
//#define __INT16_C(c) c
|
||||
#define __INT16_MAX__ 0x7fff
|
||||
//#define __INT16_TYPE__ short int
|
||||
#define __INT32_C(c) c
|
||||
//#define __INT32_C(c) c
|
||||
#define __INT32_MAX__ 0x7fffffff
|
||||
//#define __INT32_TYPE__ int
|
||||
#define __INT64_C(c) c ## L
|
||||
//#define __INT64_C(c) c ## L
|
||||
#define __INT64_MAX__ 0x7fffffffffffffffL
|
||||
//#define __INT64_TYPE__ long int
|
||||
#define __INT_FAST8_MAX__ 0x7f
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,7 @@ typedef struct request_s {
|
||||
struct {
|
||||
string_t *typ;
|
||||
string_t *fun2;
|
||||
_Bool needs_S;
|
||||
} fun;
|
||||
struct {
|
||||
int has_size;
|
||||
@ -57,6 +58,13 @@ void references_print_check(const VECTOR(references) *refs);
|
||||
void output_from_references(FILE *f, const VECTOR(references) *reqs);
|
||||
|
||||
VECTOR(references) *references_from_file(const char *filename, FILE *f); // Takes ownership of f
|
||||
|
||||
// Simple solvers (emu and target have the same pointer size)
|
||||
int solve_request_simple(request_t *req, type_t *emu_typ, type_t *target_typ, khash_t(conv_map) *conv_map);
|
||||
int solve_request_map_simple(request_t *req, khash_t(decl_map) *emu_decl_map, khash_t(decl_map) *target_decl_map, khash_t(conv_map) *conv_map);
|
||||
int solve_references_simple(VECTOR(references) *reqs, khash_t(decl_map) *emu_decl_map, khash_t(decl_map) *target_decl_map, khash_t(conv_map) *conv_map);
|
||||
|
||||
// Complex solvers (emu and target have different pointer size)
|
||||
int solve_request(request_t *req, type_t *emu_typ, type_t *target_typ, khash_t(conv_map) *conv_map);
|
||||
int solve_request_map(request_t *req, khash_t(decl_map) *emu_decl_map, khash_t(decl_map) *target_decl_map, khash_t(conv_map) *conv_map);
|
||||
int solve_references(VECTOR(references) *reqs, khash_t(decl_map) *emu_decl_map, khash_t(decl_map) *target_decl_map, khash_t(conv_map) *conv_map);
|
||||
|
@ -156,44 +156,46 @@ const char *sym2str[LAST_SYM + 1] = {
|
||||
};
|
||||
|
||||
void preproc_token_print(const preproc_token_t *tok) {
|
||||
printf("Token: ");
|
||||
loginfo_print(&tok->loginfo, 50);
|
||||
switch (tok->tokt) {
|
||||
case PPTOK_INVALID:
|
||||
printf("Token: %7s %hhd (%c)\n", "#INVAL#", tok->tokv.c, (tok->tokv.c >= 0x20) && (tok->tokv.c < 0x7F) ? tok->tokv.c : '?');
|
||||
printf("%7s %hhd (%c)\n", "#INVAL#", tok->tokv.c, (tok->tokv.c >= 0x20) && (tok->tokv.c < 0x7F) ? tok->tokv.c : '?');
|
||||
break;
|
||||
case PPTOK_IDENT:
|
||||
printf("Token: %7s '%s'\n", "IDENT", string_content(tok->tokv.str));
|
||||
printf("%7s '%s'\n", "IDENT", string_content(tok->tokv.str));
|
||||
break;
|
||||
case PPTOK_IDENT_UNEXP:
|
||||
printf("Token: %7s '%s'\n", "IDENT'", string_content(tok->tokv.str));
|
||||
printf("%7s '%s'\n", "IDENT'", string_content(tok->tokv.str));
|
||||
break;
|
||||
case PPTOK_NUM:
|
||||
printf("Token: %7s '%s'\n", "NUM", string_content(tok->tokv.str));
|
||||
printf("%7s '%s'\n", "NUM", string_content(tok->tokv.str));
|
||||
break;
|
||||
case PPTOK_STRING:
|
||||
printf("Token: %7s %c%s%c\n", "STRING",
|
||||
printf("%7s %c%s%c\n", "STRING",
|
||||
tok->tokv.sisstr ? '"' : '\'', string_content(tok->tokv.sstr), tok->tokv.sisstr ? '"' : '\'');
|
||||
break;
|
||||
case PPTOK_INCL:
|
||||
printf("Token: %7s %c%s%c\n", "INCL",
|
||||
printf("%7s %c%s%c\n", "INCL",
|
||||
tok->tokv.sisstr ? '"' : '<', string_content(tok->tokv.sstr), tok->tokv.sisstr ? '"' : '>');
|
||||
break;
|
||||
case PPTOK_SYM:
|
||||
printf("Token: %7s %-3s (%u)\n", "SYM", sym2str[tok->tokv.sym], tok->tokv.sym);
|
||||
printf("%7s %-3s (%u)\n", "SYM", sym2str[tok->tokv.sym], tok->tokv.sym);
|
||||
break;
|
||||
case PPTOK_NEWLINE:
|
||||
printf("Token: %7s\n", "NEWLINE");
|
||||
printf("%7s\n", "NEWLINE");
|
||||
break;
|
||||
case PPTOK_BLANK:
|
||||
printf("Token: %7s\n", "\e[2;31m(blank)\e[m");
|
||||
printf("%7s\n", "\e[2;31m(blank)\e[m");
|
||||
break;
|
||||
case PPTOK_START_LINE_COMMENT:
|
||||
printf("Token: %7s\n", "\e[2;31m( // ) \e[m");
|
||||
printf("%7s\n", "\e[2;31m( // ) \e[m");
|
||||
break;
|
||||
case PPTOK_EOF:
|
||||
printf("Token: %7s\n", "EOF");
|
||||
printf("%7s\n", "EOF");
|
||||
break;
|
||||
default:
|
||||
printf("Token: ??? %u\n", tok->tokt);
|
||||
printf("??? %u\n", tok->tokt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,49 +268,51 @@ const char *kw2str[LAST_KEYWORD + 1] = {
|
||||
};
|
||||
|
||||
void proc_token_print(const proc_token_t *tok) {
|
||||
printf("Token: ");
|
||||
loginfo_print(&tok->loginfo, 50);
|
||||
switch (tok->tokt) {
|
||||
case PTOK_INVALID:
|
||||
printf("Token: %7s %hhd (%c)\n", "#INVAL#", tok->tokv.c, (tok->tokv.c >= 0x20) && (tok->tokv.c < 0x7F) ? tok->tokv.c : '?');
|
||||
printf("%7s %hhd (%c)\n", "#INVAL#", tok->tokv.c, (tok->tokv.c >= 0x20) && (tok->tokv.c < 0x7F) ? tok->tokv.c : '?');
|
||||
break;
|
||||
case PTOK_IDENT:
|
||||
printf("Token: %7s '%s'\n", "IDENT", string_content(tok->tokv.str));
|
||||
printf("%7s '%s'\n", "IDENT", string_content(tok->tokv.str));
|
||||
break;
|
||||
case PTOK_KEYWORD:
|
||||
printf("Token: %7s '%s' (%u)\n", "KEYWORD", kw2str[tok->tokv.kw], tok->tokv.kw);
|
||||
printf("%7s '%s' (%u)\n", "KEYWORD", kw2str[tok->tokv.kw], tok->tokv.kw);
|
||||
break;
|
||||
case PTOK_NUM:
|
||||
printf("Token: %7s '%s'\n", "NUM", string_content(tok->tokv.str));
|
||||
printf("%7s '%s'\n", "NUM", string_content(tok->tokv.str));
|
||||
break;
|
||||
case PTOK_STRING:
|
||||
printf("Token: %7s %c%s%c\n", "STRING",
|
||||
printf("%7s %c%s%c\n", "STRING",
|
||||
tok->tokv.sisstr ? '"' : '\'', string_content(tok->tokv.sstr), tok->tokv.sisstr ? '"' : '\'');
|
||||
break;
|
||||
case PTOK_SYM:
|
||||
printf("Token: %7s %-3s (%u)\n", "SYM", sym2str[tok->tokv.sym], tok->tokv.sym);
|
||||
printf("%7s %-3s (%u)\n", "SYM", sym2str[tok->tokv.sym], tok->tokv.sym);
|
||||
break;
|
||||
case PTOK_PRAGMA:
|
||||
switch (tok->tokv.pragma.typ) {
|
||||
case PRAGMA_ALLOW_INTS:
|
||||
printf("Token: %7s Allow ints\n", "PRAGMA");
|
||||
printf("%7s Allow ints\n", "PRAGMA");
|
||||
break;
|
||||
case PRAGMA_SIMPLE_SU:
|
||||
printf("Token: %7s Mark simple: struct or union %s is simple\n", "PRAGMA", string_content(tok->tokv.pragma.val));
|
||||
printf("%7s Mark simple: struct or union %s is simple\n", "PRAGMA", string_content(tok->tokv.pragma.val));
|
||||
break;
|
||||
case PRAGMA_EXPLICIT_CONV:
|
||||
printf("Token: %7s Relaxed explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val));
|
||||
printf("%7s Relaxed explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val));
|
||||
break;
|
||||
case PRAGMA_EXPLICIT_CONV_STRICT:
|
||||
printf("Token: %7s Strict explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val));
|
||||
printf("%7s Strict explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val));
|
||||
break;
|
||||
default:
|
||||
printf("Token: %7s ???\n", "PRAGMA");
|
||||
printf("%7s ??? %u\n", "PRAGMA", tok->tokv.pragma.typ);
|
||||
}
|
||||
break;
|
||||
case PTOK_EOF:
|
||||
printf("Token: %7s\n", "EOF");
|
||||
printf("%7s\n", "EOF");
|
||||
break;
|
||||
default:
|
||||
printf("Token: ??? %u\n", tok->tokt);
|
||||
printf("??? %u\n", tok->tokt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,14 +360,14 @@ khash_t(str2kw) *str2kw;
|
||||
|
||||
int init_str2kw(void) {
|
||||
if (!(str2kw = kh_init(str2kw))) {
|
||||
printf("Failed to create the string to keyword map (init)\n");
|
||||
log_memory("failed to create the string to keyword map (init)\n");
|
||||
return 0;
|
||||
}
|
||||
int iret; khiter_t it;
|
||||
for (enum token_keyword_type_e kw = 0; kw <= LAST_KEYWORD; ++kw) {
|
||||
it = kh_put(str2kw, str2kw, kw2str[kw], &iret);
|
||||
if (iret < 0) {
|
||||
printf("Failed to create the string to keyword map (keyword %u)\n", kw);
|
||||
log_memory("failed to create the string to keyword map (keyword %u)\n", kw);
|
||||
kh_destroy(str2kw, str2kw);
|
||||
return 0;
|
||||
}
|
||||
@ -372,7 +376,7 @@ int init_str2kw(void) {
|
||||
#define ADD_ALIAS(alias, k) \
|
||||
it = kh_put(str2kw, str2kw, #alias, &iret); \
|
||||
if (iret < 0) { \
|
||||
printf("Failed to create the string to keyword map (keyword alias " #alias ")\n"); \
|
||||
log_memory("failed to create the string to keyword map (keyword alias " #alias ")\n"); \
|
||||
kh_destroy(str2kw, str2kw); \
|
||||
return 0; \
|
||||
} \
|
||||
@ -404,8 +408,8 @@ void del_str2kw(void) {
|
||||
kh_destroy(str2kw, str2kw);
|
||||
}
|
||||
|
||||
// ptr_is_32bits is actially long_is_32bits
|
||||
int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits) {
|
||||
// ptr_is_32bits is actually long_is_32bits
|
||||
int num_constant_convert(loginfo_t *li, string_t *str, num_constant_t *cst, int ptr_is_32bits) {
|
||||
if (string_len(str) == 0) return 0; // Should never happen
|
||||
#define contains(c) strchr(string_content(str), c)
|
||||
if (contains('.')
|
||||
@ -430,10 +434,10 @@ int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits)
|
||||
ok = (endc == string_end(str));
|
||||
}
|
||||
if (!ok) {
|
||||
printf("Error: '%s' is not a valid number\n", string_content(str));
|
||||
log_error(li, "'%s' is not a valid number\n", string_content(str));
|
||||
return 0;
|
||||
} else if (errno == ERANGE) {
|
||||
printf("Warning: floating point constant is too large\n");
|
||||
log_warning(li, "floating point constant is too large\n");
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
@ -451,14 +455,14 @@ int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits)
|
||||
remove_suffix:
|
||||
if ((string_content(str)[endidx - 1] == 'l') || (string_content(str)[endidx - 1] == 'L')) {
|
||||
if (suffix_type & SUFFIX_SZ) {
|
||||
printf("Error: '%s' is not a valid number (invalid suffix)\n", string_content(str));
|
||||
log_error(li, "'%s' is not a valid number (invalid suffix)\n", string_content(str));
|
||||
return 0;
|
||||
}
|
||||
if (endidx == 1) return 0; // Should never happen
|
||||
if ((string_content(str)[endidx - 2] == 'l') || (string_content(str)[endidx - 2] == 'L')) {
|
||||
if (endidx == 2) return 0; // Should never happen
|
||||
if (string_content(str)[endidx - 2] != string_content(str)[endidx - 1]) {
|
||||
printf("Error: '%s' is not a valid number (invalid suffix)\n", string_content(str));
|
||||
log_error(li, "'%s' is not a valid number (invalid suffix)\n", string_content(str));
|
||||
return 0;
|
||||
}
|
||||
endidx -= 2;
|
||||
@ -471,7 +475,7 @@ int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits)
|
||||
}
|
||||
if ((string_content(str)[endidx - 1] == 'u') || (string_content(str)[endidx - 1] == 'U')) {
|
||||
if (suffix_type & SUFFIX_SGN) {
|
||||
printf("Error: '%s' is not a valid number (invalid suffix)\n", string_content(str));
|
||||
log_error(li, "'%s' is not a valid number (invalid suffix)\n", string_content(str));
|
||||
return 0;
|
||||
}
|
||||
endidx -= 1;
|
||||
@ -480,7 +484,7 @@ int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits)
|
||||
}
|
||||
// 0u has startidx=0 endidx=1
|
||||
if (endidx <= startidx) {
|
||||
printf("Error: '%s' is not a valid number\n", string_content(str));
|
||||
log_error(li, "'%s' is not a valid number\n", string_content(str));
|
||||
}
|
||||
for (size_t i = startidx; i < endidx; ++i) {
|
||||
if ((string_content(str)[i] >= '0') && (string_content(str)[i] <= ((base == 8) ? '7' : '9'))) {
|
||||
@ -490,7 +494,7 @@ int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits)
|
||||
} else if ((base == 16) && (string_content(str)[i] >= 'a') && (string_content(str)[i] <= 'f')) {
|
||||
ret = base * ret + 10 + (unsigned)(string_content(str)[i] - 'a');
|
||||
} else {
|
||||
printf("Error: '%s' is not a valid number\n", string_content(str));
|
||||
log_error(li, "'%s' is not a valid number\n", string_content(str));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -590,6 +594,151 @@ void expr_del(expr_t *e) {
|
||||
free(e);
|
||||
}
|
||||
|
||||
static void expr_print_aux(expr_t *e, int parent_level) {
|
||||
switch (e->typ) {
|
||||
case ETY_VAR:
|
||||
// Level 0, no parenthesis
|
||||
printf("%s", string_content(e->val.var));
|
||||
break;
|
||||
|
||||
case ETY_CONST:
|
||||
// Level 0, no parenthesis
|
||||
switch (e->val.cst.typ) {
|
||||
case NCT_FLOAT: printf("%ff", e->val.cst.val.f); break;
|
||||
case NCT_DOUBLE: printf("%f", e->val.cst.val.d); break;
|
||||
case NCT_LDOUBLE: printf("%Lfl", e->val.cst.val.l); break;
|
||||
case NCT_INT32: printf("%d", e->val.cst.val.i32); break;
|
||||
case NCT_UINT32: printf("%uu", e->val.cst.val.u32); break;
|
||||
case NCT_INT64: printf("%ldll", e->val.cst.val.i64); break;
|
||||
case NCT_UINT64: printf("%lullu", e->val.cst.val.u64); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ETY_CALL:
|
||||
// Level 1, no parenthesis
|
||||
expr_print_aux(e->val.call.fun, 1);
|
||||
printf("(");
|
||||
for (size_t i = 0; i < e->val.call.nargs; ++i) {
|
||||
expr_print_aux(e->val.call.fun, 15);
|
||||
}
|
||||
printf(")");
|
||||
break;
|
||||
|
||||
case ETY_ACCESS:
|
||||
// Level 1, no parenthesis
|
||||
expr_print_aux(e->val.access.val, 1);
|
||||
printf(".%s", string_content(e->val.access.member));
|
||||
break;
|
||||
|
||||
case ETY_PTRACCESS:
|
||||
// Level 1, no parenthesis
|
||||
expr_print_aux(e->val.access.val, 1);
|
||||
printf(".%s", string_content(e->val.access.member));
|
||||
break;
|
||||
|
||||
case ETY_UNARY: {
|
||||
const char *preop = NULL;
|
||||
switch (e->val.unary.typ) {
|
||||
case UOT_POSTINCR:
|
||||
// Level 1, no parenthesis
|
||||
expr_print_aux(e->val.unary.e, 1);
|
||||
printf("++");
|
||||
break;
|
||||
case UOT_POSTDECR:
|
||||
// Level 1, no parenthesis
|
||||
expr_print_aux(e->val.unary.e, 1);
|
||||
printf("--");
|
||||
break;
|
||||
case UOT_PREINCR: preop = "++"; break;
|
||||
case UOT_PREDECR: preop = "--"; break;
|
||||
case UOT_REF: preop = "&"; break;
|
||||
case UOT_POS: preop = "+"; break;
|
||||
case UOT_NEG: preop = "-"; break;
|
||||
case UOT_DEREF: preop = "*"; break;
|
||||
case UOT_ANOT: preop = "~"; break;
|
||||
case UOT_BNOT: preop = "!"; break;
|
||||
}
|
||||
if (preop) {
|
||||
if (parent_level < 2) printf("(");
|
||||
printf("%s", preop);
|
||||
expr_print_aux(e->val.unary.e, 2);
|
||||
if (parent_level < 2) printf(")");
|
||||
}
|
||||
break; }
|
||||
|
||||
case ETY_BINARY: {
|
||||
const char *midop, *postop = NULL;
|
||||
int mlevel, llevel, rlevel;
|
||||
switch (e->val.binary.typ) {
|
||||
case BOT_ADD: mlevel = 5; llevel = 5; rlevel = 4; midop = " + "; break;
|
||||
case BOT_SUB: mlevel = 5; llevel = 5; rlevel = 4; midop = " - "; break;
|
||||
case BOT_MUL: mlevel = 4; llevel = 4; rlevel = 3; midop = " * "; break;
|
||||
case BOT_DIV: mlevel = 4; llevel = 4; rlevel = 3; midop = " / "; break;
|
||||
case BOT_MOD: mlevel = 4; llevel = 4; rlevel = 3; midop = " % "; break;
|
||||
case BOT_LSH: mlevel = 6; llevel = 6; rlevel = 5; midop = " << "; break;
|
||||
case BOT_RSH: mlevel = 6; llevel = 6; rlevel = 5; midop = " >> "; break;
|
||||
case BOT_LT: mlevel = 7; llevel = 7; rlevel = 6; midop = " < "; break;
|
||||
case BOT_GT: mlevel = 7; llevel = 7; rlevel = 6; midop = " > "; break;
|
||||
case BOT_LE: mlevel = 7; llevel = 7; rlevel = 6; midop = " <= "; break;
|
||||
case BOT_GE: mlevel = 7; llevel = 7; rlevel = 6; midop = " >= "; break;
|
||||
case BOT_EQ: mlevel = 8; llevel = 8; rlevel = 7; midop = " == "; break;
|
||||
case BOT_NE: mlevel = 8; llevel = 8; rlevel = 7; midop = " != "; break;
|
||||
case BOT_AAND: mlevel = 9; llevel = 9; rlevel = 8; midop = " & "; break;
|
||||
case BOT_AXOR: mlevel = 10; llevel = 10; rlevel = 9; midop = " ^ "; break;
|
||||
case BOT_AOR: mlevel = 11; llevel = 11; rlevel = 10; midop = " | "; break;
|
||||
case BOT_BAND: mlevel = 12; llevel = 12; rlevel = 11; midop = " && "; break;
|
||||
case BOT_BOR: mlevel = 13; llevel = 13; rlevel = 12; midop = " || "; break;
|
||||
case BOT_ASSGN_EQ: mlevel = 15; llevel = 2; rlevel = 15; midop = " = "; break;
|
||||
case BOT_ASSGN_ADD: mlevel = 15; llevel = 2; rlevel = 15; midop = " += "; break;
|
||||
case BOT_ASSGN_SUB: mlevel = 15; llevel = 2; rlevel = 15; midop = " -= "; break;
|
||||
case BOT_ASSGN_MUL: mlevel = 15; llevel = 2; rlevel = 15; midop = " *= "; break;
|
||||
case BOT_ASSGN_DIV: mlevel = 15; llevel = 2; rlevel = 15; midop = " /= "; break;
|
||||
case BOT_ASSGN_MOD: mlevel = 15; llevel = 2; rlevel = 15; midop = " %= "; break;
|
||||
case BOT_ASSGN_LSH: mlevel = 15; llevel = 2; rlevel = 15; midop = " <<= "; break;
|
||||
case BOT_ASSGN_RSH: mlevel = 15; llevel = 2; rlevel = 15; midop = " >>= "; break;
|
||||
case BOT_ASSGN_AAND: mlevel = 15; llevel = 2; rlevel = 15; midop = " &= "; break;
|
||||
case BOT_ASSGN_AXOR: mlevel = 15; llevel = 2; rlevel = 15; midop = " ^= "; break;
|
||||
case BOT_ASSGN_AOR: mlevel = 15; llevel = 2; rlevel = 15; midop = " |= "; break;
|
||||
case BOT_COMMA: mlevel = 16; llevel = 16; rlevel = 15; midop = ", "; break;
|
||||
case BOT_ARRAY: mlevel = 1; llevel = 1; rlevel = 16; midop = "["; postop = "]"; break;
|
||||
default: mlevel = 17; llevel = rlevel = -1; midop = " ? "; break;
|
||||
}
|
||||
if (parent_level < mlevel) printf("(");
|
||||
expr_print_aux(e->val.binary.e1, llevel);
|
||||
printf("%s", midop);
|
||||
expr_print_aux(e->val.binary.e2, rlevel);
|
||||
if (postop) printf("%s", midop);
|
||||
if (parent_level < mlevel) printf(")");
|
||||
break; }
|
||||
|
||||
case ETY_TERNARY:
|
||||
switch (e->val.ternary.typ) {
|
||||
case TOT_COND:
|
||||
if (parent_level < 15) printf("(");
|
||||
expr_print_aux(e->val.ternary.e1, 14);
|
||||
printf(" ? ");
|
||||
expr_print_aux(e->val.ternary.e2, 16);
|
||||
expr_print_aux(e->val.ternary.e2, 15);
|
||||
printf(" : ");
|
||||
if (parent_level < 15) printf(")");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ETY_CAST:
|
||||
if (parent_level < 3) printf("(");
|
||||
printf("(");
|
||||
type_print(e->val.cast.typ);
|
||||
printf(")");
|
||||
expr_print(e->val.cast.e);
|
||||
if (parent_level < 3) printf(")");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void expr_print(expr_t *e) {
|
||||
return expr_print_aux(e, 16);
|
||||
}
|
||||
|
||||
void struct_del_weak(struct_t *st) {
|
||||
if (--st->nrefs) return;
|
||||
if (!st->tag) struct_del(st);
|
||||
@ -701,7 +850,7 @@ void struct_map_del(khash_t(struct_map) *map) {
|
||||
type_t *type_new(void) {
|
||||
type_t *ret = malloc(sizeof *ret);
|
||||
if (!ret) {
|
||||
printf("Failed to create a new type\n");
|
||||
log_memory("failed to create a new type\n");
|
||||
return NULL;
|
||||
}
|
||||
ret->szinfo.align = ret->szinfo.size = 0;
|
||||
@ -715,7 +864,7 @@ type_t *type_new(void) {
|
||||
type_t *type_new_ptr(type_t *target) {
|
||||
type_t *ret = malloc(sizeof *ret);
|
||||
if (!ret) {
|
||||
printf("Failed to create a new pointer type\n");
|
||||
log_memory("failed to create a new pointer type\n");
|
||||
return NULL;
|
||||
}
|
||||
ret->szinfo.align = ret->szinfo.size = 0;
|
||||
@ -755,7 +904,7 @@ int type_copy_into(type_t *dest, const type_t *ref) {
|
||||
}
|
||||
type_t **args = malloc(sizeof *args * ref->val.fun.nargs);
|
||||
if (!args) {
|
||||
printf("Error: failed to allocate new argument array\n");
|
||||
log_memory("failed to allocate new argument array\n");
|
||||
return 0;
|
||||
}
|
||||
for (size_t i = 0; i < ref->val.fun.nargs; ++i) {
|
||||
@ -777,7 +926,7 @@ int type_copy_into(type_t *dest, const type_t *ref) {
|
||||
struct_t *struct_new(int is_struct, string_t *tag) {
|
||||
struct_t *ret = malloc(sizeof *ret);
|
||||
if (!ret) {
|
||||
printf("Failed to create a new struct\n");
|
||||
log_memory("Error: failed to create a new struct\n");
|
||||
return NULL;
|
||||
}
|
||||
ret->is_struct = is_struct;
|
||||
@ -785,6 +934,7 @@ struct_t *struct_new(int is_struct, string_t *tag) {
|
||||
ret->is_defined = 0;
|
||||
ret->is_simple = 0;
|
||||
ret->nrefs = 1;
|
||||
ret->has_self_recursion = 0; // Undefined structures cannot have self recursion
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -831,7 +981,7 @@ int type_t_equal_aux(type_t *typ1, type_t *typ2, int is_strict) {
|
||||
if (!typ1->val.st->tag != !typ2->val.st->tag) return 0;
|
||||
if (typ1->val.st->tag) return !strcmp(string_content(typ1->val.st->tag), string_content(typ2->val.st->tag));
|
||||
if (!typ1->val.st->is_defined || !typ2->val.st->is_defined) {
|
||||
printf("Warning: incomplete anonymous structure/union\n");
|
||||
log_warning_nopos("comparing against incomplete anonymous structure/union\n");
|
||||
return 0;
|
||||
}
|
||||
if (typ1->val.st->nmembers != typ2->val.st->nmembers) return 0;
|
||||
@ -872,7 +1022,7 @@ type_t *type_try_merge(type_t *typ, khash_t(type_set) *set) {
|
||||
int iret;
|
||||
khiter_t it = kh_put(type_set, set, typ, &iret);
|
||||
if (iret < 0) {
|
||||
printf("Error: failed to add type to type_set\n");
|
||||
log_memory("Error: failed to add type to type_set\n");
|
||||
return NULL;
|
||||
} else if (iret == 0) {
|
||||
if (typ == kh_key(set, it)) return typ;
|
||||
@ -1030,11 +1180,12 @@ void struct_print(const struct_t *st) {
|
||||
}
|
||||
if (st->is_defined) {
|
||||
printf(
|
||||
"%s %s <with %zu members%s> { ",
|
||||
"%s %s <with %zu members%s%s> { ",
|
||||
st->is_struct ? "struct" : "union",
|
||||
st->tag ? string_content(st->tag) : "<no tag>",
|
||||
st->nmembers,
|
||||
st->has_incomplete ? ", with incomplete" : "");
|
||||
st->has_incomplete ? ", with incomplete" : "",
|
||||
st->has_self_recursion ? ", with self-recursion" : "");
|
||||
for (size_t i = 0; i < st->nmembers; ++i) {
|
||||
if (i) printf(", ");
|
||||
type_print(st->members[i].typ);
|
||||
@ -1052,29 +1203,29 @@ void struct_print(const struct_t *st) {
|
||||
file_t *file_new(machine_t *target) {
|
||||
file_t *ret = malloc(sizeof *ret);
|
||||
if (!ret) {
|
||||
printf("Failed to create a new translation unit structure (init)\n");
|
||||
log_memory("failed to create a new translation unit structure (init)\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret->struct_map = kh_init(struct_map))) {
|
||||
printf("Failed to create a new translation unit structure (structure map)\n");
|
||||
log_memory("failed to create a new translation unit structure (structure map)\n");
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret->type_map = kh_init(type_map))) {
|
||||
printf("Failed to create a new translation unit structure (type map)\n");
|
||||
log_memory("failed to create a new translation unit structure (type map)\n");
|
||||
kh_destroy(struct_map, ret->struct_map);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret->enum_map = kh_init(type_map))) {
|
||||
printf("Failed to create a new translation unit structure (enumeration map)\n");
|
||||
log_memory("failed to create a new translation unit structure (enumeration map)\n");
|
||||
kh_destroy(struct_map, ret->struct_map);
|
||||
kh_destroy(type_map, ret->type_map);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret->decl_map = kh_init(decl_map))) {
|
||||
printf("Failed to create a new translation unit structure (declaration map)\n");
|
||||
log_memory("failed to create a new translation unit structure (declaration map)\n");
|
||||
kh_destroy(struct_map, ret->struct_map);
|
||||
kh_destroy(type_map, ret->type_map);
|
||||
kh_destroy(type_map, ret->enum_map);
|
||||
@ -1082,7 +1233,7 @@ file_t *file_new(machine_t *target) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret->type_set = kh_init(type_set))) {
|
||||
printf("Failed to create a new translation unit structure (type set)\n");
|
||||
log_memory("failed to create a new translation unit structure (type set)\n");
|
||||
kh_destroy(struct_map, ret->struct_map);
|
||||
kh_destroy(type_map, ret->type_map);
|
||||
kh_destroy(type_map, ret->enum_map);
|
||||
@ -1091,7 +1242,7 @@ file_t *file_new(machine_t *target) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret->const_map = kh_init(const_map))) {
|
||||
printf("Failed to create a new translation unit structure (const map)\n");
|
||||
log_memory("failed to create a new translation unit structure (const map)\n");
|
||||
kh_destroy(struct_map, ret->struct_map);
|
||||
kh_destroy(type_map, ret->type_map);
|
||||
kh_destroy(type_map, ret->enum_map);
|
||||
@ -1101,7 +1252,7 @@ file_t *file_new(machine_t *target) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(ret->relaxed_type_conversion = kh_init(conv_map))) {
|
||||
printf("Failed to create a new translation unit structure (relaxed type conversion map)\n");
|
||||
log_memory("failed to create a new translation unit structure (relaxed type conversion map)\n");
|
||||
kh_destroy(struct_map, ret->struct_map);
|
||||
kh_destroy(type_map, ret->type_map);
|
||||
kh_destroy(type_map, ret->enum_map);
|
||||
@ -1117,7 +1268,7 @@ file_t *file_new(machine_t *target) {
|
||||
for (enum type_builtin_e i = 0; i < LAST_BUILTIN + 1; ++i) {
|
||||
type_t *t = type_new();
|
||||
if (!t) {
|
||||
printf("Failed to create a new translation unit structure (builtin type)\n");
|
||||
log_memory("failed to create a new translation unit structure (builtin type)\n");
|
||||
for (; i--;) {
|
||||
free(ret->builtins[i]);
|
||||
}
|
||||
@ -1135,11 +1286,14 @@ file_t *file_new(machine_t *target) {
|
||||
t->nrefs = 2;
|
||||
t->typ = TYPE_BUILTIN;
|
||||
t->val.builtin = i;
|
||||
validate_type(target, t);
|
||||
if (!target->has_int128 && ((i == BTT_INT128) || (i == BTT_SINT128) || (i == BTT_UINT128))) {
|
||||
t->converted = string_new_cstr("<invalid int128>");
|
||||
}
|
||||
validate_type(&(loginfo_t){0}, target, t);
|
||||
ret->builtins[i] = t;
|
||||
kh_put(type_set, ret->type_set, t, &iret);
|
||||
if (iret < 0) {
|
||||
printf("Failed to create a new translation unit structure (failed to add intrinsic type to type_set)\n");
|
||||
log_memory("failed to create a new translation unit structure (failed to add intrinsic type to type_set)\n");
|
||||
kh_destroy(struct_map, ret->struct_map);
|
||||
kh_destroy(type_map, ret->type_map);
|
||||
kh_destroy(conv_map, ret->relaxed_type_conversion);
|
||||
@ -1150,7 +1304,7 @@ file_t *file_new(machine_t *target) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
} else if (iret == 0) {
|
||||
printf("Failed to create a new translation unit structure (duplicate intrinsic type in type_set)\n");
|
||||
log_memory("failed to create a new translation unit structure (duplicate intrinsic type in type_set)\n");
|
||||
for (++i; i--;) {
|
||||
free(ret->builtins[i]);
|
||||
}
|
||||
@ -1167,23 +1321,23 @@ file_t *file_new(machine_t *target) {
|
||||
}
|
||||
// ret is valid and can now be deleted by file_del
|
||||
|
||||
// Add __builtin_va_list, __int128_t, __uint128_t as typedef
|
||||
// Add __builtin_va_list, __int128_t, __uint128_t as builtin typedef
|
||||
char *sdup;
|
||||
#define ADD_TYPEDEF(name, btt) \
|
||||
sdup = strdup(#name); \
|
||||
if (!sdup) { \
|
||||
printf("Failed to create a new translation unit structure (" #name " name)\n"); \
|
||||
log_memory("failed to create a new translation unit structure (" #name " name)\n"); \
|
||||
file_del(ret); \
|
||||
return NULL; \
|
||||
} \
|
||||
it = kh_put(type_map, ret->type_map, sdup, &iret); \
|
||||
if (iret < 0) { \
|
||||
printf("Failed to create a new translation unit structure (add " #name " typedef)\n"); \
|
||||
log_memory("failed to create a new translation unit structure (add " #name " typedef)\n"); \
|
||||
free(sdup); \
|
||||
file_del(ret); \
|
||||
return NULL; \
|
||||
} else if (iret == 0) { \
|
||||
printf("Failed to create a new translation unit structure (" #name " is already a typedef)\n"); \
|
||||
log_memory("failed to create a new translation unit structure (" #name " is already a typedef)\n"); \
|
||||
free(sdup); \
|
||||
file_del(ret); \
|
||||
return NULL; \
|
||||
@ -1191,8 +1345,10 @@ file_t *file_new(machine_t *target) {
|
||||
kh_val(ret->type_map, it) = ret->builtins[BTT_ ## btt]; \
|
||||
++ret->builtins[BTT_ ## btt]->nrefs;
|
||||
ADD_TYPEDEF(__builtin_va_list, VA_LIST)
|
||||
if (target->has_int128) {
|
||||
ADD_TYPEDEF(__int128_t, INT128)
|
||||
ADD_TYPEDEF(__uint128_t, UINT128)
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "cstring.h"
|
||||
#include "khash.h"
|
||||
#include "log.h"
|
||||
#include "machine.h"
|
||||
#include "vector.h"
|
||||
|
||||
@ -75,6 +76,7 @@ typedef struct preproc_token_s {
|
||||
PPTOK_START_LINE_COMMENT,
|
||||
PPTOK_EOF
|
||||
} tokt;
|
||||
loginfo_t loginfo;
|
||||
union {
|
||||
string_t *str;
|
||||
struct {
|
||||
@ -150,6 +152,7 @@ typedef struct proc_token_s {
|
||||
PTOK_PRAGMA,
|
||||
PTOK_EOF
|
||||
} tokt;
|
||||
loginfo_t loginfo;
|
||||
union proc_token_val_u {
|
||||
string_t *str;
|
||||
struct {
|
||||
@ -193,7 +196,7 @@ typedef struct num_constant_s {
|
||||
uint64_t u64;
|
||||
} val;
|
||||
} num_constant_t;
|
||||
int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits);
|
||||
int num_constant_convert(loginfo_t *li, string_t *str, num_constant_t *cst, int ptr_is_32bits);
|
||||
KHASH_MAP_DECLARE_STR(const_map, num_constant_t)
|
||||
|
||||
typedef struct expr_s {
|
||||
@ -288,6 +291,7 @@ typedef struct expr_s {
|
||||
} val;
|
||||
} expr_t;
|
||||
void expr_del(expr_t *e);
|
||||
void expr_print(expr_t *e);
|
||||
|
||||
typedef struct size_info_s {
|
||||
size_t size, align;
|
||||
@ -387,7 +391,8 @@ typedef struct st_member_s {
|
||||
type_t *typ;
|
||||
_Bool is_bitfield;
|
||||
size_t bitfield_width;
|
||||
// TODO: add byte_offset then check in generator against both archs for every named members
|
||||
// Filled by validate_type
|
||||
size_t byte_offset; unsigned char bit_offset;
|
||||
} st_member_t;
|
||||
typedef struct struct_s {
|
||||
string_t *tag;
|
||||
@ -396,6 +401,7 @@ typedef struct struct_s {
|
||||
int is_struct; // 0 = union, 1 = struct
|
||||
int is_simple; // Pointers to the structure (in 64 bits) are simple pointers
|
||||
int has_incomplete; // 1 if the last element of the structure is a VLA or if an element of the union recursively contains a VLA
|
||||
int has_self_recursion; // 1 if the structure contains a reference to itself
|
||||
size_t nmembers;
|
||||
st_member_t *members;
|
||||
} struct_t;
|
||||
|
80
wrapperhelper/src/log.c
Normal file
80
wrapperhelper/src/log.c
Normal file
@ -0,0 +1,80 @@
|
||||
#include "log.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void loginfo_print(const loginfo_t *info, int print_sz) {
|
||||
if (!info) {
|
||||
if (print_sz > 0) printf("%*s", print_sz, "");
|
||||
return;
|
||||
}
|
||||
if (!info->filename) {
|
||||
if (print_sz > 0) printf("%*s", print_sz, "");
|
||||
return;
|
||||
}
|
||||
print_sz -= printf("%s:", info->filename);
|
||||
if (!info->lineno) {
|
||||
print_sz -= printf(" ");
|
||||
if (print_sz > 0) printf("%*s", print_sz, "");
|
||||
return;
|
||||
}
|
||||
print_sz -= printf("%zu:", info->lineno);
|
||||
if (!info->colno) {
|
||||
print_sz -= printf(" ");
|
||||
if (print_sz > 0) printf("%*s", print_sz, "");
|
||||
return;
|
||||
}
|
||||
print_sz -= printf("%zu", info->colno);
|
||||
if (!info->lineno_end || ((info->lineno_end == info->lineno) && (info->colno_end == info->colno))) {
|
||||
print_sz -= printf(": ");
|
||||
if (print_sz > 0) printf("%*s", print_sz, "");
|
||||
return;
|
||||
}
|
||||
print_sz -= printf("-");
|
||||
if (info->lineno_end != info->lineno) {
|
||||
print_sz -= printf("%zu:", info->lineno_end);
|
||||
}
|
||||
print_sz -= printf("%zu: ", info->colno_end + 1);
|
||||
if (print_sz > 0) printf("%*s", print_sz, "");
|
||||
}
|
||||
|
||||
void log_error(const loginfo_t *info, const char *format, ...) {
|
||||
printf("Error: ");
|
||||
loginfo_print(info, 0);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
void log_internal(const loginfo_t *info, const char *format, ...) {
|
||||
printf("Internal error: ");
|
||||
loginfo_print(info, 0);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
void log_memory(const char *format, ...) {
|
||||
printf("Fatal error: memory error: ");
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
void log_TODO(const loginfo_t *info, const char *format, ...) {
|
||||
printf("Error: ");
|
||||
loginfo_print(info, 0);
|
||||
printf("TODO: ");
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
void log_warning(const loginfo_t *info, const char *format, ...) {
|
||||
printf("Warning: ");
|
||||
loginfo_print(info, 0);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
27
wrapperhelper/src/log.h
Normal file
27
wrapperhelper/src/log.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __LOG_H__
|
||||
#define __LOG_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct loginfo_s {
|
||||
const char *filename; // NULL = no log info
|
||||
size_t lineno; // 0 = no (start) line/column number
|
||||
size_t colno;
|
||||
size_t lineno_end; // 0 = no end line/column number
|
||||
size_t colno_end;
|
||||
} loginfo_t;
|
||||
|
||||
#define ATTRIBUTE_FORMAT(i, j) __attribute__((format(printf, i, j)))
|
||||
|
||||
void loginfo_print(const loginfo_t *info, int print_sz); // print_sz = min characters output
|
||||
void log_error(const loginfo_t *info, const char *format, ...) ATTRIBUTE_FORMAT(2, 3);
|
||||
void log_internal(const loginfo_t *info, const char *format, ...) ATTRIBUTE_FORMAT(2, 3);
|
||||
void log_memory(const char *format, ...) ATTRIBUTE_FORMAT(1, 2);
|
||||
void log_TODO(const loginfo_t *info, const char *format, ...) ATTRIBUTE_FORMAT(2, 3);
|
||||
void log_warning(const loginfo_t *info, const char *format, ...) ATTRIBUTE_FORMAT(2, 3);
|
||||
#define log_error_nopos(...) log_error(&(loginfo_t){0}, __VA_ARGS__)
|
||||
#define log_internal_nopos(...) log_internal(&(loginfo_t){0}, __VA_ARGS__)
|
||||
#define log_TODO_nopos(...) log_TODO(&(loginfo_t){0}, __VA_ARGS__)
|
||||
#define log_warning_nopos(...) log_warning(&(loginfo_t){0}, __VA_ARGS__)
|
||||
|
||||
#endif // __LOG_H__
|
@ -5,7 +5,7 @@
|
||||
#include "lang.h"
|
||||
|
||||
machine_t machine_x86_64;
|
||||
// machine_t machine_x86;
|
||||
machine_t machine_x86;
|
||||
machine_t machine_aarch64;
|
||||
|
||||
#define PASTE2(a, b) a ## b
|
||||
@ -18,7 +18,7 @@ machine_t machine_aarch64;
|
||||
#define PATHS_OFFSET_PRE 2 // There are two paths that are always included before any other
|
||||
#define ADD_PATH(path) \
|
||||
if (!(MACHINE_VAL.include_path[failure_id] = strdup(path))) { \
|
||||
printf("Failed to add include path to " MACHINE_STR " platform\n"); \
|
||||
log_memory("failed to add include path to " MACHINE_STR " platform\n"); \
|
||||
goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \
|
||||
} \
|
||||
++failure_id;
|
||||
@ -26,7 +26,7 @@ machine_t machine_aarch64;
|
||||
MACHINE_VAL.npaths = PATHS_OFFSET_PRE + npaths + paths_offset_post; \
|
||||
if (!(MACHINE_VAL.include_path = \
|
||||
malloc(MACHINE_VAL.npaths * sizeof *MACHINE_VAL.include_path))) { \
|
||||
printf("Failed to add include path to " MACHINE_STR " platform\n"); \
|
||||
log_memory("failed to add include path to " MACHINE_STR " platform\n"); \
|
||||
goto PASTE(failed_, PASTE(CUR_MACHINE, _nopath)); \
|
||||
} \
|
||||
failure_id = 0; \
|
||||
@ -48,24 +48,45 @@ int init_machines(size_t npaths, const char *const *extra_include_path) {
|
||||
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
|
||||
#define CUR_MACHINE x86_64
|
||||
machine_x86_64.size_long = 8;
|
||||
machine_x86_64.align_longdouble = 16;
|
||||
machine_x86_64.size_longdouble = 16;
|
||||
machine_x86_64.align_valist = 8;
|
||||
machine_x86_64.size_valist = 24;
|
||||
machine_x86_64.unsigned_char = 1;
|
||||
machine_x86_64.max_align = 8;
|
||||
machine_x86_64.has_int128 = 1;
|
||||
machine_x86_64.unsigned_char = 0;
|
||||
machine_x86_64.unnamed_bitfield_aligns = 0;
|
||||
INIT_PATHS
|
||||
#define DO_PATH ADD_PATH
|
||||
#include "machine.gen"
|
||||
#undef DO_PATH
|
||||
#undef CUR_MACHINE
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
|
||||
#define CUR_MACHINE x86
|
||||
machine_x86.size_long = 4;
|
||||
machine_x86.align_longdouble = 4;
|
||||
machine_x86.size_longdouble = 12;
|
||||
machine_x86.align_valist = 4;
|
||||
machine_x86.size_valist = 4;
|
||||
machine_x86.max_align = 4;
|
||||
machine_x86.has_int128 = 0;
|
||||
machine_x86.unsigned_char = 0;
|
||||
machine_x86.unnamed_bitfield_aligns = 0;
|
||||
INIT_PATHS
|
||||
#define DO_PATH ADD_PATH
|
||||
#include "machine.gen"
|
||||
#undef DO_PATH
|
||||
#undef CUR_MACHINE
|
||||
|
||||
#define CUR_MACHINE aarch64
|
||||
machine_aarch64.size_long = 8;
|
||||
machine_aarch64.align_longdouble = 16;
|
||||
machine_aarch64.size_longdouble = 16;
|
||||
machine_aarch64.align_valist = 8;
|
||||
machine_aarch64.size_valist = 32;
|
||||
machine_aarch64.unsigned_char = 0;
|
||||
machine_aarch64.max_align = 8;
|
||||
machine_aarch64.has_int128 = 1;
|
||||
machine_aarch64.unsigned_char = 1;
|
||||
machine_aarch64.unnamed_bitfield_aligns = 1;
|
||||
INIT_PATHS
|
||||
#define DO_PATH ADD_PATH
|
||||
@ -82,6 +103,13 @@ failed_aarch64_paths:
|
||||
}
|
||||
free(machine_aarch64.include_path);
|
||||
failed_aarch64_nopath:
|
||||
failure_id = machine_x86.npaths;
|
||||
failed_x86_paths:
|
||||
while (failure_id--) {
|
||||
free(machine_x86.include_path[failure_id]);
|
||||
}
|
||||
free(machine_x86.include_path);
|
||||
failed_x86_nopath:
|
||||
failure_id = machine_x86_64.npaths;
|
||||
failed_x86_64_paths:
|
||||
while (failure_id--) {
|
||||
@ -100,100 +128,143 @@ static void machine_del(machine_t *m) {
|
||||
}
|
||||
void del_machines(void) {
|
||||
machine_del(&machine_x86_64);
|
||||
machine_del(&machine_x86);
|
||||
machine_del(&machine_aarch64);
|
||||
}
|
||||
|
||||
machine_t *convert_machine_name(const char *archname) {
|
||||
if (!strcmp(archname, "x86_64"))
|
||||
return &machine_x86_64;
|
||||
if (!strcmp(archname, "x86"))
|
||||
return &machine_x86;
|
||||
if (!strcmp(archname, "aarch64"))
|
||||
return &machine_aarch64;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int validate_type(machine_t *target, type_t *typ) {
|
||||
void fill_self_recursion(type_t *typ, struct_t *st) {
|
||||
if (typ->_internal_use) return; // Recursion, but not self recursion
|
||||
typ->_internal_use = 1;
|
||||
switch (typ->typ) {
|
||||
case TYPE_BUILTIN: break;
|
||||
case TYPE_ARRAY:
|
||||
fill_self_recursion(typ->val.array.typ, st);
|
||||
break;
|
||||
case TYPE_PTR:
|
||||
fill_self_recursion(typ->val.typ, st);
|
||||
break;
|
||||
case TYPE_FUNCTION:
|
||||
if (typ->val.fun.nargs != (size_t)-1) {
|
||||
for (size_t i = 0; (i < typ->val.fun.nargs) && !st->has_self_recursion; ++i) {
|
||||
fill_self_recursion(typ->val.fun.args[i], st);
|
||||
}
|
||||
}
|
||||
if (!st->has_self_recursion) fill_self_recursion(typ->val.fun.ret, st);
|
||||
break;
|
||||
case TYPE_STRUCT_UNION:
|
||||
if (typ->val.st == st) {
|
||||
st->has_self_recursion = 1;
|
||||
break;
|
||||
}
|
||||
if (!typ->val.st->is_defined) break;
|
||||
for (size_t i = 0; (i < typ->val.st->nmembers) && !st->has_self_recursion; ++i) {
|
||||
fill_self_recursion(typ->val.st->members[i].typ, st);
|
||||
}
|
||||
break;
|
||||
case TYPE_ENUM:
|
||||
fill_self_recursion(typ->val.typ, st);
|
||||
break;
|
||||
}
|
||||
typ->_internal_use = 0;
|
||||
}
|
||||
|
||||
int validate_type(loginfo_t *loginfo, machine_t *target, type_t *typ) {
|
||||
if (typ->is_validated) return 1;
|
||||
typ->is_validated = 1;
|
||||
if (typ->is_restrict) {
|
||||
if (typ->typ != TYPE_PTR) {
|
||||
printf("Error: only pointers to object types may be restrict-qualified\n");
|
||||
log_error(loginfo, "only pointers to object types may be restrict-qualified\n");
|
||||
return 0;
|
||||
}
|
||||
if (typ->val.typ->typ == TYPE_FUNCTION) {
|
||||
printf("Error: only pointers to object types may be restrict-qualified\n");
|
||||
log_error(loginfo, "only pointers to object types may be restrict-qualified\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (typ->is_atomic) {
|
||||
if ((typ->typ == TYPE_ARRAY) || (typ->typ == TYPE_FUNCTION)) {
|
||||
printf("Error: array types and function types may not be atomic-qualified\n");
|
||||
log_error(loginfo, "array types and function types may not be atomic-qualified\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
switch (typ->typ) {
|
||||
case TYPE_BUILTIN:
|
||||
switch (typ->val.builtin) {
|
||||
case BTT_VOID: typ->szinfo.align = typ->szinfo.size = 0; break;
|
||||
case BTT_BOOL: typ->szinfo.align = typ->szinfo.size = 1; break;
|
||||
case BTT_CHAR: typ->szinfo.align = typ->szinfo.size = 1; break;
|
||||
case BTT_SCHAR: typ->szinfo.align = typ->szinfo.size = 1; break;
|
||||
case BTT_UCHAR: typ->szinfo.align = typ->szinfo.size = 1; break;
|
||||
case BTT_SHORT: typ->szinfo.align = typ->szinfo.size = 2; break;
|
||||
case BTT_SSHORT: typ->szinfo.align = typ->szinfo.size = 2; break;
|
||||
case BTT_USHORT: typ->szinfo.align = typ->szinfo.size = 2; break;
|
||||
case BTT_INT: typ->szinfo.align = typ->szinfo.size = 4; break;
|
||||
case BTT_SINT: typ->szinfo.align = typ->szinfo.size = 4; break;
|
||||
case BTT_UINT: typ->szinfo.align = typ->szinfo.size = 4; break;
|
||||
case BTT_LONG: typ->szinfo.align = typ->szinfo.size = target->size_long; break;
|
||||
case BTT_SLONG: typ->szinfo.align = typ->szinfo.size = target->size_long; break;
|
||||
case BTT_ULONG: typ->szinfo.align = typ->szinfo.size = target->size_long; break;
|
||||
case BTT_LONGLONG: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_SLONGLONG: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_ULONGLONG: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_INT128: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_SINT128: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_UINT128: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_S8: typ->szinfo.align = typ->szinfo.size = 1; break;
|
||||
case BTT_U8: typ->szinfo.align = typ->szinfo.size = 1; break;
|
||||
case BTT_S16: typ->szinfo.align = typ->szinfo.size = 2; break;
|
||||
case BTT_U16: typ->szinfo.align = typ->szinfo.size = 2; break;
|
||||
case BTT_S32: typ->szinfo.align = typ->szinfo.size = 4; break;
|
||||
case BTT_U32: typ->szinfo.align = typ->szinfo.size = 4; break;
|
||||
case BTT_S64: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_U64: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_FLOAT: typ->szinfo.align = typ->szinfo.size = 4; break;
|
||||
case BTT_CFLOAT: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_IFLOAT: typ->szinfo.align = typ->szinfo.size = 4; break;
|
||||
case BTT_DOUBLE: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_CDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_IDOUBLE: typ->szinfo.align = typ->szinfo.size = 8; break;
|
||||
case BTT_LONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_CLONGDOUBLE: typ->szinfo.align = 16; typ->szinfo.size = 32; break;
|
||||
case BTT_ILONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_FLOAT128: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_CFLOAT128: typ->szinfo.align = 16; typ->szinfo.size = 32; break;
|
||||
case BTT_IFLOAT128: typ->szinfo.align = typ->szinfo.size = 16; break;
|
||||
case BTT_VA_LIST: typ->szinfo.align = target->align_valist; typ->szinfo.size = target->size_valist; break;
|
||||
case BTT_VOID: typ->szinfo.align = typ->szinfo.size = 0; return 1;
|
||||
case BTT_BOOL:
|
||||
case BTT_CHAR:
|
||||
case BTT_SCHAR:
|
||||
case BTT_UCHAR:
|
||||
case BTT_S8:
|
||||
case BTT_U8: typ->szinfo.align = typ->szinfo.size = 1; return 1;
|
||||
case BTT_SHORT:
|
||||
case BTT_SSHORT:
|
||||
case BTT_USHORT:
|
||||
case BTT_S16:
|
||||
case BTT_U16: typ->szinfo.align = typ->szinfo.size = 2; return 1;
|
||||
case BTT_INT:
|
||||
case BTT_SINT:
|
||||
case BTT_UINT:
|
||||
case BTT_S32:
|
||||
case BTT_U32: typ->szinfo.align = typ->szinfo.size = 4; return 1;
|
||||
case BTT_LONGLONG:
|
||||
case BTT_SLONGLONG:
|
||||
case BTT_ULONGLONG:
|
||||
case BTT_S64:
|
||||
case BTT_U64: typ->szinfo.align = target->max_align; typ->szinfo.size = 8; return 1;
|
||||
case BTT_LONG:
|
||||
case BTT_SLONG:
|
||||
case BTT_ULONG: typ->szinfo.align = typ->szinfo.size = target->size_long; return 1;
|
||||
case BTT_FLOAT:
|
||||
case BTT_IFLOAT: typ->szinfo.align = typ->szinfo.size = 4; return 1;
|
||||
case BTT_CFLOAT:
|
||||
case BTT_DOUBLE:
|
||||
case BTT_IDOUBLE: typ->szinfo.align = target->max_align; typ->szinfo.size = 8; return 1;
|
||||
case BTT_CDOUBLE: typ->szinfo.align = target->max_align; typ->szinfo.size = 16; return 1;
|
||||
case BTT_LONGDOUBLE:
|
||||
case BTT_ILONGDOUBLE: typ->szinfo.align = target->align_longdouble; typ->szinfo.size = target->size_longdouble; return 1;
|
||||
case BTT_CLONGDOUBLE: typ->szinfo.align = target->align_longdouble; typ->szinfo.size = 2*target->size_longdouble; return 1;
|
||||
case BTT_INT128:
|
||||
case BTT_SINT128:
|
||||
case BTT_UINT128:
|
||||
if (!target->has_int128) {
|
||||
if (loginfo->filename) log_error(loginfo, "target does not have type __int128\n");
|
||||
typ->szinfo.align = typ->szinfo.size = 0; return 0;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case BTT_FLOAT128:
|
||||
case BTT_IFLOAT128: typ->szinfo.align = typ->szinfo.size = 16; return 1;
|
||||
case BTT_CFLOAT128: typ->szinfo.align = 16; typ->szinfo.size = 32; return 1;
|
||||
case BTT_VA_LIST: typ->szinfo.align = target->align_valist; typ->szinfo.size = target->size_valist; return 1;
|
||||
default:
|
||||
printf("Unknown builtin %u, cannot fill size info\n", typ->val.builtin);
|
||||
log_error(loginfo, "unknown builtin %u, cannot fill size info\n", typ->val.builtin);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
case TYPE_ARRAY:
|
||||
if (typ->val.array.typ->is_incomplete || (typ->val.array.typ->typ == TYPE_FUNCTION)) {
|
||||
printf("Error: array types must point to complete object types\n");
|
||||
log_error(loginfo, "array types must point to complete object types\n");
|
||||
return 0;
|
||||
}
|
||||
if ((typ->val.array.typ->typ == TYPE_STRUCT_UNION) && typ->val.array.typ->val.st->has_incomplete) {
|
||||
printf("Error: array types may not (inductively) point to structures which last element is incomplete\n");
|
||||
log_error(loginfo, "array types may not (inductively) point to structures which last element is incomplete\n");
|
||||
return 0;
|
||||
}
|
||||
if ((typ->is_atomic) || (typ->is_const) || (typ->is_restrict) || (typ->is_volatile)) {
|
||||
// qualifier-type-list in array declaration is only allowed in function argument declaration under certain circumstances
|
||||
printf("Error: array types may not be qualified\n");
|
||||
log_error(loginfo, "array types may not be qualified\n");
|
||||
return 0;
|
||||
}
|
||||
if (!validate_type(target, typ->val.array.typ)) return 0;
|
||||
if (!validate_type(loginfo, target, typ->val.array.typ)) return 0;
|
||||
if (typ->val.array.array_sz == (size_t)-1) {
|
||||
typ->szinfo.size = 0;
|
||||
typ->szinfo.align = (typ->val.array.typ->szinfo.align < 16) ? 16 : typ->val.array.typ->szinfo.align;
|
||||
@ -208,10 +279,10 @@ int validate_type(machine_t *target, type_t *typ) {
|
||||
case TYPE_PTR:
|
||||
typ->szinfo.size = target->size_long;
|
||||
typ->szinfo.align = target->size_long;
|
||||
return validate_type(target, typ->val.typ);
|
||||
return validate_type(loginfo, target, typ->val.typ);
|
||||
case TYPE_FUNCTION:
|
||||
if ((typ->val.fun.ret->typ == TYPE_FUNCTION) || (typ->val.fun.ret->typ == TYPE_ARRAY)) {
|
||||
printf("Error: function types may not return function or array types\n");
|
||||
log_error(loginfo, "function types may not return function or array types\n");
|
||||
return 0;
|
||||
}
|
||||
if (typ->val.fun.nargs != (size_t)-1) {
|
||||
@ -219,57 +290,72 @@ int validate_type(machine_t *target, type_t *typ) {
|
||||
// Adjust the argument if necessary
|
||||
// Assume arrays are already converted
|
||||
if (typ->val.fun.args[i]->typ == TYPE_ARRAY) {
|
||||
printf("Error: function argument %zu is an array\n", i + 1);
|
||||
log_error(loginfo, "function argument %zu is an array\n", i + 1);
|
||||
return 0;
|
||||
}
|
||||
if (typ->val.fun.args[i]->typ == TYPE_FUNCTION) {
|
||||
// Adjustment to pointer
|
||||
type_t *t2 = type_new_ptr(typ->val.fun.args[i]);
|
||||
if (!t2) {
|
||||
printf("Error: failed to adjust type of argument from function to pointer\n");
|
||||
log_error(loginfo, "failed to adjust type of argument from function to pointer\n");
|
||||
return 0;
|
||||
}
|
||||
typ->val.fun.args[i] = t2;
|
||||
}
|
||||
if (!validate_type(target, typ->val.fun.args[i])) return 0;
|
||||
if (!validate_type(loginfo, target, typ->val.fun.args[i])) return 0;
|
||||
}
|
||||
}
|
||||
typ->szinfo.size = 0;
|
||||
typ->szinfo.align = 0;
|
||||
return validate_type(target, typ->val.fun.ret);
|
||||
return validate_type(loginfo, target, typ->val.fun.ret);
|
||||
case TYPE_STRUCT_UNION: {
|
||||
if (!typ->val.st->is_defined) return typ->is_incomplete;
|
||||
size_t max_align = 1, cur_sz = 0, cur_bit = 0;
|
||||
size_t max_align = 1, cur_sz = 0; unsigned char cur_bit = 0;
|
||||
for (size_t i = 0; i < typ->val.st->nmembers; ++i) {
|
||||
// Adjust the argument if necessary
|
||||
st_member_t *mem = &typ->val.st->members[i];
|
||||
if (mem->typ->typ == TYPE_FUNCTION) {
|
||||
printf("Error: structures may not contain function members\n");
|
||||
log_error(loginfo, "structures may not contain function members\n");
|
||||
return 0;
|
||||
}
|
||||
if (mem->typ->is_incomplete) {
|
||||
if ((i != typ->val.st->nmembers - 1) || !typ->val.st->is_struct || (mem->typ->typ != TYPE_ARRAY)) {
|
||||
// The last element of a structure may be a VLA
|
||||
printf("Error: structures may not contain incomplete members\n");
|
||||
log_error(loginfo, "structures may not contain incomplete members\n");
|
||||
return 0;
|
||||
}
|
||||
typ->val.st->has_incomplete = 1;
|
||||
}
|
||||
if (!validate_type(target, mem->typ)) return 0;
|
||||
if (!validate_type(loginfo, target, mem->typ)) return 0;
|
||||
if (!typ->val.st->has_self_recursion) fill_self_recursion(mem->typ, typ->val.st);
|
||||
if (!typ->val.st->is_struct && (mem->typ->typ == TYPE_STRUCT_UNION)) {
|
||||
typ->val.st->has_incomplete |= mem->typ->val.st->has_incomplete;
|
||||
} else if ((mem->typ->typ == TYPE_STRUCT_UNION) && mem->typ->val.st->has_incomplete) {
|
||||
log_error(loginfo, "structures may not (inductively) contain structures which last element is incomplete\n");
|
||||
return 0;
|
||||
} else if (typ->val.st->is_struct) {
|
||||
if (mem->typ->is_incomplete) {
|
||||
if (i && (i == typ->val.st->nmembers - 1) && (mem->typ->typ == TYPE_ARRAY)) {
|
||||
typ->val.st->has_incomplete |= mem->typ->val.st->has_incomplete;
|
||||
} else {
|
||||
log_error(loginfo, "structures may not have any incomplete element, except that the last, but not first, element may be an incomplete array\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
mem->byte_offset = cur_sz;
|
||||
mem->bit_offset = cur_bit;
|
||||
if (mem->is_bitfield) {
|
||||
if (!typ->val.st->is_struct) {
|
||||
printf("Error: TODO: bitfield in union\n");
|
||||
log_error(loginfo, "TODO: bitfield in union\n");
|
||||
return 0;
|
||||
}
|
||||
if (mem->typ->is_atomic) {
|
||||
printf("Error: atomic bitfields are not supported\n");
|
||||
log_error(loginfo, "atomic bitfields are not supported\n");
|
||||
return 0;
|
||||
}
|
||||
if (mem->typ->typ != TYPE_BUILTIN) {
|
||||
printf("Error: bitfields can only have a specific subset of types\n");
|
||||
log_error(loginfo, "bitfields can only have a specific subset of types\n");
|
||||
return 0;
|
||||
}
|
||||
if ((mem->typ->val.builtin != BTT_BOOL) && (mem->typ->val.builtin != BTT_CHAR)
|
||||
@ -285,11 +371,11 @@ int validate_type(machine_t *target, type_t *typ) {
|
||||
&& (mem->typ->val.builtin != BTT_S64) && (mem->typ->val.builtin != BTT_U64)) {
|
||||
// C standard: allow _Bool, (s/u)int
|
||||
// Implementation: also allow (u/s)char, (u/s)short, (u/s)long, (u/s)long long, [u]intx_t
|
||||
printf("Error: bitfields can only have a specific subset of types\n");
|
||||
log_error(loginfo, "bitfields can only have a specific subset of types\n");
|
||||
return 0;
|
||||
}
|
||||
if (mem->typ->szinfo.size < mem->bitfield_width / 8) {
|
||||
printf("Error: bitfield member %c%s%c has width (%zu) greater than its container size (%zu * 8)\n",
|
||||
log_error(loginfo, "bitfield member %c%s%c has width (%zu) greater than its container size (%zu * 8)\n",
|
||||
mem->name ? '\'' : '<',
|
||||
mem->name ? string_content(mem->name) : "unnamed",
|
||||
mem->name ? '\'' : '>',
|
||||
@ -302,7 +388,8 @@ int validate_type(machine_t *target, type_t *typ) {
|
||||
size_t cur_block = cur_sz / mem->typ->szinfo.align;
|
||||
size_t end_block = (cur_sz + (cur_bit + mem->bitfield_width - 1) / 8) / mem->typ->szinfo.align;
|
||||
if (cur_block == end_block) {
|
||||
cur_bit += mem->bitfield_width;
|
||||
cur_sz += mem->bitfield_width / 8;
|
||||
cur_bit += mem->bitfield_width % 8;
|
||||
cur_sz += cur_bit / 8;
|
||||
cur_bit %= 8;
|
||||
} else {
|
||||
@ -312,7 +399,7 @@ int validate_type(machine_t *target, type_t *typ) {
|
||||
} else {
|
||||
if (max_align < mem->typ->szinfo.align) max_align = mem->typ->szinfo.align;
|
||||
cur_sz = ((cur_sz + mem->typ->szinfo.align - 1) & ~(mem->typ->szinfo.align - 1)) + mem->typ->szinfo.size;
|
||||
printf("Error: TODO: unnamed zero-width bitfield member\n");
|
||||
log_error(loginfo, "TODO: unnamed zero-width bitfield member\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@ -337,7 +424,7 @@ int validate_type(machine_t *target, type_t *typ) {
|
||||
return 1; }
|
||||
case TYPE_ENUM:
|
||||
if (typ->val.typ->typ != TYPE_BUILTIN) {
|
||||
printf("Error: the underlying type of an enum is not a builtin type\n");
|
||||
log_error(loginfo, "the underlying type of an enum is not a builtin type\n");
|
||||
return 0;
|
||||
}
|
||||
typ->szinfo = typ->val.typ->szinfo;
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "cstring.h"
|
||||
#include "khash.h"
|
||||
#include "log.h"
|
||||
#include "vector.h"
|
||||
|
||||
struct type_s; // lang.h
|
||||
@ -16,7 +17,9 @@ typedef struct machine_s {
|
||||
|
||||
// Parsing
|
||||
size_t size_long;
|
||||
size_t align_longdouble, size_longdouble;
|
||||
size_t align_valist, size_valist;
|
||||
size_t max_align; _Bool has_int128;
|
||||
_Bool unsigned_char;
|
||||
// Structure parsing
|
||||
_Bool unnamed_bitfield_aligns;
|
||||
@ -26,6 +29,6 @@ int init_machines(size_t npaths, const char *const *extra_include_path);
|
||||
void del_machines(void);
|
||||
machine_t *convert_machine_name(const char *archname);
|
||||
|
||||
int validate_type(machine_t *target, struct type_s *typ);
|
||||
int validate_type(loginfo_t *loginfo, machine_t *target, struct type_s *typ);
|
||||
|
||||
#endif // MACHINE_H
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
static void help(char *arg0) {
|
||||
printf("Usage: %s --help\n"
|
||||
" %s {-I/path/to/include}* [--prepare|--preproc|--proc] [--arch <arch>] <filename_in>\n"
|
||||
" %s {-I/path/to/include}* [--emu <arch>] [--target <arch>] <filename_in> <filename_reqs> <filename_out>\n"
|
||||
" %s {-I/path/to/include}* [--prepare|--preproc|--proc] [--arch <arch>|-32|-64|--32|--64] <filename_in>\n"
|
||||
" %s {-I/path/to/include}* [[--emu <arch>] [--target <arch>]|-32|-64|--32|--64] <filename_in> <filename_reqs> <filename_out>\n"
|
||||
"\n"
|
||||
" --prepare Dump all preprocessor tokens (prepare phase)\n"
|
||||
" --preproc Dump all processor tokens (preprocessor phase)\n"
|
||||
@ -29,8 +29,10 @@ static void help(char *arg0) {
|
||||
" --arch <arch> Use the architecture <arch>\n"
|
||||
" --emu <arch> Use the architecture <arch> as emulated architecture\n"
|
||||
" --target <arch> Use the architecture <arch> as target/running architecture\n"
|
||||
" -32 --32 Use the x86 architecture as arch/emulated, aarch64 as target\n"
|
||||
" -64 --64 Use the x86_64 architecture as arch/emulated, aarch64 as target\n"
|
||||
"\n"
|
||||
" <arch> is one of 'x86_64', 'aarch64'\n",
|
||||
" <arch> is one of 'x86', 'x86_64', 'aarch64'\n",
|
||||
arg0, arg0, arg0);
|
||||
}
|
||||
|
||||
@ -41,14 +43,21 @@ enum main_state {
|
||||
MAIN_PROC,
|
||||
};
|
||||
|
||||
enum bits_state {
|
||||
BITS_NONE,
|
||||
BITS_32,
|
||||
BITS_64,
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
setbuf(stdout, NULL);
|
||||
if (!setlocale(LC_NUMERIC, "C")) {
|
||||
printf("Error: failed to set LC_NUMERIC to C\n");
|
||||
log_error_nopos("failed to set LC_NUMERIC to C\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
enum main_state ms = MAIN_RUN;
|
||||
enum bits_state bs = BITS_NONE;
|
||||
const char *in_file = NULL, *ref_file = NULL, *out_file = NULL;
|
||||
VECTOR(charp) *paths = vector_new(charp);
|
||||
const char *archname = NULL, *emuname = NULL, *targetname = NULL;
|
||||
@ -69,13 +78,13 @@ int main(int argc, char **argv) {
|
||||
// Ignore
|
||||
} else if (!strcmp(argv[i], "-I") && (i + 1 < argc)) {
|
||||
if (!vector_push(charp, paths, argv[i + 1])) {
|
||||
printf("Error: failed to add path to buffer\n");
|
||||
log_memory("failed to add path to buffer\n");
|
||||
return 2;
|
||||
}
|
||||
++i;
|
||||
} else if ((argv[i][0] == '-') && (argv[i][1] == 'I') && (argv[i][2] != '\0')) {
|
||||
if (!vector_push(charp, paths, argv[i] + 2)) {
|
||||
printf("Error: failed to add path to buffer\n");
|
||||
log_memory("failed to add path to buffer\n");
|
||||
return 2;
|
||||
}
|
||||
} else if (!strcmp(argv[i], "--arch")) {
|
||||
@ -83,7 +92,7 @@ int main(int argc, char **argv) {
|
||||
if (i < argc) {
|
||||
archname = argv[i];
|
||||
} else {
|
||||
printf("Error: invalid '--arch' option in last position\n");
|
||||
log_error_nopos("invalid '--arch' option in last position\n");
|
||||
help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
@ -92,7 +101,7 @@ int main(int argc, char **argv) {
|
||||
if (i < argc) {
|
||||
emuname = argv[i];
|
||||
} else {
|
||||
printf("Error: invalid '--emu' option in last position\n");
|
||||
log_error_nopos("invalid '--emu' option in last position\n");
|
||||
help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
@ -101,16 +110,20 @@ int main(int argc, char **argv) {
|
||||
if (i < argc) {
|
||||
targetname = argv[i];
|
||||
} else {
|
||||
printf("Error: invalid '--target' option in last position\n");
|
||||
log_error_nopos("invalid '--target' option in last position\n");
|
||||
help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
} else if (!strcmp(argv[i], "-32") || !strcmp(argv[i], "--32")) {
|
||||
bs = BITS_32;
|
||||
} else if (!strcmp(argv[i], "-64") || !strcmp(argv[i], "--64")) {
|
||||
bs = BITS_64;
|
||||
} else if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--filename")) {
|
||||
++i;
|
||||
if (i < argc) {
|
||||
isfile = 1;
|
||||
} else {
|
||||
printf("Error: invalid '--filename' option in last position\n");
|
||||
log_error_nopos("invalid '--filename' option in last position\n");
|
||||
help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
@ -125,7 +138,7 @@ int main(int argc, char **argv) {
|
||||
} else if (!out_file) {
|
||||
out_file = argv[i];
|
||||
} else {
|
||||
printf("Error: too many unknown options considered as file\n");
|
||||
log_error_nopos("too many unknown options considered as file\n");
|
||||
help(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
@ -137,15 +150,23 @@ int main(int argc, char **argv) {
|
||||
case MAIN_PROC:
|
||||
check_proc:
|
||||
if (!in_file || ref_file || out_file) {
|
||||
printf("Error: too many unknown options/not enough arguments\n");
|
||||
log_error_nopos("too many unknown options/not enough arguments\n");
|
||||
help(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
if (emuname || targetname) {
|
||||
printf("Error: invalid option '--emu' or '--target' in prepare/preprocessor/processor mode\n");
|
||||
log_error_nopos("invalid option '--emu' or '--target' in prepare/preprocessor/processor mode\n");
|
||||
help(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
if (bs != BITS_NONE) {
|
||||
if (archname) {
|
||||
log_error_nopos("invalid option '--arch' with '--32' or '--64' in prepare/preprocessor/processor mode\n");
|
||||
help(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
archname = (bs == BITS_32) ? "x86" : "x86_64";
|
||||
}
|
||||
if (!archname) archname = "x86_64";
|
||||
break;
|
||||
case MAIN_RUN:
|
||||
@ -154,15 +175,24 @@ int main(int argc, char **argv) {
|
||||
goto check_proc;
|
||||
}
|
||||
if (!in_file || !ref_file || !out_file) {
|
||||
printf("Error: too many unknown options/not enough arguments\n");
|
||||
log_error_nopos("too many unknown options/not enough arguments\n");
|
||||
help(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
if (archname) {
|
||||
printf("Error: invalid option '--arch' in run mode\n");
|
||||
log_error_nopos("invalid option '--arch' in run mode\n");
|
||||
help(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
if (bs != BITS_NONE) {
|
||||
if (emuname || targetname) {
|
||||
log_error_nopos("invalid option '--emu' or '--target' with '--32' or '--64' in run mode\n");
|
||||
help(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
emuname = (bs == BITS_32) ? "x86" : "x86_64";
|
||||
targetname = "aarch64";
|
||||
}
|
||||
if (!emuname) emuname = "x86_64";
|
||||
if (!targetname) targetname = "aarch64";
|
||||
break;
|
||||
@ -173,6 +203,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
if (!init_machines(vector_size(charp, paths), (const char*const*)vector_content(charp, paths))) {
|
||||
vector_del(charp, paths);
|
||||
del_str2kw();
|
||||
return 2;
|
||||
}
|
||||
vector_del(charp, paths);
|
||||
@ -180,22 +211,30 @@ int main(int argc, char **argv) {
|
||||
FILE *f = fopen(in_file, "r");
|
||||
if (!f) {
|
||||
err(2, "Error: failed to open %s", in_file);
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 2;
|
||||
}
|
||||
switch (ms) {
|
||||
case MAIN_RUN: {
|
||||
machine_t *emu = convert_machine_name(emuname);
|
||||
if (!emu) {
|
||||
printf("Error: invalid emulation architecture '%s'\n", emuname);
|
||||
log_error_nopos("invalid emulation architecture '%s'\n", emuname);
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 0;
|
||||
}
|
||||
machine_t *target = convert_machine_name(targetname);
|
||||
if (!target) {
|
||||
printf("Error: invalid target architecture '%s'\n", targetname);
|
||||
log_error_nopos("invalid target architecture '%s'\n", targetname);
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 0;
|
||||
}
|
||||
|
||||
file_t *emu_content = parse_file(emu, in_file, f); // Takes ownership of f
|
||||
if (!emu_content) {
|
||||
printf("Error: failed to parse the file\n");
|
||||
log_error_nopos("failed to parse the file\n");
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 0;
|
||||
@ -204,11 +243,14 @@ int main(int argc, char **argv) {
|
||||
f = fopen(in_file, "r");
|
||||
if (!f) {
|
||||
err(2, "Error: failed to re-open %s", in_file);
|
||||
file_del(emu_content);
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 2;
|
||||
}
|
||||
file_t *target_content = parse_file(target, in_file, f); // Takes ownership of f
|
||||
if (!target_content) {
|
||||
printf("Error: failed to parse the file\n");
|
||||
log_error_nopos("failed to parse the file\n");
|
||||
file_del(emu_content);
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
@ -218,6 +260,8 @@ int main(int argc, char **argv) {
|
||||
FILE *ref = fopen(ref_file, "r");
|
||||
if (!ref) {
|
||||
err(2, "Error: failed to open %s", ref_file);
|
||||
file_del(emu_content);
|
||||
file_del(target_content);
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 2;
|
||||
@ -231,8 +275,14 @@ int main(int argc, char **argv) {
|
||||
return 2;
|
||||
}
|
||||
// vector_for(references, req, refs) request_print(req);
|
||||
if (target->size_long != emu->size_long) {
|
||||
if (!solve_references(refs, emu_content->decl_map, target_content->decl_map, emu_content->relaxed_type_conversion)) {
|
||||
printf("Warning: failed to solve all default requests\n");
|
||||
log_warning_nopos("failed to solve all default requests\n");
|
||||
}
|
||||
} else {
|
||||
if (!solve_references_simple(refs, emu_content->decl_map, target_content->decl_map, emu_content->relaxed_type_conversion)) {
|
||||
log_warning_nopos("failed to solve all default requests\n");
|
||||
}
|
||||
}
|
||||
// vector_for(references, req, refs) request_print(req);
|
||||
references_print_check(refs);
|
||||
@ -254,14 +304,15 @@ int main(int argc, char **argv) {
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 0; }
|
||||
|
||||
case MAIN_PROC: {
|
||||
machine_t *arch = convert_machine_name(archname);
|
||||
if (!arch) {
|
||||
printf("Error: invalid architecture '%s'\n", archname);
|
||||
log_error_nopos("invalid architecture '%s'\n", archname);
|
||||
}
|
||||
file_t *content = parse_file(arch, in_file, f); // Takes ownership of f
|
||||
if (!content) {
|
||||
printf("Error: failed to parse the file\n");
|
||||
log_error_nopos("failed to parse the file\n");
|
||||
del_machines();
|
||||
del_str2kw();
|
||||
return 0;
|
||||
@ -334,7 +385,7 @@ int main(int argc, char **argv) {
|
||||
case MAIN_PREPROC: {
|
||||
machine_t *arch = convert_machine_name(archname);
|
||||
if (!arch) {
|
||||
printf("Error: invalid architecture '%s'\n", archname);
|
||||
log_error_nopos("invalid architecture '%s'\n", archname);
|
||||
}
|
||||
dump_preproc(arch, in_file, f); // Takes ownership of f
|
||||
del_machines();
|
||||
@ -342,6 +393,6 @@ int main(int argc, char **argv) {
|
||||
return 0; }
|
||||
}
|
||||
|
||||
printf("Internal error: failed to run mode %u\n", ms);
|
||||
log_internal_nopos("failed to run mode %u\n", ms);
|
||||
return 2;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,11 +2,17 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct char_s {
|
||||
int c;
|
||||
loginfo_t li;
|
||||
} char_t;
|
||||
|
||||
struct prepare_s {
|
||||
FILE *f;
|
||||
int buf[4];
|
||||
int buf_len; // <= 4 (though 3 *should* be enough)
|
||||
char_t buf[5];
|
||||
int buf_len; // <= 5 (though 4 *should* be enough)
|
||||
char *srcn;
|
||||
loginfo_t li;
|
||||
enum prepare_state {
|
||||
PREPST_NONE = 0,
|
||||
PREPST_NL,
|
||||
@ -21,14 +27,24 @@ struct prepare_s {
|
||||
prepare_t *prepare_new_file(FILE *f, const char *filename) {
|
||||
prepare_t *ret = malloc(sizeof *ret);
|
||||
if (!ret) {
|
||||
log_memory("failed to allocate new preparator structure\n");
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *srcn = strdup(filename);
|
||||
if (!srcn) {
|
||||
log_memory("failed to duplicate filename\n");
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*ret = (prepare_t){
|
||||
.f = f,
|
||||
.buf = {0, 0, 0},
|
||||
.buf = {{0}, {0}, {0}, {0}},
|
||||
.buf_len = 0,
|
||||
.srcn = strdup(filename),
|
||||
.srcn = srcn,
|
||||
.li = { .filename = srcn, .lineno = 1, .colno = 1, .lineno_end = 0, .colno_end = 0 },
|
||||
.st = PREPST_NL,
|
||||
};
|
||||
return ret;
|
||||
@ -40,28 +56,72 @@ void prepare_del(prepare_t *prep) {
|
||||
free(prep);
|
||||
}
|
||||
|
||||
static int get_char(prepare_t *src) {
|
||||
start_get_char:
|
||||
int c = src->buf_len ? src->buf[--src->buf_len] : getc(src->f);
|
||||
src->buf_len = 0;
|
||||
if (c == '\\') {
|
||||
c = src->buf_len ? src->buf[--src->buf_len] : getc(src->f);
|
||||
if (c == '\n') goto start_get_char;
|
||||
src->buf[src->buf_len++] = c;
|
||||
return '\\';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
// Do not call this more than twice in a row if the last character retrieved is '\\'
|
||||
static void unget_char(prepare_t *src, int c) {
|
||||
static void unget_char(prepare_t *src, char_t c) {
|
||||
src->buf[src->buf_len++] = c;
|
||||
}
|
||||
// Transforms \n, \r\n and \r into \n
|
||||
static char_t get_char(prepare_t *src) {
|
||||
if (src->buf_len) {
|
||||
return src->buf[--src->buf_len];
|
||||
}
|
||||
start_get_char:
|
||||
int c = getc(src->f);
|
||||
if (c == '\\') {
|
||||
c = getc(src->f);
|
||||
if (c == '\n') {
|
||||
++src->li.lineno;
|
||||
src->li.colno = 1;
|
||||
goto start_get_char;
|
||||
} else if (c == '\r') {
|
||||
++src->li.lineno;
|
||||
src->li.colno = 1;
|
||||
c = getc(src->f);
|
||||
if (c == '\n') {
|
||||
goto start_get_char;
|
||||
} else {
|
||||
unget_char(src, (char_t){.c = c, .li = src->li});
|
||||
goto start_get_char;
|
||||
}
|
||||
}
|
||||
src->li.colno += 2;
|
||||
src->buf[src->buf_len++] = (char_t){
|
||||
.c = c,
|
||||
.li = { .filename = src->li.filename, .lineno = src->li.lineno, .colno = src->li.colno - 1, .lineno_end = 0, .colno_end = 0 }
|
||||
};
|
||||
return (char_t){
|
||||
.c = '\\',
|
||||
.li = { .filename = src->li.filename, .lineno = src->li.lineno, .colno = src->li.colno - 2, .lineno_end = 0, .colno_end = 0 }
|
||||
};
|
||||
}
|
||||
char_t ret = {
|
||||
.c = c,
|
||||
.li = { .filename = src->li.filename, .lineno = src->li.lineno, .colno = src->li.colno, .lineno_end = 0, .colno_end = 0 }
|
||||
};
|
||||
if (c == '\n') {
|
||||
++src->li.lineno;
|
||||
src->li.colno = 1;
|
||||
} else if (c == '\r') {
|
||||
++src->li.lineno;
|
||||
src->li.colno = 1;
|
||||
ret.c = '\n';
|
||||
c = getc(src->f);
|
||||
if (c != '\n') {
|
||||
unget_char(src, (char_t){.c = c, .li = src->li});
|
||||
}
|
||||
} else {
|
||||
++src->li.colno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fill_ident(prepare_t *src, string_t *buf) {
|
||||
static void fill_ident(prepare_t *src, string_t *buf, size_t *lineno_end, size_t *colno_end) {
|
||||
while (1) {
|
||||
int c = get_char(src);
|
||||
if ((c == '_') || ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) {
|
||||
string_add_char(buf, (char)c);
|
||||
char_t c = get_char(src);
|
||||
if ((c.c == '_') || ((c.c >= '0') && (c.c <= '9')) || ((c.c >= 'A') && (c.c <= 'Z')) || ((c.c >= 'a') && (c.c <= 'z'))) {
|
||||
string_add_char(buf, (char)c.c);
|
||||
*lineno_end = c.li.lineno;
|
||||
*colno_end = c.li.colno;
|
||||
} else {
|
||||
unget_char(src, c);
|
||||
return;
|
||||
@ -69,14 +129,16 @@ static void fill_ident(prepare_t *src, string_t *buf) {
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_num(prepare_t *src, string_t *buf) {
|
||||
static void fill_num(prepare_t *src, string_t *buf, size_t *lineno_end, size_t *colno_end) {
|
||||
int started_exp = 0;
|
||||
while (1) {
|
||||
int c = get_char(src);
|
||||
if ((c == '_') || (c == '.') || ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))
|
||||
|| (started_exp && ((c == '+') || (c == '-')))) {
|
||||
started_exp = (c == 'e') || (c == 'E') || (c == 'p') || (c == 'P');
|
||||
string_add_char(buf, (char)c);
|
||||
char_t c = get_char(src);
|
||||
if ((c.c == '_') || (c.c == '.') || ((c.c >= '0') && (c.c <= '9')) || ((c.c >= 'A') && (c.c <= 'Z')) || ((c.c >= 'a') && (c.c <= 'z'))
|
||||
|| (started_exp && ((c.c == '+') || (c.c == '-')))) {
|
||||
started_exp = (c.c == 'e') || (c.c == 'E') || (c.c == 'p') || (c.c == 'P');
|
||||
string_add_char(buf, (char)c.c);
|
||||
*lineno_end = c.li.lineno;
|
||||
*colno_end = c.li.colno;
|
||||
} else {
|
||||
unget_char(src, c);
|
||||
return;
|
||||
@ -84,32 +146,42 @@ static void fill_num(prepare_t *src, string_t *buf) {
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_str(prepare_t *src, string_t *buf, char end_c, int can_esc) {
|
||||
static void fill_str(prepare_t *src, string_t *buf, char end_c, int can_esc, size_t *lineno_end, size_t *colno_end) {
|
||||
int has_esc = 0;
|
||||
while (1) {
|
||||
int c = get_char(src);
|
||||
if (has_esc && (c >= 0) && (c <= 0x7F) && (c != '\n')) {
|
||||
char_t c = get_char(src);
|
||||
if (has_esc && (c.c >= 0) && (c.c <= 0x7F) && (c.c != '\n')) {
|
||||
// Not technically standard compliant (should support \ooo, \x..., \u..., \U...)
|
||||
// Since we don't really care about parsing the content, only the delimiters, this is good enough
|
||||
string_add_char(buf, '\\');
|
||||
string_add_char(buf, (char)c);
|
||||
string_add_char(buf, (char)c.c);
|
||||
has_esc = 0;
|
||||
} else if (c == '\\') {
|
||||
*lineno_end = c.li.lineno;
|
||||
*colno_end = c.li.colno;
|
||||
} else if (c.c == '\\') {
|
||||
*lineno_end = c.li.lineno;
|
||||
*colno_end = c.li.colno;
|
||||
if (can_esc) {
|
||||
has_esc = 1;
|
||||
} else {
|
||||
string_add_char(buf, '\\');
|
||||
}
|
||||
} else if ((c >= 0) && (c <= 0x7F) && (c != '\n') && (c != end_c)) {
|
||||
} else if ((c.c >= 0) && (c.c <= 0x7F) && (c.c != '\n') && (c.c != end_c)) {
|
||||
has_esc = 0;
|
||||
string_add_char(buf, (char)c);
|
||||
string_add_char(buf, (char)c.c);
|
||||
*lineno_end = c.li.lineno;
|
||||
*colno_end = c.li.colno;
|
||||
} else {
|
||||
// c.c is invalid (> 0x80) or a '\n', or can_esc = 0 and c.c = end_c
|
||||
if (has_esc) {
|
||||
// c is invalid or a '\n', or can_esc = 0 and c = end_c
|
||||
string_add_char(buf, '\\');
|
||||
}
|
||||
if (c != end_c)
|
||||
if (c.c != end_c) {
|
||||
unget_char(src, c);
|
||||
} else {
|
||||
*lineno_end = c.li.lineno;
|
||||
*colno_end = c.li.colno;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -157,42 +229,47 @@ static const struct symbs_s {
|
||||
preproc_token_t pre_next_token(prepare_t *src, int allow_comments) {
|
||||
if (src->st == PREPST_COMMENT) {
|
||||
// In comments, keep everything as 'BLANK' except for idents, newlines and EOF
|
||||
int c = get_char(src);
|
||||
if (c == EOF) {
|
||||
char_t c = get_char(src);
|
||||
if (c.c == EOF) {
|
||||
// Force newline at EOF
|
||||
unget_char(src, c);
|
||||
src->st = PREPST_NL;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_NEWLINE,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
} else if ((c == '_') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {
|
||||
} else if ((c.c == '_') || ((c.c >= 'a') && (c.c <= 'z')) || ((c.c >= 'A') && (c.c <= 'Z'))) {
|
||||
preproc_token_t ret;
|
||||
ret.tokt = PPTOK_IDENT;
|
||||
ret.loginfo = c.li;
|
||||
ret.tokv.str = string_new_cap(1);
|
||||
string_add_char(ret.tokv.str, (char)c);
|
||||
fill_ident(src, ret.tokv.str);
|
||||
string_add_char(ret.tokv.str, (char)c.c);
|
||||
fill_ident(src, ret.tokv.str, &ret.loginfo.lineno_end, &ret.loginfo.colno_end);
|
||||
return ret;
|
||||
} else if ((c >= 0) && (c <= 0x7F)) {
|
||||
} else if ((c.c >= 0) && (c.c <= 0x7F)) {
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_BLANK,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
} else {
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_INVALID,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
start_next_token:
|
||||
int c = get_char(src);
|
||||
if (c == EOF) {
|
||||
char_t c = get_char(src);
|
||||
if (c.c == EOF) {
|
||||
if (src->st == PREPST_NL) {
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_EOF,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
} else {
|
||||
// Force newline at EOF
|
||||
@ -200,60 +277,67 @@ start_next_token:
|
||||
src->st = PREPST_NL;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_NEWLINE,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (src->st == PREPST_INCL && (c == '<')) {
|
||||
if (src->st == PREPST_INCL && (c.c == '<')) {
|
||||
src->st = PREPST_NONE;
|
||||
preproc_token_t ret;
|
||||
ret.tokt = PPTOK_INCL;
|
||||
ret.loginfo = c.li;
|
||||
ret.tokv.sisstr = 0;
|
||||
ret.tokv.sstr = string_new();
|
||||
fill_str(src, ret.tokv.sstr, '>', 0);
|
||||
fill_str(src, ret.tokv.sstr, '>', 0, &ret.loginfo.lineno_end, &ret.loginfo.colno_end);
|
||||
return ret;
|
||||
}
|
||||
if (c == '\'') {
|
||||
if (c.c == '\'') {
|
||||
src->st = PREPST_NONE;
|
||||
preproc_token_t ret;
|
||||
ret.tokt = PPTOK_STRING;
|
||||
ret.loginfo = c.li;
|
||||
ret.tokv.sisstr = 0;
|
||||
ret.tokv.sstr = string_new_cap(1); // Usually only one character is inside a char literal
|
||||
fill_str(src, ret.tokv.sstr, '\'', 1);
|
||||
fill_str(src, ret.tokv.sstr, '\'', 1, &ret.loginfo.lineno_end, &ret.loginfo.colno_end);
|
||||
return ret;
|
||||
}
|
||||
if (c == '"') {
|
||||
if (c.c == '"') {
|
||||
preproc_token_t ret;
|
||||
ret.tokt = (src->st == PREPST_INCL) ? PPTOK_INCL : PPTOK_STRING;
|
||||
src->st = PREPST_NONE;
|
||||
ret.loginfo = c.li;
|
||||
ret.tokv.sisstr = 1;
|
||||
ret.tokv.sstr = string_new();
|
||||
fill_str(src, ret.tokv.sstr, '"', ret.tokt == PPTOK_STRING);
|
||||
fill_str(src, ret.tokv.sstr, '"', ret.tokt == PPTOK_STRING, &ret.loginfo.lineno_end, &ret.loginfo.colno_end);
|
||||
return ret;
|
||||
}
|
||||
if ((c == ' ') || (c == '\f') || (c == '\t') || (c == '\v')) {
|
||||
if ((c.c == ' ') || (c.c == '\f') || (c.c == '\t') || (c.c == '\v')) {
|
||||
if (src->st == PREPST_DEFID) {
|
||||
src->st = PREPST_NONE;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_BLANK,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
} else goto start_next_token;
|
||||
}
|
||||
if (c == '\n') {
|
||||
if (c.c == '\n') {
|
||||
src->st = PREPST_NL;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_NEWLINE,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
}
|
||||
if ((c == '_') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {
|
||||
if ((c.c == '_') || ((c.c >= 'a') && (c.c <= 'z')) || ((c.c >= 'A') && (c.c <= 'Z'))) {
|
||||
preproc_token_t ret;
|
||||
ret.tokt = PPTOK_IDENT;
|
||||
ret.loginfo = c.li;
|
||||
ret.tokv.str = string_new_cap(1);
|
||||
string_add_char(ret.tokv.str, (char)c);
|
||||
fill_ident(src, ret.tokv.str);
|
||||
string_add_char(ret.tokv.str, (char)c.c);
|
||||
fill_ident(src, ret.tokv.str, &ret.loginfo.lineno_end, &ret.loginfo.colno_end);
|
||||
src->st =
|
||||
((src->st == PREPST_HASH) && (!strcmp(string_content(ret.tokv.str), "include"))) ? PREPST_INCL :
|
||||
((src->st == PREPST_HASH) && (!strcmp(string_content(ret.tokv.str), "include_next"))) ? PREPST_INCL :
|
||||
@ -262,107 +346,131 @@ start_next_token:
|
||||
PREPST_NONE;
|
||||
return ret;
|
||||
}
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
if ((c.c >= '0') && (c.c <= '9')) {
|
||||
src->st = PREPST_NONE;
|
||||
preproc_token_t ret;
|
||||
ret.tokt = PPTOK_NUM;
|
||||
ret.loginfo = c.li;
|
||||
ret.tokv.str = string_new_cap(1);
|
||||
string_add_char(ret.tokv.str, (char)c);
|
||||
fill_num(src, ret.tokv.str);
|
||||
string_add_char(ret.tokv.str, (char)c.c);
|
||||
fill_num(src, ret.tokv.str, &ret.loginfo.lineno_end, &ret.loginfo.colno_end);
|
||||
return ret;
|
||||
}
|
||||
if (c == '.') {
|
||||
if (c.c == '.') {
|
||||
loginfo_t oldli = c.li;
|
||||
c = get_char(src);
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
if ((c.c >= '0') && (c.c <= '9')) {
|
||||
src->st = PREPST_NONE;
|
||||
preproc_token_t ret;
|
||||
ret.tokt = PPTOK_NUM;
|
||||
ret.loginfo = oldli;
|
||||
ret.loginfo.lineno_end = c.li.lineno;
|
||||
ret.loginfo.colno_end = c.li.colno;
|
||||
ret.tokv.str = string_new_cap(2);
|
||||
string_add_char(ret.tokv.str, '.');
|
||||
string_add_char(ret.tokv.str, (char)c);
|
||||
fill_num(src, ret.tokv.str);
|
||||
string_add_char(ret.tokv.str, (char)c.c);
|
||||
fill_num(src, ret.tokv.str, &ret.loginfo.lineno_end, &ret.loginfo.colno_end);
|
||||
return ret;
|
||||
} else {
|
||||
unget_char(src, c);
|
||||
c = '.';
|
||||
c.c = '.';
|
||||
c.li = oldli;
|
||||
}
|
||||
}
|
||||
if (c == '/') {
|
||||
c = get_char(src);
|
||||
if (c == '/') {
|
||||
if (c.c == '/') {
|
||||
char_t c2 = get_char(src);
|
||||
if (c2.c == '/') {
|
||||
if (allow_comments) {
|
||||
src->st = PREPST_COMMENT;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_START_LINE_COMMENT,
|
||||
.tokv.c = '/'
|
||||
.loginfo = {
|
||||
.filename = c2.li.filename,
|
||||
.lineno = c.li.lineno, .colno = c.li.colno,
|
||||
.lineno_end = c2.li.lineno, .colno_end = c2.li.colno,
|
||||
},
|
||||
.tokv.c = '/',
|
||||
};
|
||||
}
|
||||
|
||||
do {
|
||||
c = get_char(src);
|
||||
} while ((c != EOF) && (c != '\n'));
|
||||
if (c != EOF) {
|
||||
c2 = get_char(src);
|
||||
} while ((c2.c != EOF) && (c2.c != '\n'));
|
||||
if (c2.c != EOF) {
|
||||
if (src->st == PREPST_NL)
|
||||
goto start_next_token;
|
||||
else {
|
||||
src->st = PREPST_NL;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_NEWLINE,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c2.li,
|
||||
.tokv.c = (char)c2.c
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
src->st = PREPST_NONE;
|
||||
printf("Unfinished comment while preparing %s\n", src->srcn);
|
||||
// Force newline at EOF
|
||||
unget_char(src, c2);
|
||||
src->st = PREPST_NL;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_INVALID,
|
||||
.tokv.c = (char)c
|
||||
.tokt = PPTOK_NEWLINE,
|
||||
.loginfo = c2.li,
|
||||
.tokv.c = (char)c2.c
|
||||
};
|
||||
} else if (c == '*') {
|
||||
} else if (c2.c == '*') {
|
||||
if (allow_comments) {
|
||||
printf("Unsupported multiline comment with allow_comment in %s\n", src->srcn);
|
||||
c.li.lineno_end = c2.li.lineno;
|
||||
c.li.colno_end = c2.li.colno;
|
||||
log_error(&c.li, "unsupported multiline comment with allow_comment\n");
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_INVALID,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c
|
||||
};
|
||||
}
|
||||
|
||||
c = get_char(src);
|
||||
c2 = get_char(src);
|
||||
int last_star = 0;
|
||||
while ((c != EOF) && (!last_star || (c != '/'))) {
|
||||
last_star = c == '*';
|
||||
c = get_char(src);
|
||||
while ((c2.c != EOF) && (!last_star || (c2.c != '/'))) {
|
||||
last_star = c2.c == '*';
|
||||
c2 = get_char(src);
|
||||
}
|
||||
if (c != EOF) goto start_next_token;
|
||||
if (c2.c != EOF) goto start_next_token;
|
||||
|
||||
c.li.lineno_end = c2.li.lineno;
|
||||
c.li.colno_end = c2.li.colno;
|
||||
log_error(&c.li, "unfinished multiline comment\n");
|
||||
src->st = PREPST_NONE;
|
||||
printf("Unfinished comment while preparing %s\n", src->srcn);
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_INVALID,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c2.li,
|
||||
.tokv.c = (char)c2.c
|
||||
};
|
||||
} else {
|
||||
unget_char(src, c);
|
||||
c = '/';
|
||||
unget_char(src, c2);
|
||||
}
|
||||
}
|
||||
|
||||
struct symbs_s const *sym = NULL;
|
||||
for (int i = 0; i < BASE_NSYMS; ++i) {
|
||||
if (c == symbs[i].c) {
|
||||
if (c.c == symbs[i].c) {
|
||||
sym = &symbs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sym) {
|
||||
loginfo_t lisym = c.li;
|
||||
loginfo_t liend = c.li;
|
||||
while (sym->nnext) {
|
||||
c = get_char(src);
|
||||
int found = 0;
|
||||
for (int i = 0; i < sym->nnext; ++i) {
|
||||
if (c == sym->next[i].c) {
|
||||
if (c.c == sym->next[i].c) {
|
||||
found = 1;
|
||||
sym = &sym->next[i];
|
||||
liend = c.li;
|
||||
lisym.lineno_end = c.li.lineno;
|
||||
lisym.colno_end = c.li.colno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -372,41 +480,66 @@ start_next_token:
|
||||
}
|
||||
}
|
||||
if (sym->sym == LAST_SYM + 1) {
|
||||
unget_char(src, sym->c);
|
||||
sym = &symbs[0]; // This is where no check is made (see comment in the definition of symbs)
|
||||
// This is where no check is made (see comment in the definition of symbs)
|
||||
unget_char(src, (char_t){.c = sym->c, .li = liend});
|
||||
sym = &symbs[0];
|
||||
lisym.lineno_end = lisym.colno_end = 0;
|
||||
}
|
||||
src->st = ((src->st == PREPST_NL) && (sym->sym == SYM_HASH)) ? PREPST_HASH : PREPST_NONE;
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_SYM,
|
||||
.loginfo = lisym,
|
||||
.tokv.sym = sym->sym
|
||||
};
|
||||
}
|
||||
|
||||
src->st = PREPST_NONE;
|
||||
printf("Invalid character 0x%X (%c) while preparing %s\n", (unsigned)c, (c >= 0x20) && (c < 127) ? c : '?', src->srcn);
|
||||
log_error(&c.li, "invalid character 0x%02X (%c)\n", (unsigned)c.c, (c.c >= 0x20) && (c.c < 0x7F) ? c.c : '?');
|
||||
return (preproc_token_t){
|
||||
.tokt = PPTOK_INVALID,
|
||||
.tokv.c = (char)c
|
||||
.loginfo = c.li,
|
||||
.tokv.c = (char)c.c,
|
||||
};
|
||||
}
|
||||
|
||||
void prepare_set_line(prepare_t *src, char *filename, size_t lineno) {
|
||||
if (filename) {
|
||||
if (src->srcn) free(filename);
|
||||
src->srcn = filename;
|
||||
src->li.filename = filename;
|
||||
}
|
||||
size_t colno = 1;
|
||||
for (int i = src->buf_len; i--; ) {
|
||||
src->buf[i].li.lineno = lineno;
|
||||
src->buf[i].li.colno = colno;
|
||||
if (src->buf[i].c == '\n') {
|
||||
++lineno;
|
||||
colno = 1;
|
||||
} else {
|
||||
++colno;
|
||||
}
|
||||
}
|
||||
src->li.lineno = lineno;
|
||||
src->li.colno = colno;
|
||||
}
|
||||
|
||||
// Warning: unsafe method
|
||||
void prepare_mark_nocomment(prepare_t *src) {
|
||||
src->st = PREPST_NONE;
|
||||
}
|
||||
int pre_next_newline_token(prepare_t *src, string_t *buf) {
|
||||
while (1) {
|
||||
int c = get_char(src);
|
||||
if (c == EOF) {
|
||||
char_t c = get_char(src);
|
||||
if (c.c == EOF) {
|
||||
// Force newline at EOF
|
||||
unget_char(src, c);
|
||||
src->st = PREPST_NL;
|
||||
return 1;
|
||||
} else if (c == '\n') {
|
||||
} else if (c.c == '\n') {
|
||||
src->st = PREPST_NL;
|
||||
return 1;
|
||||
} else if ((c >= 0) && (c <= 0x7F)) {
|
||||
if (!string_add_char(buf, (char)c)) return 0;
|
||||
} else if ((c.c >= 0) && (c.c <= 0x7F)) {
|
||||
if (!string_add_char(buf, (char)c.c)) return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ prepare_t *prepare_new_file(FILE *f, const char *filename); // Takes ownership o
|
||||
void prepare_del(prepare_t *src);
|
||||
preproc_token_t pre_next_token(prepare_t *src, int allow_comments);
|
||||
|
||||
void prepare_set_line(prepare_t *src, char *filename, size_t lineno); // Takes ownership of filename if != NULL
|
||||
|
||||
void prepare_mark_nocomment(prepare_t *src); // Change the state (usually from COMMENT) to NONE
|
||||
int pre_next_newline_token(prepare_t *src, string_t *buf); // In a comment append everything until the EOL or EOF to the buffer
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user