p99_map.h 12.6 KB
Newer Older
(no author)'s avatar
(no author) committed
1
2
/* This may look like nonsense, but it really is -*- mode: C -*-              */
/*                                                                            */
3
/* Except for parts copied from previous work and as explicitly stated below, */
(no author)'s avatar
(no author) committed
4
/* the authors and copyright holders for this work are as follows:            */
5
/* (C) copyright  2010-2013 Jens Gustedt, INRIA, France                       */
(no author)'s avatar
(no author) committed
6
7
8
9
10
11
12
13
/* (C) copyright  2012 William Morris                                         */
/*                                                                            */
/* This file is free software; it is part of the P99 project.                 */
/* You can redistribute it and/or modify it under the terms of the QPL as     */
/* given in the file LICENSE. It is distributed without any warranty;         */
/* without even the implied warranty of merchantability or fitness for a      */
/* particular purpose.                                                        */
/*                                                                            */
(no author)'s avatar
(no author) committed
14
15
#ifndef     P99_MAP_H_
# define    P99_MAP_H_
16

Jens Gustedt's avatar
Jens Gustedt committed
17
18
19
20
21
22
/**
 ** @file
 ** @brief macros to produce lists of statements or declarations.
 ** @see statement_lists
 **/

23
#include "p99_for.h"
24

25
/** @addtogroup statement_lists Produce C99 statements or expression lists
26
 **
27
28
29
 ** This provides tools to produce a list of declarations (e.g @c
 ** typedef), list of initializers or perform a sequence of additions
 ** or other operations. The input usually is just a list of names, e.g.
30
 **
31
32
33
34
 ** @{
 **/


35
#define P00_ACCESSOR(NAME, X, I) P99_IF_EMPTY(NAME)([I])((NAME)[I])
36
37
38
39
#define P00_VASSIGN(NAME, X, I) X = P00_ACCESSOR(NAME, X, I)
#define P00_STRLEN(NAME, X, I) strlen(X)
#define P00_SIZEOF(NAME, X, I) sizeof(X)
#define P00_TYPD(NAME, X, I) typedef X P99_PASTE2(NAME, I)
40
#define P00_DESIGNATE(NAME, X, I) X = (NAME)X
41
#define P00_ADD(NAME, I, REC, RES) P99_ADD(RES, REC)
42

43
44
45
#define P00_STRLENS(N, ...) P99_FOR(,N, P00_SUM, P00_STRLEN, __VA_ARGS__)
#define P00_SIZEOFS(N, ...) P99_FOR(,N, P00_SUM, P00_SIZEOF, __VA_ARGS__)
#define P00_ADDS(N, ...) P99_FOR(, N, P00_ADD, P00_IDT, __VA_ARGS__)
46

47
48
49
50
51
52
53
54
55
56
#define P00_POW0(X, _1, _2) (X)
#define P00_POW(X, _1, REC, _3) (X) * REC

/**
 ** @brief Compute the @a N<sup>th</sup> multiplicative integer power of @a X.
 **
 ** @a N must be a decimal constant without suffixes. The value @c 0
 ** is special in that it evaluates to a @c 1 that is promoted to the
 ** promoted type of @a X.
 **/
57
58
P00_DOCUMENT_NUMBER_ARGUMENT(P99_IPOW, 0)
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_IPOW, 1)
59
60
#define P99_IPOW(N, X) P99_IF_EQ(N,0)(P99_SIGN_PROMOTE(1, X))((P99_FOR(X, N, P00_POW, P00_POW0, P99_REP(N,))))

61
62
63
64
/**
 ** @brief Return an expression that returns the sum of the lengths of
 ** all strings that are given as arguments.
 **/
65
#define P99_STRLENS(...) P00_STRLENS(P99_NARG(__VA_ARGS__),__VA_ARGS__)
66

67
68
/**
 ** @brief Return an expression that returns the sum of the size of
69
 ** all arguments.
70
 **/
71
#define P99_SIZEOFS(...) P00_SIZEOFS(P99_NARG(__VA_ARGS__),__VA_ARGS__)
72

73
74
75
/**
 ** @brief Return a token that is the sum of all arguments.
 **/
76
#define P99_ADDS(...) P00_ADDS(P99_NARG(__VA_ARGS__),__VA_ARGS__)
77

78
#ifndef P00_DOXYGEN
79
P99_DECLARE_STRUCT(p00_strcat_state);
80
#endif
81

82
struct p00_strcat_state {
83
84
  char*restrict p00_buf;
  char*restrict p00_pos;
85
86
};

