30
30
(*****************************************************************************)
32
(*****************************************************************************)
33
let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_unparsing
35
(*****************************************************************************)
31
36
(* Types used during the intermediate phases of the unparsing *)
32
37
(*****************************************************************************)
44
49
* This type contains the whole information. Have all the tokens with this
53
Min of (int list (* match numbers *) * int (* adjacency information *))
48
| T2 of Parser_c.token * bool (* minus *) *
57
| T2 of Parser_c.token * min *
49
58
int option (* orig index, abstracting away comments and space *)
60
| Cocci2 of string * int (* line *) * int (* lcol *) * int (* rcol *)
82
91
let str_of_token2 = function
83
92
| T2 (t,_,_) -> TH.str_of_tok t
94
| Cocci2 (s,_,_,_) -> s
87
96
| Indent_cocci2 -> ""
88
97
| Unindent_cocci2 -> ""
90
99
let print_token2 = function
91
| T2 (t,b,_) -> "T2:"^(if b then "-" else "")^TH.str_of_tok t
104
Printf.sprintf "-%d[%s]" adj
105
(String.concat " " (List.map string_of_int index))
107
"T2:"^b_str^TH.str_of_tok t
93
| Cocci2 s -> "Cocci2:"^s
109
| Cocci2 (s,_,lc,rc) -> Printf.sprintf "Cocci2:%d:%d%s" lc rc s
95
111
| Indent_cocci2 -> "Indent"
96
112
| Unindent_cocci2 -> "Unindent"
98
let print_all_tokens2 l =
114
let simple_print_all_tokens2 l =
99
115
List.iter (function x -> Printf.printf "%s " (print_token2 x)) l;
100
116
Printf.printf "\n"
132
148
| Ast_cocci.CONTEXT (_,Ast_cocci.NOTHING) -> false
133
149
| Ast_cocci.CONTEXT _ -> true
134
150
(* patch: when need full coccinelle transformation *)
135
| Ast_cocci.MINUS (_,[]) -> false
136
| Ast_cocci.MINUS (_,x::xs) -> true
151
| Ast_cocci.MINUS (_,_,_,[]) -> false
152
| Ast_cocci.MINUS (_,_,_,x::xs) -> true
137
153
| Ast_cocci.PLUS -> raise Impossible
139
155
let contain_plus info =
242
258
match fake_info with
243
259
Some(bef,((Fake1 info) as fake),aft) ->
244
260
(match !(info.cocci_tag) with
245
263
(Ast_cocci.CONTEXT(_,Ast_cocci.BEFORE _),_) ->
246
264
(* move the fake node forwards *)
247
265
let (whitespace,rest) = Common.span is_whitespace aft in
270
291
let comment2t2 = function
271
292
(Token_c.TCommentCpp x,(info : Token_c.info)) ->
272
293
C2("\n"^info.Common.str^"\n")
273
| x -> failwith (Printf.sprintf "unexpected comment %s" (Dumper.dump x))
294
| x -> failwith (Printf.sprintf "unexpected comment %s" (Common.dump x))
275
296
let expand_mcode toks =
276
297
let toks_out = ref [] in
317
338
let expand_info t =
318
let (mcode,env) = !((info_of_token1 t).cocci_tag) in
340
Ast_c.mcode_and_env_of_cocciref ((info_of_token1 t).cocci_tag) in
321
push2 (Cocci2 s) toks_out
342
let pr_cocci s ln col rcol =
343
push2 (Cocci2(s,ln,col,rcol)) toks_out in
324
345
(match Ast_c.pinfo_of_info info with
325
346
Ast_c.AbstractLineTok _ ->
332
353
(!(info.Ast_c.comments_tag)).Ast_c.mafter +>
333
354
List.iter (fun x -> Common.push2 (comment2t2 x) toks_out) in
337
let pr_space _ = push2 (C2 " ") toks_out in
356
let pr_barrier ln col = (* marks a position, used around C code *)
357
push2 (Cocci2("",ln,col,col)) toks_out in
358
let pr_nobarrier ln col = () in (* not needed for linux spacing *)
360
let pr_cspace _ = push2 (C2 " ") toks_out in
362
let pr_space _ = () (* rely on add_space in cocci code *) in
363
let pr_arity _ = () (* not interested *) in
339
365
let indent _ = push2 Indent_cocci2 toks_out in
340
366
let unindent _ = push2 Unindent_cocci2 toks_out in
342
let args_pp = (env, pr_cocci, pr_c, pr_space, indent, unindent) in
369
(env, pr_cocci, pr_c, pr_cspace,
370
(match !Flag_parsing_c.spacing with
371
Flag_parsing_c.SMPL -> pr_space | _ -> pr_cspace),
373
(match !Flag_parsing_c.spacing with
374
Flag_parsing_c.SMPL -> pr_barrier | _ -> pr_nobarrier),
344
377
(* old: when for yacfe with partial cocci:
345
378
* add_elem t false;
348
381
(* patch: when need full coccinelle transformation *)
349
382
let unparser = Unparse_cocci.pp_list_list_any args_pp false in
351
| Ast_cocci.MINUS (_,any_xxs) ->
384
| Ast_cocci.MINUS (_,inst,adj,any_xxs) ->
352
385
(* Why adding ? because I want to have all the information, the whole
353
386
* set of tokens, so I can then process and remove the
354
387
* is_between_two_minus for instance *)
388
add_elem t (Min (inst,adj));
356
389
unparser any_xxs Unparse_cocci.InPlace
357
390
| Ast_cocci.CONTEXT (_,any_befaft) ->
358
391
(match any_befaft with
359
392
| Ast_cocci.NOTHING ->
361
394
| Ast_cocci.BEFORE xxs ->
362
395
unparser xxs Unparse_cocci.Before;
364
397
| Ast_cocci.AFTER xxs ->
366
399
unparser xxs Unparse_cocci.After;
367
400
| Ast_cocci.BEFOREAFTER (xxs, yys) ->
368
401
unparser xxs Unparse_cocci.Before;
370
403
unparser yys Unparse_cocci.After;
372
405
| Ast_cocci.PLUS -> raise Impossible
408
441
(*previously gave up if the first character was a newline, but not clear why*)
409
442
let is_minusable_comment_or_plus x = is_minusable_comment x or all_coccis x
411
let set_minus_comment = function
412
| T2 (t,false,idx) ->
444
let set_minus_comment adj = function
413
446
let str = TH.str_of_tok t in
415
448
| Parser_c.TCommentSpace _
425
458
(TH.line_of_tok t) str)
426
459
| _ -> raise Impossible
429
462
(* patch: coccinelle *)
430
| T2 (Parser_c.TCommentNewline _,true,idx) as x -> x
463
| T2 (Parser_c.TCommentNewline _,Min adj,idx) as x -> x
431
464
| _ -> raise Impossible
433
let set_minus_comment_or_plus = function
466
let set_minus_comment_or_plus adj = function
434
467
Cocci2 _ | C2 _ | Indent_cocci2 | Unindent_cocci2 as x -> x
435
| x -> set_minus_comment x
468
| x -> set_minus_comment adj x
437
470
let remove_minus_and_between_and_expanded_and_fake xs =
448
481
(*This drops the space before each completely minused block (no plus code).*)
449
482
let minus_or_comment = function
483
T2(_,Min adj,_) -> true
451
484
| T2(Parser_c.TCommentNewline _,_b,_i) -> false
452
485
| x -> is_minusable_comment x in
454
487
let rec adjust_before_minus = function
456
489
(* patch: coccinelle *)
457
| (T2(Parser_c.TCommentNewline c,_b,_i) as x)::((T2(_,true,_)::_) as xs) ->
490
| (T2(Parser_c.TCommentNewline c,_b,_i) as x)::
491
((T2(_,Min adj,_)::_) as xs) ->
458
492
let (between_minus,rest) = Common.span minus_or_comment xs in
460
[] -> (set_minus_comment x) :: between_minus
494
[] -> (set_minus_comment adj x) :: between_minus
461
495
| T2(Parser_c.TCommentNewline _,_b,_i)::_ ->
462
(set_minus_comment x) :: between_minus @
496
(set_minus_comment adj x) :: between_minus @
463
497
(adjust_before_minus rest)
464
498
| _ -> x :: between_minus @ (adjust_before_minus rest))
465
499
| x::xs -> x::adjust_before_minus xs in
469
503
(* this drops blank lines after a brace introduced by removing code *)
470
504
let rec adjust_after_brace = function
472
| ((T2(_,false,_)) as x)::((T2(_,true,_)::_) as xs)
506
| ((T2(_,Ctx,_)) as x)::((T2(_,Min adj,_)::_) as xs)
473
507
when str_of_token2 x =$= "{" ->
474
508
let (between_minus,rest) = Common.span minus_or_comment xs in
475
509
let is_whitespace = function
487
521
let (drop_newlines,last_newline) = loop xs in
488
522
(drop_newlines,x::last_newline) in
489
523
loop (List.rev newlines) in
490
x::between_minus@(List.map set_minus_comment drop_newlines)@
524
x::between_minus@(List.map (set_minus_comment adj) drop_newlines)@
492
526
adjust_after_brace rest
493
527
| x::xs -> x::adjust_after_brace xs in
499
533
(* The use of is_minusable_comment_or_plus and set_minus_comment_or_plus
500
534
is because the + code can end up anywhere in the middle of the - code;
501
535
it is not necessarily to the far left *)
537
let common_adj (index1,adj1) (index2,adj2) =
538
adj1 = adj2 (* same adjacency info *) &&
539
(* non-empty intersection of witness trees *)
540
not ((Common.inter_set index1 index2) = []) in
502
542
let rec adjust_between_minus xs =
505
| (T2 (t1,true,idx1))::xs ->
545
| ((T2 (_,Min adj1,_)) as t1)::xs ->
507
546
let (between_comments, rest) =
508
547
Common.span is_minusable_comment_or_plus xs in
510
| [] -> [(T2 (t1, true,idx1))]
512
| (T2 (t2, true,idx2))::rest ->
513
(T2 (t1, true,idx1))::
514
(List.map set_minus_comment_or_plus between_comments @
515
adjust_between_minus ((T2 (t2, true, idx2))::rest))
551
| ((T2 (_,Min adj2,_)) as t2)::rest when common_adj adj1 adj2 ->
553
(List.map (set_minus_comment_or_plus adj1) between_comments @
554
adjust_between_minus (t2::rest))
517
(T2 (t1, true, idx1))::
518
(between_comments @ adjust_between_minus (x::xs))
556
t1::(between_comments @ adjust_between_minus (x::xs))
521
559
| x::xs -> x::adjust_between_minus xs in
533
571
let toks = List.rev toks in
534
572
let rec loop = function
536
| ((T2(_,false,_)) as x)::xs ->
574
| ((T2(_,Ctx,_)) as x)::xs ->
537
575
if List.mem (str_of_token2 x) [";";")";","]
539
577
let (spaces, rest) = Common.span is_minusable_comment xs in
541
(T2(_,true,_))::_ | (Cocci2 _)::_ ->
579
(T2(_,Min _,_))::_ | (Cocci2 _)::_ ->
542
580
(* only drop spaces if something was actually changed before *)
544
582
| _ -> x :: loop xs)
593
| (Cocci2(sx,lnx,_,rcolx) as x)::((Cocci2(sy,lny,lcoly,_)) as y)::xs
594
when !Flag_parsing_c.spacing = Flag_parsing_c.SMPL &&
595
not (lnx = -1) && lnx = lny && not (rcolx = -1) && rcolx < lcoly ->
596
(* this only works within a line. could consider whether
597
something should be done to add newlines too, rather than
598
printing them explicitly in unparse_cocci. *)
599
x::C2 (String.make (lcoly-rcolx) ' ')::add_space (y::xs)
556
601
let sx = str_of_token2 x in
557
602
let sy = str_of_token2 y in
629
674
(* patch: coccinelle *)
630
675
| ((T2 (tok,_,_)) as x)::(T2 (Parser_c.TCommentNewline s, _, _))::
631
(Cocci2 "{")::xs when started && str_of_token2 x =$= ")" ->
676
((Cocci2 ("{",_,_,_)) as a)::xs
677
when started && str_of_token2 x =$= ")" ->
632
678
(* to be done for if, etc, but not for a function header *)
633
x::(Cocci2 " {")::(aux started xs)
679
x::(C2 " ")::a::(aux started xs)
634
680
| ((T2 (Parser_c.TCommentNewline s, _, _)) as x)::xs ->
635
681
let old_tabbing = !_current_tabbing in
636
682
str_of_token2 x +> new_tabbing +> (fun s -> _current_tabbing := s);
647
693
None -> aux started xs
649
695
_current_tabbing := (!_current_tabbing)^tu;
650
Cocci2 (tu)::aux started xs)
696
Cocci2 (tu,-1,-1,-1)::aux started xs)
651
697
| Unindent_cocci2::xs ->
652
698
(match !tabbing_unit with
653
699
None -> aux started xs
655
701
_current_tabbing := remtab tu (!_current_tabbing);
657
703
(* border between existing code and cocci code *)
658
| ((T2 (tok,_,_)) as x)::((Cocci2 "\n") as y)::xs
704
| ((T2 (tok,_,_)) as x)::((Cocci2("\n",_,_,_)) as y)::xs
659
705
when str_of_token2 x =$= "{" ->
660
706
x::aux true (y::Indent_cocci2::xs)
661
707
| ((Cocci2 _) as x)::((T2 (tok,_,_)) as y)::xs
663
709
x::aux started (y::Unindent_cocci2::xs)
664
710
(* starting the body of the function *)
665
711
| ((T2 (tok,_,_)) as x)::xs when str_of_token2 x =$= "{" -> x::aux true xs
666
| (Cocci2 "{")::xs -> (Cocci2 "{")::aux true xs
667
| ((Cocci2 "\n") as x)::xs ->
712
| ((Cocci2("{",_,_,_)) as a)::xs -> a::aux true xs
713
| ((Cocci2("\n",_,_,_)) as x)::xs ->
668
714
(* dont inline in expr because of weird eval order of ocaml *)
669
715
let s = !_current_tabbing in
670
x::Cocci2 (s)::aux started xs
716
x::Cocci2 (s,-1,-1,-1)::aux started xs
671
717
| x::xs -> x::aux started xs in