[WRAPPERHELPER] Added box32 and line number support in the wrapperhelper (#1890)

This commit is contained in:
rajdakin 2024-09-30 12:31:45 +02:00 committed by GitHub
parent 703d19b256
commit 4715ef2633
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 3638 additions and 1783 deletions

1
.gitignore vendored
View File

@ -69,6 +69,7 @@ backup/
/wrapperhelper/sanundefined
/wrapperhelper/src/machine.gen
/wrapperhelper/*.h
!/wrapperhelper/example-libc.h
# macOS
.DS_Store

View File

@ -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__(_)`)

View File

@ -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

View File

@ -1,4 +1,2 @@
// Ignore all attributes
#define __attribute__(_)
#include_next "stdc-predef.h"

View 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 */

View 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"

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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
View 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
View 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__

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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