~ubuntu-branches/ubuntu/karmic/coccinelle/karmic

« back to all changes in this revision

Viewing changes to parsing_c/unparse_c.ml

  • Committer: Bazaar Package Importer
  • Author(s): Євгеній Мещеряков
  • Date: 2009-05-11 15:32:24 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090511153224-1odv41d4dkr3y80v
Tags: 0.1.8.deb-2
Use common install Makefile target for both native and bytecode
build. This hopefully fixes FTBFS on bytecode archs 

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
 
30
30
(*****************************************************************************)
 
31
(* Wrappers *)
 
32
(*****************************************************************************)
 
33
let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_unparsing
 
34
 
 
35
(*****************************************************************************)
31
36
(* Types used during the intermediate phases of the unparsing *)
32
37
(*****************************************************************************)
33
38
 
44
49
 * This type contains the whole information. Have all the tokens with this
45
50
 * type.
46
51
 *)
 
52
type min =
 
53
    Min of (int list (* match numbers *) * int (* adjacency information *))
 
54
  | Ctx
 
55
 
47
56
type token2 = 
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 *)
50
59
  | Fake2
51
 
  | Cocci2 of string
 
60
  | Cocci2 of string * int (* line *) * int (* lcol *) * int (* rcol *)
52
61
  | C2 of string
53
62
  | Indent_cocci2
54
63
  | Unindent_cocci2
82
91
let str_of_token2 = function
83
92
  | T2 (t,_,_) -> TH.str_of_tok t
84
93
  | Fake2 -> ""
85
 
  | Cocci2 s -> s
 
94
  | Cocci2 (s,_,_,_) -> s
86
95
  | C2 s -> s
87
96
  | Indent_cocci2 -> ""
88
97
  | Unindent_cocci2 -> ""
89
98
 
90
99
let print_token2 = function
91
 
  | T2 (t,b,_) -> "T2:"^(if b then "-" else "")^TH.str_of_tok t
 
100
  | T2 (t,b,_) ->
 
101
      let b_str =
 
102
        match b with
 
103
          Min (index,adj) ->
 
104
            Printf.sprintf "-%d[%s]" adj
 
105
              (String.concat " " (List.map string_of_int index))
 
106
        | Ctx -> "" in
 
107
      "T2:"^b_str^TH.str_of_tok t
92
108
  | Fake2 -> ""
93
 
  | Cocci2 s -> "Cocci2:"^s
 
109
  | Cocci2 (s,_,lc,rc) -> Printf.sprintf "Cocci2:%d:%d%s" lc rc s
94
110
  | C2 s -> "C2:"^s
95
111
  | Indent_cocci2 -> "Indent"
96
112
  | Unindent_cocci2 -> "Unindent"
97
113
 
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"
101
117
 
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
138
154
 
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
 
261
        | Some x -> 
 
262
          (match x 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
259
277
            failwith "fake node should not be before-after"
260
278
        | _ -> bef @ fake :: (loop aft) (* old: was removed when have simpler yacfe *)
261
279
        )
 
280
        | None -> 
 
281
            bef @ fake :: (loop aft)
 
282
        )
262
283
    | None -> toks
263
284
    | _ -> raise Impossible in
264
285
  loop toks
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))
274
295
 
275
296
let expand_mcode toks = 
276
297
  let toks_out = ref [] in
315
336
  in
316
337
 
317
338
  let expand_info t = 
318
 
    let (mcode,env) = !((info_of_token1 t).cocci_tag) in
 
339
    let (mcode,env) = 
 
340
      Ast_c.mcode_and_env_of_cocciref ((info_of_token1 t).cocci_tag) in
319
341
 
320
 
    let pr_cocci s = 
321
 
      push2 (Cocci2 s) toks_out 
322
 
    in
 
342
    let pr_cocci s ln col rcol = 
 
343
      push2 (Cocci2(s,ln,col,rcol)) toks_out  in
323
344
    let pr_c info = 
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
334
355
 
335
 
 
336
 
 
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 *)
 
359
 
 
360
    let pr_cspace _ = push2 (C2 " ") toks_out in
 
361
 
 
362
    let pr_space _ = () (* rely on add_space in cocci code *) in
 
363
    let pr_arity _ = () (* not interested *) in
338
364
 
339
365
    let indent _   = push2 Indent_cocci2 toks_out in
340
366
    let unindent _ = push2 Unindent_cocci2 toks_out in
341
367
 
342
 
    let args_pp = (env, pr_cocci, pr_c, pr_space, indent, unindent) in
 
368
    let args_pp =
 
369
      (env, pr_cocci, pr_c, pr_cspace,
 
370
       (match !Flag_parsing_c.spacing with
 
371
         Flag_parsing_c.SMPL -> pr_space | _ -> pr_cspace),
 
372
       pr_arity,
 
373
       (match !Flag_parsing_c.spacing with
 
374
         Flag_parsing_c.SMPL -> pr_barrier | _ -> pr_nobarrier),
 
375
       indent, unindent) in
