Use templates to avoid repetition, and to add type safety#1236
Use templates to avoid repetition, and to add type safety#1236alejandro-colomar wants to merge 14 commits intoshadow-maint:masterfrom
Conversation
cd88259 to
68fb6b6
Compare
|
Am Montag, dem 10.03.2025 um 09:39 -0700 schrieb Alejandro Colomar:
@alejandro-colomar commented on this pull request.
In lib/atoi/strtoi/strton.h:
> + \
+ if (*endp == s) \
+ *status = ECANCELED; \
+ else if (errno == ERANGE || n < min || n > max) \
+ *status = ERANGE; \
+ else if (**endp != '\0') \
+ *status = ENOTSUP; \
+ else \
+ *status = 0; \
+ \
+ errno = e; \
+ \
+ return MAX(min, MIN(max, n)); \
+}
+//#enddef
+#define STRTON(T, ...) STRTON__ ## T(__VA_ARGS__)
I could actually fix the off-by-one attributes by moving the T to the end of the parameter list, and using the explicit parameter list here instead of ....
I would just write it as STRTON__ ## in the definition
instead of using the STRTON macro, which would get rid
fo the off-by-one. I also hides less of mechanism which
I think is good.
I also wonder whether you can replace the code in
the c file with something such as
extern inline typeof(STRTON__ ## uintmax_t) STRTON__ ## uintmax_t;
instead of repeating all the arguments.
… —
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
The good thing about using STRTON() is that it looks like a function definition. grepc(1) (my regex-based program for grepping C code) finds it just fine. However, if I use ##, then the regex doesn't find it.
I'm not too worried, since that repetition is checked by the compiler. Also, the same argument applied: regex-based programs will find the prototypes using STRTON(). https://www.alejandro-colomar.es/src/alx/alx/grepc.git/tree/bin/grepc |
Actually, I correct myself. grepc(1) is able to grep the template definition with $ grepc -h CMP .
#define CMP(T) cmp__ ## T // For use as a callback$ grepc -hC1 'cmp__ ## T' .
#def template_cmp(T)
inline int
cmp__ ## T(const void *key, const void *elt)
{
const T *k = key;
const T *e = elt;
if (*k < *e)
return -1;
if (*k > *e)
return +1;
return 0;
}
#enddefSo, I'll follow your suggestion and make it explicit that I'm using |
No, you can't. search/cmp/cmp.c:12:28: error: stray '##' in program
12 | extern inline typeof(CMP__ ## int) CMP__ ## int;
| ^~
search/cmp/cmp.c:12:22: error: 'CMP__' undeclared here (not in a function); did you mean 'CMP'?
12 | extern inline typeof(CMP__ ## int) CMP__ ## int;
| ^~~~~
| CMP
search/cmp/cmp.c:12:27: error: expected ')' before 'int'
12 | extern inline typeof(CMP__ ## int) CMP__ ## int;
| ~ ^ ~~~
| )Concatenation doesn't work outside of macros. I guess I'll either concatenate myself, or write a small macro for that. |
084f3d7 to
e287e1b
Compare
lib/search/l/lfind.c
Outdated
| extern inline void *lfind_(const void *k, const void *a, size_t n, size_t ksize, | ||
| typeof(int (const void *k, const void *elt)) *cmp); | ||
| extern inline const int *LFIND__int(size_t n; | ||
| const int *k, const int a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.c
Outdated
| extern inline const int *LFIND__int(size_t n; | ||
| const int *k, const int a[n], size_t n); | ||
| extern inline const long *LFIND__long(size_t n; | ||
| const long *k, const long a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.c
Outdated
| extern inline const long *LFIND__long(size_t n; | ||
| const long *k, const long a[n], size_t n); | ||
| extern inline const u_int *LFIND__u_int(size_t n; | ||
| const u_int *k, const u_int a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.c
Outdated
| extern inline const u_int *LFIND__u_int(size_t n; | ||
| const u_int *k, const u_int a[n], size_t n); | ||
| extern inline const u_long *LFIND__u_long(size_t n; | ||
| const u_long *k, const u_long a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.h
Outdated
| /* lfind(3) wants a pointer to n for historic reasons. */ \ | ||
| return lfind(k, a, &n, sizeof(T), CMP(T)); \ | ||
| } | ||
| template_LFIND(int); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| { \ | ||
| lsearch(k, a, n, sizeof(T), CMP(T)); \ | ||
| } | ||
| template_LSEARCH(int); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| lsearch(k, a, n, sizeof(T), CMP(T)); \ | ||
| } | ||
| template_LSEARCH(int); | ||
| template_LSEARCH(long); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| } | ||
| template_LSEARCH(int); | ||
| template_LSEARCH(long); | ||
| template_LSEARCH(u_int); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| template_LSEARCH(int); | ||
| template_LSEARCH(long); | ||
| template_LSEARCH(u_int); | ||
| template_LSEARCH(u_long); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/sort/qsort.h
Outdated
| template_QSORT(int); | ||
| template_QSORT(long); | ||
| template_QSORT(u_int); | ||
| template_QSORT(u_long); |
Check notice
Code scanning / CodeQL
Short global name
12ff7c4 to
7716e5e
Compare
7716e5e to
37ea130
Compare
37ea130 to
4aeb169
Compare
818eb20 to
40b10cf
Compare
f101a61 to
25091f3
Compare
25091f3 to
8dd0396
Compare
0a3d6a1 to
d32bec8
Compare
d32bec8 to
d8cab62
Compare
2b74192 to
5550350
Compare
116ccb3 to
f91d495
Compare
8af07c0 to
a70fa5f
Compare
bb0de08 to
591deb0
Compare
591deb0 to
fc7b96a
Compare
bd1ece0 to
4d254ac
Compare
It won't hurt; if the type is convertible, it will be accepted; and if it's not convertible, the compiler will reject it at call site. This 'default' branch allows converting a QChar** into a char**. Signed-off-by: Alejandro Colomar <alx@kernel.org>
This allows grepping for casts more easily. It also reduces the damage of a bogus cast. Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
We don't need the return value of lsearch_T() at all; let's remove it. We don't need to modify the return value of lfind_T(); make it const. Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This allows us to get rid of ({}), which is a GNU extension.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
4d254ac to
d7fd67d
Compare
Cc: @uecker
Cc: @chrisbazley
This is an experiment about mimicking templates in C with macros. If we get rid of the trailing
\, this looks quite nice.