87
#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
88
p99_inline
89
90
char *p00_stpcpy(char *restrict p00_des, const char *restrict p00_src) {
  return stpcpy(p00_des, p00_src);
91
92
93
}
#else
p99_inline
94
char *p00_stpcpy(char *restrict p00_des, const char *restrict p00_src) {
95
  for (;;) {
96
97
98
    *p00_des = *p00_src;
    if (!*p00_src) break;
    ++p00_des; ++p00_src;
99
  }
100
  return p00_des;
101
102
103
104
105
}
#endif


p99_inline
106
107
108
109
p00_strcat_state* p00_strcat(p00_strcat_state *restrict p00_des, char const*restrict p00_src) {
  if (!p00_des->p00_pos) p00_des->p00_pos = strchr(p00_des->p00_buf, 0);
  p00_des->p00_pos = p00_stpcpy(p00_des->p00_pos, p00_src);
  return p00_des;
110
}
111

112
p99_inline
113
114
char* p00_strcat_terminate(p00_strcat_state *restrict p00_des) {
  return p00_des->p00_buf;
115
}
116
117
118
119

/**
 ** @brief Append all argument strings after @a TARG to @a TARG.
 **
120
121
122
123
 ** @a TARG should be compatible with @c char* and must provide enough
 ** space to hold the concatenation of all strings. The remaining
 ** arguments must be compatible with @c const char*.
 **
124
125
126
 ** This macro ensures linear complexity in the operation. In
 ** particular each position in the argument strings is accessed at
 ** most twice, once by a call to strlen and once by a call to
127
128
129
130
131
 ** memcpy.
 **
 ** This uses some small inlined helper functions, since the repeated
 ** use of bare @c strcat would have quadratic complexity.
 **
132
 ** The resulting replacement produced by this macro evaluates
133
 ** each of the arguments at most once.
134
 **/
135
#define P99_STRCATS(TARG, ...)                                 \
Jens Gustedt's avatar
Jens Gustedt committed
136
p00_strcat_terminate                                           \
137
(P99_BIGFUNC                                                   \
Jens Gustedt's avatar
Jens Gustedt committed
138
 (p00_strcat,                                                  \
139
  P99_NARG(TARG, __VA_ARGS__),                                 \
140
  (&(p00_strcat_state){ .p00_buf = (TARG), .p00_pos = 0  }),   \
141
   __VA_ARGS__))
142
143
144
145
146
147
148
149
150
151
152
153
154

/**
 ** @brief Concatenate all arguments.
 **
 ** All arguments must be strings for which the length can be computed
 ** at compile time.
 **
 ** @return a temporary string that is valid in the containing block
 ** of the expression holding the call to this macro.
 **
 ** @see P99_STRDUP for a variant that returns a @c malloc'ed string and
 ** thus can be called with any type of @c char* arguments.
 **/
155
156
157
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_JOIN, 0)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_JOIN, 1)
P00_DOCUMENT_PERMITTED_ARGUMENT(P99_JOIN, 2)
158
#define P99_JOIN(...) P99_STRCATS((char[P99_SIZEOFS(__VA_ARGS__) + 1]){ 0 }, __VA_ARGS__)
159
160
161
162
163

/**
 ** @brief Concatenate all arguments.
 **
 ** @return a string that must be freed by @c free
164
 **
165
 ** The resulting replacement produced by this macro evaluates
166
 ** each of the arguments twice; once to compute the overall length of
167
 ** the new string and then again for the duplication operation.
168
 **/
169
170
171
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_STRDUP, 0)
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_STRDUP, 1)
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_STRDUP, 2)
172
#define P99_STRDUP(...) P99_STRCATS(calloc(P99_STRLENS(__VA_ARGS__) + 16, 1), __VA_ARGS__)
173
174
175
176
177

/**
 ** @brief Produce a list of length @a N that has the contents of 0,
 ** 1, , @a N-1
 **/
178
P00_DOCUMENT_NUMBER_ARGUMENT(P99_POSS, 0)
179
#define P99_POSS(N) P99_FOR(,N, P00_SEQ, P00_POS,)
180

181
182
183

#define P00_ACCESSORS(X, ...) P99_FOR(X, __VA_ARGS__, P00_SEQ, P00_ACCESSOR, )

184
185
186
187
188
/**
 ** Produce a list of length @a N that has the contents of @a X[0], @a
 ** X [1], ,
 ** @a X[@a N-1]
 **/
189
190
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_ACCESSORS, 0)
P00_DOCUMENT_NUMBER_ARGUMENT(P99_ACCESSORS, 1)
191
#define P99_ACCESSORS(X, N) P00_ACCESSORS(X, N)
192
193
194
195
196
197
198
199
200


/**
 ** @brief Vector-assign to a list
 **
 ** Produce a list of length @c N that has the contents of @c V0 = @a
 ** NAME[0], @c V1 = @a NAME[1], ..., @c VN-1 = @a NAME[@a N-1], where
 ** V0, etc are the remaining arguments.
 **/
