permit multiline comments and strings in macros
[bpt/coccinelle.git] / parsing_c / cpp_token_c.ml
CommitLineData
708f4980
C
1open Common
2
3module TH = Token_helpers
4
5open Parser_c
6open Token_views_c
7
8(*****************************************************************************)
9(* Prelude *)
10(*****************************************************************************)
11
12(* cpp functions working at the token level. Cf cpp_ast_c for cpp functions
ae4735db 13 * working at the AST level (which is very unusual but makes sense in
708f4980 14 * the coccinelle context for instance).
ae4735db 15 *
708f4980 16 * Note that as I use a single lexer to work both at the C and cpp level
ae4735db
C
17 * there are some inconveniencies.
18 * For instance 'for' is a valid name for a macro parameter and macro
19 * body, but is interpreted in a special way by our single lexer, and
708f4980
C
20 * so at some places where I expect a TIdent I need also to
21 * handle special cases and accept Tfor, Tif, etc at those places.
ae4735db 22 *
708f4980
C
23 * There are multiple issues related to those keywords incorrect tokens.
24 * Those keywords can be:
25 * - (1) in the name of the macro as in #define inline
26 * - (2) in a parameter of the macro as in #define foo(char) char x;
27 * - (3) in an argument to a macro call as in IDENT(if);
28 * Case 1 is easy to fix in define_ident.
ae4735db 29 * Case 2 is easy to fix in define_parse where detect such toks in
708f4980 30 * the parameter and then replace their occurence in the body in a Tident.
ae4735db 31 * Case 3 is only an issue when the expanded token is not really use
708f4980
C
32 * as usual but use for instance in concatenation as in a ## if
33 * when expanded. In the case the grammar this time will not be happy
34 * so this is also easy to fix in cpp_engine.
ae4735db 35 *
708f4980
C
36 *)
37
38(*****************************************************************************)
39(* Wrappers *)
40(*****************************************************************************)
ae4735db 41let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_parsing
708f4980
C
42
43(*****************************************************************************)
44(* Types *)
45(*****************************************************************************)
46
708f4980
C
47(* ------------------------------------------------------------------------- *)
48(* mimic standard.h *)
49(* ------------------------------------------------------------------------- *)
50
ae4735db
C
51type define_def = string * define_param * define_body
52 and define_param =
708f4980 53 | NoParam
abad11c5
C
54 | Params of define_arg list
55 and define_arg = FixedArg of string | VariadicArg of string
ae4735db 56 and define_body =
708f4980
C
57 | DefineBody of Parser_c.token list
58 | DefineHint of parsinghack_hint
59
ae4735db 60 and parsinghack_hint =
708f4980
C
61 | HintIterator
62 | HintDeclarator
63 | HintMacroString
64 | HintMacroStatement
65 | HintAttribute
66 | HintMacroIdentBuilder
67
68
978fd7e5
C
69(*****************************************************************************)
70(* Parsing and helpers of hints *)
71(*****************************************************************************)
708f4980
C
72
73(* cf also data/test.h *)
74let assoc_hint_string = [
75 "YACFE_ITERATOR" , HintIterator;
76 "YACFE_DECLARATOR" , HintDeclarator;
77 "YACFE_STRING" , HintMacroString;
78 "YACFE_STATEMENT" , HintMacroStatement;
79 "YACFE_ATTRIBUTE" , HintAttribute;
80 "YACFE_IDENT_BUILDER" , HintMacroIdentBuilder;
81
82 "MACROSTATEMENT" , HintMacroStatement; (* backward compatibility *)
83]
84
85
ae4735db 86let (parsinghack_hint_of_string: string -> parsinghack_hint option) = fun s ->
708f4980 87 Common.assoc_option s assoc_hint_string
ae4735db 88let (string_of_parsinghack_hint: parsinghack_hint -> string) = fun hint ->
978fd7e5
C
89 let assoc' = assoc_hint_string +> List.map (fun (a,b) -> (b,a) ) in
90 Common.assoc hint assoc'
91
92
708f4980 93
ae4735db 94let (is_parsinghack_hint: string -> bool) = fun s ->
708f4980
C
95 parsinghack_hint_of_string s <> None
96
ae4735db
C
97let (token_from_parsinghack_hint:
98 (string * Ast_c.info) -> parsinghack_hint -> Parser_c.token) =
708f4980
C
99 fun (s,ii) hint ->
100 match hint with
ae4735db 101 | HintIterator ->
708f4980 102 Parser_c.TMacroIterator (s, ii)
ae4735db 103 | HintDeclarator ->
708f4980 104 Parser_c.TMacroDecl (s, ii)
ae4735db 105 | HintMacroString ->
708f4980 106 Parser_c.TMacroString (s, ii)
ae4735db 107 | HintMacroStatement ->
708f4980 108 Parser_c.TMacroStmt (s, ii)
ae4735db 109 | HintAttribute ->
708f4980 110 Parser_c.TMacroAttr (s, ii)
ae4735db 111 | HintMacroIdentBuilder ->
708f4980 112 Parser_c.TMacroIdentBuilder (s, ii)
ae4735db 113
708f4980 114
978fd7e5
C
115(* used in extract_macros for example *)
116let string_of_define_def (s, params, body) =
708f4980 117
ae4735db 118 let s1 =
978fd7e5 119 match params with
ae4735db 120 | NoParam ->
978fd7e5 121 spf "#define %s " s
ae4735db 122 | Params xs ->
abad11c5 123 let xs = List.map (function FixedArg s -> s | VariadicArg s -> s) xs in
978fd7e5
C
124 spf "#define %s(%s) " s (Common.join "," xs)
125 in
ae4735db 126 let s2 =
978fd7e5 127 match body with
ae4735db 128 | DefineHint hint ->
978fd7e5 129 string_of_parsinghack_hint hint
ae4735db 130 | DefineBody xs ->
978fd7e5
C
131 Common.join " " (xs +> List.map Token_helpers.str_of_tok)
132 in
133 s1 ^ s2
708f4980
C
134
135
136(*****************************************************************************)
137(* Expansion helpers *)
138(*****************************************************************************)
139
ae4735db
C
140(* In some cases we can have macros like IDENT(if) that expands to some
141 * 'int xxx_if(void)', but as the lexer will currently generate a Tif for
708f4980
C
142 * the expanded code, that may not be accepted as a token after a ##
143 * in the grammar. Hence this function to remap some tokens. This is because
144 * we should not use a single lexer for both working at the C level and
145 * cpp level.
ae4735db
C
146 *
147 * update: it can also rename some TypedefIdent into TIdent, possibly
708f4980
C
148 * because of bad interaction with add_typedef_root in parsing_hacks.
149 *)
ae4735db 150let rec remap_keyword_tokens xs =
708f4980
C
151 match xs with
152 | [] -> []
153 | [x] -> [x]
ae4735db 154 | x::y::xs ->
708f4980 155 (match x, y with
ae4735db 156 | Parser_c.TCppConcatOp _, Parser_c.TIdent _ ->
708f4980 157 x::y::remap_keyword_tokens xs
ae4735db 158 | Parser_c.TIdent _, Parser_c.TCppConcatOp _ ->
708f4980
C
159 x::y::remap_keyword_tokens xs
160
ae4735db 161 | Parser_c.TCppConcatOp (i1), y ->
708f4980
C
162 let s = TH.str_of_tok y in
163 let ii = TH.info_of_tok y in
164 if s ==~ Common.regexp_alpha
165 then begin
978fd7e5 166 pr2 (spf "remapping: %s to an ident in expanded code" s);
708f4980
C
167 x::(Parser_c.TIdent (s, ii))::remap_keyword_tokens xs
168 end
ae4735db 169 else
708f4980
C
170 x::y::remap_keyword_tokens xs
171
ae4735db 172 | x, Parser_c.TCppConcatOp (i1) ->
708f4980
C
173 let s = TH.str_of_tok x in
174 let ii = TH.info_of_tok x in
175 if s ==~ Common.regexp_alpha
176 then begin
978fd7e5 177 pr2 (spf "remapping: %s to an ident in expanded code" s);
708f4980
C
178 (Parser_c.TIdent (s, ii))::remap_keyword_tokens (y::xs)
179 end
ae4735db 180 else
708f4980
C
181 x::y::remap_keyword_tokens xs
182
ae4735db 183 | _, _ ->
708f4980
C
184 x::remap_keyword_tokens (y::xs)
185 )
978fd7e5
C
186
187
188(* works with agglomerate_concat_op_ident below *)
ae4735db 189let rec get_ident_in_concat_op xs =
978fd7e5 190 match xs with
ae4735db 191 | [] ->
978fd7e5
C
192 pr2 "weird: ident after ## operator not found";
193 "", []
ae4735db 194 | [x] ->
978fd7e5
C
195 (match x with
196 | Parser_c.TIdent (s, i1) -> s, []
ae4735db 197 | _ ->
978fd7e5
C
198 pr2 "weird: ident after ## operator not found";
199 "", [x]
200 )
ae4735db 201 | x::y::xs ->
978fd7e5 202 (match x, y with
ae4735db 203 | Parser_c.TIdent (s,i1), Parser_c.TCppConcatOp (i2) ->
978fd7e5
C
204 let (s2, rest) = get_ident_in_concat_op xs in
205 s ^ s2, rest
ae4735db 206 | Parser_c.TIdent (s, i1), _ ->
978fd7e5 207 s, (y::xs)
ae4735db 208 | _ ->
978fd7e5
C
209 pr2 "weird: ident after ## operator not found";
210 "", x::y::xs
211 )
212
213(* must be run after the expansion has been done for the parameter so
214 * that all idents are actually ident, not macro parameter names.
215 *)
ae4735db 216let rec agglomerate_concat_op_ident xs =
978fd7e5
C
217 match xs with
218 | [] -> []
219 | [x] -> [x]
ae4735db
C
220 | x::y::xs ->
221 (* can we have ## id, and so ## as first token ? yes
978fd7e5
C
222 * but the semantic is different as it represents variadic
223 * names so this must be handled elsewhere.
224 *)
225 (match x, y with
ae4735db
C
226 | Parser_c.TIdent (s,i1), Parser_c.TCppConcatOp (i2) ->
227 let (all_str_ident, rest_toks) =
978fd7e5
C
228 get_ident_in_concat_op xs
229 in
230 let new_s = s ^ all_str_ident in
231 let i1' = Ast_c.rewrap_str new_s i1 in
232 Parser_c.TIdent (new_s, i1')::agglomerate_concat_op_ident rest_toks
ae4735db 233 | Parser_c.TCppConcatOp _, _ ->
978fd7e5
C
234 pr2 "weird, ## alone";
235 x::agglomerate_concat_op_ident (y::xs)
ae4735db 236 | _ ->
978fd7e5 237 x::agglomerate_concat_op_ident (y::xs)
ae4735db 238
978fd7e5 239 )
ae4735db
C
240
241
708f4980
C
242
243(* To expand the parameter of the macro. The env corresponds to the actual
244 * code that is binded to the parameters of the macro.
245 * Recurse ? fixpoint ? the expansion may also contain macro.
246 * Or to macro expansion in a strict manner, that is process first
247 * the parameters, expands macro in params, and then process enclosing
248 * macro call.
ae4735db 249 *
708f4980
C
250 * note: do the concatenation job of a##b here ?
251 * normally this should be done in the grammar. Here just expand
252 * tokens. The only thing we handle here is we may have to remap
253 * some tokens.
ae4735db 254 *
708f4980 255 * todo: handle stringification here ? if #n
ae4735db
C
256 *
257 * todo? but could parsing_hacks then pass over the remapped tokens,
708f4980
C
258 * for instance transform some of the back into some TypedefIdent
259 * so cpp_engine may be fooled?
260 *)
ae4735db 261let rec (cpp_engine:
978fd7e5 262 ?evaluate_concatop:bool ->
ae4735db
C
263 (string , Parser_c.token list) assoc ->
264 Parser_c.token list -> Parser_c.token list) =
978fd7e5 265 fun ?(evaluate_concatop=true) env xs ->
ae4735db 266 xs +> List.map (fun tok ->
708f4980 267 (* expand only TIdent ? no cos the parameter of the macro
ae4735db 268 * can actually be some 'register' so may have to look for
708f4980
C
269 * any tokens candidates for the expansion.
270 * Only subtelity is maybe dont expand the TDefineIdent.
ae4735db
C
271 *
272 * update: in fact now the caller (define_parse) will have done
708f4980
C
273 * the job right and already replaced the macro parameter with a TIdent.
274 *)
275 match tok with
abad11c5
C
276 | TIdent (s,i1) when List.mem_assoc s env ->
277 Common.assoc s env
708f4980
C
278 | x -> [x]
279 )
280 +> List.flatten
281 +> remap_keyword_tokens
ae4735db 282 +> (fun xs ->
978fd7e5
C
283 if evaluate_concatop
284 then agglomerate_concat_op_ident xs
285 else xs
ae4735db 286 )
708f4980
C
287
288
289
290(* ------------------------------------------------------------------------- *)
291(* apply macro, using standard.h or other defs *)
292(* ------------------------------------------------------------------------- *)
293
294(* Thanks to this function many stuff are not anymore hardcoded in ocaml code.
ae4735db 295 * At some point there were hardcoded in a standard.h file but now I
708f4980
C
296 * can even generate them on the fly on demand when there is actually
297 * a parsing problem.
ae4735db 298 *
708f4980
C
299 * No need to take care to not substitute the macro name itself
300 * that occurs in the macro definition because the macro name is
301 * after fix_token_define a TDefineIdent, no more a TIdent.
302 *)
303
ae4735db
C
304let rec apply_macro_defs
305 ~msg_apply_known_macro
306 ~msg_apply_known_macro_hint
978fd7e5
C
307 ?evaluate_concatop
308 ?(inplace_when_single=true)
ae4735db 309 defs xs =
993936c0 310
ae4735db 311 let rec apply_macro_defs xs =
708f4980
C
312 match xs with
313 | [] -> ()
314
315 (* old: "but could do more, could reuse same original token
316 * so that have in the Ast a Dbg, not a MACROSTATEMENT"
ae4735db
C
317 *
318 * | PToken ({tok = TIdent (s,i1)} as id)::xs
319 * when s = "MACROSTATEMENT" ->
320 *
708f4980
C
321 * msg_macro_statement_hint s;
322 * id.tok <- TMacroStmt(TH.info_of_tok id.tok);
323 * find_macro_paren xs
ae4735db
C
324 *
325 * let msg_macro_statement_hint s =
708f4980
C
326 * incr Stat.nMacroHint;
327 * ()
ae4735db 328 *
708f4980
C
329 *)
330
331 (* recognized macro of standard.h (or other) *)
ae4735db
C
332 | PToken ({tok = TIdent (s,i1)} as id)::Parenthised (xxs,info_parens)::xs
333 when Hashtbl.mem defs s ->
334
708f4980
C
335 msg_apply_known_macro s;
336 let (s, params, body) = Hashtbl.find defs s in
337
338 (match params with
ae4735db 339 | NoParam ->
708f4980
C
340 pr2 ("WEIRD: macro without param used before parenthize: " ^ s);
341 (* ex: PRINTP("NCR53C400 card%s detected\n" ANDP(((struct ... *)
342
343 (match body with
ae4735db 344 | DefineBody bodymacro ->
708f4980
C
345 set_as_comment (Token_c.CppMacro) id;
346 id.new_tokens_before <- bodymacro;
ae4735db 347 | DefineHint hint ->
708f4980
C
348 msg_apply_known_macro_hint s;
349 id.tok <- token_from_parsinghack_hint (s,i1) hint;
350 )
ae4735db 351 | Params params ->
708f4980 352 (match body with
ae4735db 353 | DefineBody bodymacro ->
708f4980 354
ae4735db 355 (* bugfix: better to put this that before the match body,
abad11c5
C
356 * cos our macrostatement hint can have variable number of
357 * arguments and so it's ok if it does not match exactly
358 * the number of arguments. *)
359 let build_binder params xxs =
360 let rec loop = function
361 ([],[]) -> Some (function [] -> [] | _ -> failwith "bad")
1b9ae606 362 | ([],[[]]) -> Some (function [[]] -> [] | _ -> failwith "bad")
abad11c5
C
363 | ([],l) -> None
364 | ([(VariadicArg s)],l) ->
365 Some (function l -> List.map (function a -> (s,a)) l)
366 | ((VariadicArg _)::_,l) -> None
367 | ((FixedArg _)::_,[]) -> None
368 | ((FixedArg s)::rest,x::xs) ->
369 (match loop (rest,xs) with
370 Some k ->
371 Some (function l -> (s,(List.hd l)) :: k (List.tl l))
372 | None -> None) in
373 loop (params, xxs) in
374 (match build_binder params xxs with
375 None ->
376 pr2_once
377 ("WEIRD: macro with wrong number of arguments: " ^ s);
378 (* old: id.new_tokens_before <- bodymacro; *)
379
380 (* update: if wrong number, then I just pass this macro *)
381 [Parenthised (xxs, info_parens)] +>
708f4980 382 iter_token_paren (set_as_comment Token_c.CppMacro);
abad11c5
C
383 set_as_comment Token_c.CppMacro id
384 | Some bind ->
385
386 let xxs' = xxs +> List.map (fun x ->
387 (tokens_of_paren_ordered x) +> List.map (fun x ->
388 TH.visitor_info_of_tok Ast_c.make_expanded x.tok
389 )
390 ) in
391 id.new_tokens_before <-
392 (* !!! cpp expansion job here !!! *)
393 cpp_engine ?evaluate_concatop
394 (bind xxs') bodymacro;
395
396 (* important to do that after have apply the macro,
397 otherwise will pass as argument to the macro some
398 tokens that are all TCommentCpp
399 *)
400 [Parenthised (xxs, info_parens)] +>
708f4980 401 iter_token_paren (set_as_comment Token_c.CppMacro);
abad11c5
C
402 set_as_comment Token_c.CppMacro id)
403
404 | DefineHint (HintMacroStatement as hint) ->
708f4980 405 (* important to do that after have apply the macro, otherwise
abad11c5 406 * will pass as argument to the macro some tokens that
708f4980 407 * are all TCommentCpp
ae4735db 408 *
708f4980
C
409 * note: such macrostatement can have a variable number of
410 * arguments but here we don't care, we just pass all the
411 * parameters.
412 *)
413
414 (match xs with
ae4735db
C
415 | PToken ({tok = TPtVirg _} as id2)::_ ->
416 pr2_once
708f4980
C
417 ("macro stmt with trailing ';', passing also ';' for: "^
418 s);
419 (* sometimes still want pass its params ... as in
420 * DEBUGPOLL(static unsigned int prev_mask = 0);
421 *)
422
423 msg_apply_known_macro_hint s;
424 id.tok <- token_from_parsinghack_hint (s,i1) hint;
ae4735db 425 [Parenthised (xxs, info_parens)] +>
708f4980
C
426 iter_token_paren (set_as_comment Token_c.CppMacro);
427 set_as_comment Token_c.CppMacro id2;
428
429 | _ ->
430 msg_apply_known_macro_hint s;
431 id.tok <- token_from_parsinghack_hint (s,i1) hint;
ae4735db 432 [Parenthised (xxs, info_parens)] +>
708f4980
C
433 iter_token_paren (set_as_comment Token_c.CppMacro);
434 )
708f4980 435
ae4735db
C
436
437 | DefineHint hint ->
708f4980
C
438 msg_apply_known_macro_hint s;
439 id.tok <- token_from_parsinghack_hint (s,i1) hint;
440 )
441 );
442 apply_macro_defs xs
443
ae4735db
C
444 | PToken ({tok = TIdent (s,i1)} as id)::xs
445 when Hashtbl.mem defs s ->
708f4980
C
446
447 msg_apply_known_macro s;
448 let (_s, params, body) = Hashtbl.find defs s in
449
450 (match params with
abad11c5 451 | Params _ ->
708f4980
C
452 pr2 ("WEIRD: macro with params but no parens found: " ^ s);
453 (* dont apply the macro, perhaps a redefinition *)
454 ()
ae4735db 455 | NoParam ->
708f4980 456 (match body with
978fd7e5
C
457 (* bugfix: we prefer not using this special case when we come
458 * from extract_macros context
459 *)
ae4735db 460 | DefineBody [newtok] when inplace_when_single ->
708f4980 461 (* special case when 1-1 substitution, we reuse the token *)
ae4735db 462 id.tok <- (newtok +> TH.visitor_info_of_tok (fun _ ->
708f4980 463 TH.info_of_tok id.tok))
ae4735db 464 | DefineBody bodymacro ->
708f4980
C
465 set_as_comment Token_c.CppMacro id;
466 id.new_tokens_before <- bodymacro;
ae4735db 467 | DefineHint hint ->
708f4980
C
468 msg_apply_known_macro_hint s;
469 id.tok <- token_from_parsinghack_hint (s,i1) hint;
470 )
471 );
472 apply_macro_defs xs
473
474
475
476
477 (* recurse *)
ae4735db
C
478 | (PToken x)::xs -> apply_macro_defs xs
479 | (Parenthised (xxs, info_parens))::xs ->
708f4980
C
480 xxs +> List.iter apply_macro_defs;
481 apply_macro_defs xs
482 in
483 apply_macro_defs xs
484
485
486
708f4980 487(*****************************************************************************)
978fd7e5 488(* extracting define_def from a standard.h *)
708f4980 489(*****************************************************************************)
978fd7e5 490(* was the cpp-builtin, standard.h, part 0 *)
708f4980 491
ae4735db 492let macro_body_to_maybe_hint body =
708f4980
C
493 match body with
494 | [] -> DefineBody body
ae4735db 495 | [TIdent (s,i1)] ->
708f4980
C
496 (match parsinghack_hint_of_string s with
497 | Some hint -> DefineHint hint
498 | None -> DefineBody body
499 )
500 | xs -> DefineBody body
501
5636bb2c 502exception Bad_param
708f4980 503
ae4735db 504let rec (define_parse: Parser_c.token list -> (string * define_def) list) =
978fd7e5 505 fun xs ->
708f4980
C
506 match xs with
507 | [] -> []
ae4735db 508 | TDefine i1::TIdentDefine (s,i2)::TOParDefine i3::xs ->
708f4980
C
509 (* note: the macro could be badly written and have no closing ')' for
510 * its param, which would make us go too far away, but I don't think
511 * it's important to handle such an error *)
5636bb2c
C
512 let def =
513 try
514 let (tokparams, _, xs) =
515 xs +> Common.split_when (function TCPar _ -> true | _ -> false) in
516 let (body, _, xs) =
517 xs +> Common.split_when (function TDefEOL _ -> true | _ -> false) in
518 let params =
519 tokparams +> Common.map_filter (function
abad11c5
C
520 | TComma _ -> None
521 | TIdent (s, _) -> Some (FixedArg s)
5636bb2c
C
522
523 (* TODO *)
abad11c5 524 | TDefParamVariadic (s, _) -> Some (VariadicArg s)
5636bb2c 525 (* TODO *)
abad11c5 526 | TEllipsis _ -> Some (VariadicArg "...")
5636bb2c 527
abad11c5 528 | x ->
5636bb2c 529 (* bugfix: param of macros can be tricky *)
abad11c5
C
530 let s = TH.str_of_tok x in
531 if s ==~ Common.regexp_alpha
532 then begin
533 pr2 (spf "remapping: %s to a macro parameter" s);
534 Some (FixedArg s)
535 end
536 else
537 begin
538 pr2 (spf "bad character %s in macro parameter list" s);
539 raise Bad_param
540 end) in
5636bb2c 541 (* bugfix: also substitute to ident in body so cpp_engine will
abad11c5
C
542 * have an easy job.
543 *)
5636bb2c
C
544 let body = body +> List.map (fun tok ->
545 match tok with
546 | TIdent _ -> tok
547 | _ ->
548 let s = TH.str_of_tok tok in
549 let ii = TH.info_of_tok tok in
abad11c5
C
550 let params =
551 List.map
552 (function FixedArg s -> s | VariadicArg s -> s)
553 params in
5636bb2c
C
554 if s ==~ Common.regexp_alpha && List.mem s params
555 then begin
556 pr2 (spf "remapping: %s to an ident in macro body" s);
557 TIdent (s, ii)
558 end
559 else tok) +>
560 List.map (TH.visitor_info_of_tok Ast_c.make_expanded) in
561 Some (s, (s, Params params, macro_body_to_maybe_hint body))
562 with Bad_param -> None in
563 (match def with
564 Some def -> def::define_parse xs
565 | None -> define_parse xs)
708f4980 566
ae4735db
C
567 | TDefine i1::TIdentDefine (s,i2)::xs ->
568 let (body, _, xs) =
708f4980 569 xs +> Common.split_when (function TDefEOL _ -> true | _ -> false) in
ae4735db 570 let body = body +> List.map
708f4980
C
571 (TH.visitor_info_of_tok Ast_c.make_expanded) in
572 let def = (s, (s, NoParam, macro_body_to_maybe_hint body)) in
573 def::define_parse xs
574
575 (* cf tests-bis/define_plus.c *)
ae4735db 576 | TDefine i1::xs ->
708f4980
C
577 let line = Ast_c.line_of_info i1 in
578 pr2 (spf "WEIRD: no ident in define at line %d" line);
579 define_parse xs
ae4735db
C
580
581 | x::xs -> define_parse xs
582
708f4980
C
583
584
ae4735db
C
585let extract_macros xs =
586 let cleaner = xs +> List.filter (fun x ->
708f4980
C
587 not (TH.is_comment x)
588 ) in
589 define_parse cleaner
708f4980
C
590
591