File: parse_printf.ml

package info (click to toggle)
coccinelle 1.0.8.deb-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 26,148 kB
  • sloc: ml: 136,392; ansic: 23,594; sh: 2,189; makefile: 2,157; perl: 1,576; lisp: 840; python: 823; awk: 70; csh: 12
file content (109 lines) | stat: -rw-r--r-- 3,176 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
(*
 * This file is part of Coccinelle, licensed under the terms of the GPL v2.
 * See copyright.txt in the Coccinelle source code for more information.
 * The Coccinelle source code can be obtained at http://coccinelle.lip6.fr
 *)

(* %[parameter][flags][width][.precision][length]type *)

exception Not_format_string

let suffix s n = String.sub s n (String.length s - n)

let string_of_char c = Printf.sprintf "%c" c

let safe_get s n = try String.get s n with _ -> raise Not_format_string

let check_parameter s =
  match Str.split (Str.regexp_string "$") s with
    a::rest ->
      (try
	let _ = int_of_string a in
	(Some a, String.concat "$" rest)
      with Failure _(*"int_of_string"*) -> (None, s))
  | _ -> (None, s)

let check_flags s =
  let c1 = safe_get s 0 in
  match c1 with
    '+' | ' ' | '-' | '#' | '0' -> (Some (string_of_char c1), suffix s 1)
  | _ -> (None, s)

let check_width s =
  if safe_get s 0 = '*'
  then (Some "*", suffix s 1)
  else
    let re = Str.regexp "[0-9]+" in
    if Str.string_match re s 0
    then
      let front = Str.matched_string s in
      let front_len = String.length front in
      (Some front, suffix s front_len)
    else (None, s)

let check_precision s =
  match safe_get s 0 with
    '.' ->
      let s1 = suffix s 1 in
      (match check_width s1 with
	(Some n, s) -> (Some ("."^n), s)
      |	(None, s) -> raise Not_format_string)
  | _ -> (None, s)

(* PRI macros not supported *)
let check_length s =
  let c1 = safe_get s 0 in
  match c1 with
    'h' ->
      let s1 = suffix s 1 in
      let c2 = safe_get s1 0 in
      (match c2 with
	'h' -> (Some "hh", suffix s1 1)
      |	_ -> (Some "h", s1))
  | 'l' ->
      let s1 = suffix s 1 in
      let c2 = safe_get s1 0 in
      (match c2 with
	'l' -> (Some "ll", suffix s1 1)
      |	_ -> (Some "l", s1))
  | 'L' | 'z' | 'j' | 't' -> (Some (string_of_char c1), suffix s 1)
  | 'I' ->
      let s1 = suffix s 1 in
      if Str.string_match (Str.regexp "32") s1 0 ||
	Str.string_match (Str.regexp "64") s1 0
      then (Some ("I"^Str.matched_string s1), suffix s1 2)
      else (Some "I", suffix s 1)
  | 'q' (* BSD *) -> (Some "q", suffix s 1)
  | _ -> (None, s)

let check_type s =
  let c1 = safe_get s 0 in
  match c1 with
    'd' | 'i' | 'u' | 'f' | 'F' | 'e' | 'E' | 'g' | 'G' | 'x' | 'X' |
    'o' | 's' | 'c' | 'p' | 'a' | 'A' | 'n' -> (string_of_char c1, suffix s 1)
  | 'D' when !Flag.ibm ->
      (match safe_get s 1 with
	'(' ->
	  (try
	    let final = Str.search_forward (Str.regexp_string ")") s 2 in
	    let len = final + 1 in
	    (String.sub s 0 len, suffix s len)
	  with _ -> raise Not_format_string)
      |	_ -> raise Not_format_string)
  | _ -> raise Not_format_string

(* perhaps useful for ocaml scripts *)
let get_all_pieces s =
  let (p,s) = check_parameter s in
  let (f,s) = check_flags s in
  let (w,s) = check_width s in
  let (pr,s) = check_precision s in
  let (l,s) = check_length s in
  let (t,s) = check_type s in
  (p,f,w,pr,l,t,s)

let unsome = function Some s -> s | None -> ""

let get_format_string s =
  let (p,f,w,pr,l,t,s) = get_all_pieces s in
  (((unsome p) ^ (unsome f) ^ (unsome w) ^ (unsome pr) ^ (unsome l) ^ t), s)