201
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_VASSIGNS, 0)
Jens Gustedt's avatar
Jens Gustedt committed
202
#define P99_VASSIGNS(NAME, ...)                                            \
203
P99_IF_LT(P99_NARG(__VA_ARGS__),2)                                         \
Jens Gustedt's avatar
Jens Gustedt committed
204
(P99_IF_VOID(__VA_ARGS__)((void)0)(__VA_ARGS__ = (NAME)[0]))               \
205
  (P99_FOR(NAME, P00_NARG(__VA_ARGS__),P00_SEP, P00_VASSIGN, __VA_ARGS__))
206

Jens Gustedt's avatar
Jens Gustedt committed
207
#define P00_TYPEDEFS(NAME, N, ...)                             \
208
209
  P99_IF_VOID(__VA_ARGS__)                                     \
  (P99_MACRO_END(NAME, _eat_the_semicolon_, N))                \
210
  (P99_FOR(NAME, N, P00_SEP, P00_TYPD, __VA_ARGS__))
211
212

/**
213
 ** @brief Take each argument on the list and transform it into a
214
215
 ** @c typedef of name NAME_0, NAME_1, etc.
 **
216
 ** Due to syntax problems this can't be used for function or
217
218
 ** array type derivatives.
 **/
219
#define P99_TYPEDEFS(NAME, ...)                                \
220
P00_TYPEDEFS(NAME, P99_NARG(__VA_ARGS__), __VA_ARGS__)
221

222
#define P00_DESIGNATED(VAR, N, ...) P99_FOR(VAR, N, P00_SEQ, P00_DESIGNATE, __VA_ARGS__)
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/**
 ** @brief Construct a designated initializer by copying fields of @a VAR.
 **
 ** The argument list must be composed of designators, something like
 ** @code
 ** struct toto { int a; int b; } A = { .a = 9, .b = 7 };
 ** struct toto B = P99_DESIGNATED(A, .b);
 ** double C[4] = { 1, 2, 3, 4 };
 ** double D[4] = P99_DESIGNATED(C, [0], [2]);
 ** @endcode
 **
 ** So here @c B.b is initialized with the value of @c A.b and @c B.a,
 ** since @c .a is not in the list, is initialized by 0. Likewise @c D
 ** gets copies of @c C[0] and @c C[2] and the other fields are
 ** initialized to @c 0.
 ** @see P99_LCOPY
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_DESIGNATED, 0)
P00_DOCUMENT_DESIGNATOR_ARGUMENT(P99_DESIGNATED, 1)
P00_DOCUMENT_DESIGNATOR_ARGUMENT(P99_DESIGNATED, 2)
P00_DOCUMENT_DESIGNATOR_ARGUMENT(P99_DESIGNATED, 3)
#define P99_DESIGNATED(VAR, ...) { P00_DESIGNATED(VAR, P99_NARG(__VA_ARGS__), __VA_ARGS__) }

247
248
249
/**
 ** @brief Expand to an array initializer copying array @a VAR for @a N positions.
 **
250
 ** This can be used to initialize an array with a designated
251
252
253
254
255
256
257
258
259
260
 ** initializer that is derived from another array.
 ** @code
 ** double B[] = P99_ADESIGNATED(A, 3);
 ** @endcode
 **
 ** Would initialize @c B to be an array of 3 @c double that are
 ** copies of the first three values of @c A.
 **/
#define P99_ADESIGNATED(VAR, N) P99_DESIGNATED(VAR, P99_ACCESSORS(, N))

261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/**
 ** @brief Construct a compound literal of type @a TYPE by copying fields of @a VAR.
 **
 ** The argument list must be composed of designators, something like
 ** @code
 ** struct toto { int a; int b; } A = { .a = 9, .b = 7 };
 ** struct toto B = P99_LCOPY(struct toto, A, .b);
 ** double C[4] = { 1, 2, 3, 4 };
 ** double *D = P99_LCOPY(double[4], C, [0], [2]);
 ** @endcode
 **
 ** So here @c B.b is initialized with the value of @c A.b and @c B.a,
 ** since @c .a is not in the list, is initialized by 0. Likewise @c D
 ** gets copies of @c C[0] and @c C[2] and the other fields are
 ** initialized to @c 0.
 **
 ** This is probably best used indirectly inside a type specific
 ** macro. E.g if you know that the copy operation for @c toto as
279
 ** above should always copy only @c .b and not @c .a you could do
280
281
282
283
284
285
286
287
288
289
290
291
 ** @code
 ** #define TOTO_LCOPY(A) P99_LCOPY(struct toto, A, .b);
 ** struct toto B = TOTO_LCOPY(A);
 ** @endcode
 ** @see P99_DESIGNATED
 **/
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_LCOPY, 1)
P00_DOCUMENT_TYPE_ARGUMENT(P99_LCOPY, 0)
P00_DOCUMENT_DESIGNATOR_ARGUMENT(P99_LCOPY, 2)
P00_DOCUMENT_DESIGNATOR_ARGUMENT(P99_LCOPY, 3)
P00_DOCUMENT_DESIGNATOR_ARGUMENT(P99_LCOPY, 4)
#define P99_LCOPY(TYPE, VAR, ...) ((TYPE)P99_DESIGNATED(VAR, __VA_ARGS__))
292