343
376
 
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
350
383
    match mcode with
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 *)
355
 
        add_elem t true;
 
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 -> 
360
 
            add_elem t false
 
393
            add_elem t Ctx
361
394
        | Ast_cocci.BEFORE xxs -> 
362
395
            unparser xxs Unparse_cocci.Before;
363
 
            add_elem t false
 
396
            add_elem t Ctx
364
397
        | Ast_cocci.AFTER xxs -> 
365
 
            add_elem t false;
 
398
            add_elem t Ctx;
366
399
            unparser xxs Unparse_cocci.After;
367
400
        | Ast_cocci.BEFOREAFTER (xxs, yys) -> 
368
401
            unparser xxs Unparse_cocci.Before;
369
 
            add_elem t false;
 
402
            add_elem t Ctx;
370
403
            unparser yys Unparse_cocci.After;
371
404
        )
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
410
443
 
411
 
let set_minus_comment = function
412
 
  | T2 (t,false,idx) -> 
 
444
let set_minus_comment adj = function
 
445
  | T2 (t,Ctx,idx) -> 
413
446
      let str = TH.str_of_tok t in
414
447
      (match t with
415
448
      | Parser_c.TCommentSpace _
425
458
                 (TH.line_of_tok t) str)
426
459
      | _ -> raise Impossible
427
460
      );
428
 
      T2 (t, true, idx)
 
461
      T2 (t, Min adj, idx)
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
432
465
 
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
436
469
 
437
470
let remove_minus_and_between_and_expanded_and_fake xs =
438
471
 
447
480
 
448
481
  (*This drops the space before each completely minused block (no plus code).*)
449
482
  let minus_or_comment = function
450
 
      T2(_,true,_) -> true
 
483
      T2(_,Min adj,_) -> true
451
484
    | T2(Parser_c.TCommentNewline _,_b,_i) -> false
452
485
    | x -> is_minusable_comment x in
453
486
 
454
487
  let rec adjust_before_minus = function
455
488
      [] -> []
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
459
493
        (match rest with
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
471
505
      [] -> []
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)@
491
525
         last_newline@
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 *)
 
536
 
 
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
 
541
 
502
542
  let rec adjust_between_minus xs =
503
543
    match xs with
504
544
    | [] -> []
505
 
    | (T2 (t1,true,idx1))::xs -> 
506
 
 
 
545
    | ((T2 (_,Min adj1,_)) as t1)::xs ->
507
546
        let (between_comments, rest) =
508
547
          Common.span is_minusable_comment_or_plus xs in
509
548
        (match rest with
510
 
        | [] -> [(T2 (t1, true,idx1))]
 
549
        | [] -> [t1]
511
550
 
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 ->
 
552
            t1::
 
553
            (List.map (set_minus_comment_or_plus adj1) between_comments @
 
554
             adjust_between_minus (t2::rest))
516
555
        | x::xs ->
517
 
            (T2 (t1, true, idx1))::
518
 
            (between_comments @ adjust_between_minus (x::xs))
 
556
            t1::(between_comments @ adjust_between_minus (x::xs))
519
557
        )
520
558
 
521
559
    | x::xs -> x::adjust_between_minus xs in
523
561
  let xs = adjust_between_minus xs in
524
562
 
525
563
  let xs = xs +> Common.exclude (function
526
 
    | T2 (t,true,_) -> true
 
564
    | T2 (t,Min adj,_) -> true
527
565
    | _ -> false
528
566
  ) in
529
567
  xs
533
571
  let toks = List.rev toks in
534
572
  let rec loop = function
535
573
      [] -> []
536
 
    | ((T2(_,false,_)) as x)::xs ->
 
574
    | ((T2(_,Ctx,_)) as x)::xs ->
537
575
        if List.mem (str_of_token2 x) [";";")";","]
538
576
        then
539
577
          let (spaces, rest) = Common.span is_minusable_comment xs in
540
578
          (match rest with
541
 
            (T2(_,true,_))::_ | (Cocci2 _)::_ ->
 
579
            (T2(_,Min _,_))::_ | (Cocci2 _)::_ ->
542
580
              (* only drop spaces if something was actually changed before *)
543
581
              x :: loop rest
544
582
          | _ -> x :: loop xs)
552
590
  match xs with
553
591
  | [] -> []
554
592
  | [x] -> [x]
 
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)
555
600
  | x::y::xs -> 
556
601
      let sx = str_of_token2 x in
557
602
      let sy = str_of_token2 y in
628
673
    | [] ->  []
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
648
694
        | Some (tu,_) ->
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);
656
702
            aux started xs)
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
672
718
  aux false xs
673
719