293
294
295
296
297

#define P00_ACOPY4(TYPE, N, VAR, ...) ((TYPE[N])P99_DESIGNATED(VAR, P00_ACCESSORS(, __VA_ARGS__)))

#define P00_ACOPY3(TYPE, N, VAR) P00_ACOPY4(TYPE, N, VAR, N)

Jens Gustedt's avatar
Jens Gustedt committed
298
#ifdef P00_DOXYGEN
299
300
301
302
/**
 ** @brief Expand to an array literal of type @a TYPE[@a N] copying
 ** from another array.
 **
Jens Gustedt's avatar
Jens Gustedt committed
303
304
 ** The third argument is the array @a VAR to be copied from. The
 ** optional forth argument @a M is the number of elements from @c VAR
305
 ** that are to be copied. It defaults to @a N if omitted. Obviously
306
 ** we must always have <code>M <= N</code> for this to work.
307
 **
308
 ** This can be used to call a function with a copy of
309
310
311
312
 ** of @a VAR.
 **
 ** @remark The base type of @a VAR must be assignment compatible with type @a TYPE.
 **/
Jens Gustedt's avatar
Jens Gustedt committed
313
314
#define P99_ACOPY(TYPE, N, VAR, M)
#else
315
316
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_ACOPY, 2)
P00_DOCUMENT_DECLARATION_ARGUMENT(P99_ACOPY, 4)
(no author)'s avatar
(no author) committed
317
318
319
#define P99_ACOPY(TYPE, N, ...)                                \
P99_IF_LT(P99_NARG(__VA_ARGS__), 2)                            \
(P00_ACOPY3(TYPE, N, __VA_ARGS__))                             \
320
(P00_ACOPY4(TYPE, N, __VA_ARGS__))
Jens Gustedt's avatar
Jens Gustedt committed
321
#endif
322

Jens Gustedt's avatar
Jens Gustedt committed
323
#ifdef P00_DOXYGEN
Jens Gustedt's avatar
Jens Gustedt committed
324
325
326
327
328
329
330
331
332
333
334
335
/**
 ** @brief Assign the content of array @a SOURCE to @a TARGET.
 **
 ** Only the @a N first elements are copied. Use it as in
 ** @code
 ** size_t B[4] = { 2, 3, 4, 5 };
 ** double *A = malloc(sizeof(double[4]));
 ** P99_AASSIGN(A, B, 4);
 ** @endcode
 **
 ** @pre @a N must expand to a decimal integer constant.
 **
336
 ** @pre @a SOURCE and @a TARGET must be arrays with a size of at least @a N
Jens Gustedt's avatar
Jens Gustedt committed
337
338
 ** or pointers that point to such arrays.
 **
339
 ** @remark If @a TARGET has more than @a N elements the excess
Jens Gustedt's avatar
Jens Gustedt committed
340
341
 ** elements are left untouched.
 **
342
343
 ** @remark The base types must not necessarily be the same but that
 ** of @a SOURCE must be assignable to that for @a TARGET. In
Jens Gustedt's avatar
Jens Gustedt committed
344
 ** particular, the type of @a TARGET should be at least as wide as
345
 ** that for @a SOURCE.
Jens Gustedt's avatar
Jens Gustedt committed
346
 **/
Jens Gustedt's avatar
Jens Gustedt committed
347
348
#define P99_AASSIGN(TARGET, SOURCE, N)
#else
Jens Gustedt's avatar
Jens Gustedt committed
349
350
351
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_AASSIGN, 0)
P00_DOCUMENT_MULTIPLE_ARGUMENT(P99_AASSIGN, 1)
#define P99_AASSIGN(TARGET, SOURCE, N) P99_BLOCK(P99_VASSIGNS(SOURCE, P99_ACCESSORS(TARGET, N));)
Jens Gustedt's avatar
Jens Gustedt committed
352
#endif
Jens Gustedt's avatar
Jens Gustedt committed
353

354
355
356
/** @}
 **/

(no author)'s avatar
(no author) committed
357
#endif      /* !P99_MAP_H_ */