diff options
| author | Pascal Rigaux <pixel@mandriva.com> | 2002-12-10 01:50:05 +0000 | 
|---|---|---|
| committer | Pascal Rigaux <pixel@mandriva.com> | 2002-12-10 01:50:05 +0000 | 
| commit | 637ce17cdab0061cb2e20e12674cf5a0c9c6ddea (patch) | |
| tree | 73451af85f95037c3ba8962970a7fe1a6e9e5f1e | |
| parent | 4a1099012a04e35b54a5e067294fecddaa3d4cf7 (diff) | |
| download | perl_checker-637ce17cdab0061cb2e20e12674cf5a0c9c6ddea.tar perl_checker-637ce17cdab0061cb2e20e12674cf5a0c9c6ddea.tar.gz perl_checker-637ce17cdab0061cb2e20e12674cf5a0c9c6ddea.tar.bz2 perl_checker-637ce17cdab0061cb2e20e12674cf5a0c9c6ddea.tar.xz perl_checker-637ce17cdab0061cb2e20e12674cf5a0c9c6ddea.zip | |
perl_checker: new --generate-pot feature
| -rw-r--r-- | perl_checker.src/common.ml | 9 | ||||
| -rw-r--r-- | perl_checker.src/common.mli | 1 | ||||
| -rw-r--r-- | perl_checker.src/flags.ml | 3 | ||||
| -rw-r--r-- | perl_checker.src/flags.mli | 2 | ||||
| -rw-r--r-- | perl_checker.src/lexer.mll | 21 | ||||
| -rw-r--r-- | perl_checker.src/parser.mly | 4 | ||||
| -rw-r--r-- | perl_checker.src/parser_helper.ml | 41 | ||||
| -rw-r--r-- | perl_checker.src/parser_helper.mli | 5 | ||||
| -rw-r--r-- | perl_checker.src/perl_checker.ml | 16 | 
9 files changed, 91 insertions, 11 deletions
| diff --git a/perl_checker.src/common.ml b/perl_checker.src/common.ml index a938ffb..f84e027 100644 --- a/perl_checker.src/common.ml +++ b/perl_checker.src/common.ml @@ -692,6 +692,15 @@ let rec explode_string = function    | "" -> []    | s -> (String.get s 0) :: explode_string (String.sub s 1 (String.length s - 1)) +let count_matching_char s c = +  let rec count_matching_char_ nb i = +    try +      let i' = String.index_from s i c in +      count_matching_char_ (nb+1) (i'+1) +    with Not_found -> nb +  in +  count_matching_char_ 0 0 +  let is_uppercase c = Char.lowercase c <> c  let is_lowercase c = Char.uppercase c <> c diff --git a/perl_checker.src/common.mli b/perl_checker.src/common.mli index 162b6bd..f3a66c7 100644 --- a/perl_checker.src/common.mli +++ b/perl_checker.src/common.mli @@ -187,6 +187,7 @@ val non_index : string -> char -> int  val non_rindex_from : string -> int -> char -> int  val non_rindex : string -> char -> int  val explode_string : string -> char list +val count_matching_char : string -> char -> int  val is_uppercase : char -> bool  val is_lowercase : char -> bool  val char_is_alphanumerical : char -> bool diff --git a/perl_checker.src/flags.ml b/perl_checker.src/flags.ml index 5256831..6f0949b 100644 --- a/perl_checker.src/flags.ml +++ b/perl_checker.src/flags.ml @@ -2,3 +2,6 @@ open Common  let verbose = ref false  let quiet = ref false +let generate_pot = ref false +let expand_tabs = ref false + diff --git a/perl_checker.src/flags.mli b/perl_checker.src/flags.mli index 9f17f55..81045b1 100644 --- a/perl_checker.src/flags.mli +++ b/perl_checker.src/flags.mli @@ -1,2 +1,4 @@  val verbose : bool ref  val quiet : bool ref +val generate_pot : bool ref +val expand_tabs : bool ref diff --git a/perl_checker.src/lexer.mll b/perl_checker.src/lexer.mll index 448d0c9..c9ce890 100644 --- a/perl_checker.src/lexer.mll +++ b/perl_checker.src/lexer.mll @@ -20,6 +20,7 @@ type raw_token =    | BAREWORD_PAREN of (string * raw_pos)    | REVISION of (string * raw_pos)    | PERL_CHECKER_COMMENT of (string * raw_pos) +  | PO_COMMENT of (string * raw_pos)    | POD of (string * raw_pos)    | LABEL of (string * raw_pos)    | COMMAND_STRING of (raw_interpolated_string * raw_pos) @@ -75,6 +76,7 @@ let rec raw_token_to_pos_and_token spaces = function    | BAREWORD_PAREN(s, pos) -> pos, Parser.BAREWORD_PAREN(s, (spaces, pos))    | REVISION(s, pos) -> pos, Parser.REVISION(s, (spaces, pos))    | PERL_CHECKER_COMMENT(s, pos) -> pos, Parser.PERL_CHECKER_COMMENT(s, (spaces, pos)) +  | PO_COMMENT(s, pos) -> pos, Parser.PO_COMMENT(s, (spaces, pos))    | POD(s, pos) -> pos, Parser.POD(s, (spaces, pos))    | LABEL(s, pos) -> pos, Parser.LABEL(s, (spaces, pos))    | PRINT(s, pos) -> pos, Parser.PRINT(s, (spaces, pos)) @@ -327,12 +329,13 @@ let ident = ident_start ['0'-'9' 'A'-'Z' 'a'-'z' '_'] *  let pattern_separator = [ '/' '!' ',' '|' ]  rule token = parse -| ' '+ {  +| [' ' '\t']+ {       (* propagate not_ok_for_match when it was set by the previous token *)      if lexeme_start lexbuf = !not_ok_for_match then not_ok_for_match := lexeme_end lexbuf;       SPACE(lexeme_end lexbuf - lexeme_start lexbuf)    }  | "# perl_checker: " [^ '\n']* { PERL_CHECKER_COMMENT(skip_n_char 16 (lexeme lexbuf), pos lexbuf) } +| "#-PO: " [^ '\n']* { PO_COMMENT(skip_n_char 1 (lexeme lexbuf), pos lexbuf) }  | '#' [^ '\n']* { SPACE(1) }  | "\n=" {  @@ -623,7 +626,6 @@ and string = parse      add_a_new_line(lexeme_end lexbuf);      next string lexbuf    } -  | [^ '\n' '\\' '"' '$' '@']+ { next string lexbuf }  | eof { die_in_string lexbuf "Unterminated_string" } @@ -716,6 +718,8 @@ and string_escape = parse  | '0' { next_s "\000" (Stack.pop next_rule) lexbuf }  | '"' { next_s "\"" (Stack.pop next_rule) lexbuf }  | ''' { next_s "'"  (Stack.pop next_rule) lexbuf } +| ':' { next_s ":"  (Stack.pop next_rule) lexbuf } +| '\\'{ next_s "\\" (Stack.pop next_rule) lexbuf }  | 'n' { next_s "\n" (Stack.pop next_rule) lexbuf }  | 't' { next_s "\t" (Stack.pop next_rule) lexbuf }  | 'x' _ _ {  @@ -724,6 +728,7 @@ and string_escape = parse      next_s s (Stack.pop next_rule) lexbuf     with Failure("int_of_string") -> die_in_string lexbuf ("Bad_hex_in_string \"" ^ lexeme lexbuf ^ "\"")    } +| '\n' { die lexbuf "do not use \"\\\" before end-of-line, it's useless and generally bad" }  | _ { next_s ("\\" ^ lexeme lexbuf) (Stack.pop next_rule) lexbuf } @@ -738,7 +743,8 @@ and string_interpolate_scalar = parse  | "{"  | ident "->"? '{' -| eof { next_s "$" (Stack.pop next_rule) lexbuf } +| '"' { putback lexbuf 1; next_s "$" (Stack.pop next_rule) lexbuf } +| eof {                   next_s "$" (Stack.pop next_rule) lexbuf }  | _ { warn lexbuf (Printf.sprintf "weird \"%s\" in string" (lexeme lexbuf)); next_s ("$" ^ lexeme lexbuf) (Stack.pop next_rule) lexbuf }  and delimited_string_interpolate_scalar = parse (* needed for delimited string like m!foo$! where $! should not be taken as is... *) @@ -772,8 +778,9 @@ and string_interpolate_array = parse  | (ident | (ident? ("::" ident)+)) { string_interpolate token "@" lexbuf }  | [ '@' '*' '<' '>' ']' '.' '('] { next_s ("@" ^ lexeme lexbuf) (Stack.pop next_rule) lexbuf } -| eof { next_s "$" (Stack.pop next_rule) lexbuf } -| _ { warn lexbuf (Printf.sprintf "weird \"%s\" in string" (lexeme lexbuf)); next_s ("$" ^ lexeme lexbuf) (Stack.pop next_rule) lexbuf } +| '"' { putback lexbuf 1; next_s "@" (Stack.pop next_rule) lexbuf } +| eof {                   next_s "@" (Stack.pop next_rule) lexbuf } +| _ { warn lexbuf (Printf.sprintf "weird \"%s\" in string" (lexeme lexbuf)); next_s ("@" ^ lexeme lexbuf) (Stack.pop next_rule) lexbuf }  and delimited_string_interpolate_array = parse  | '$' ident @@ -781,12 +788,12 @@ and delimited_string_interpolate_array = parse  | (ident | (ident? ("::" ident)+)) { string_interpolate token "@" lexbuf }  | [ '@' '*' '<' '>' ']' '.' '('] { next_s ("@" ^ lexeme lexbuf) (Stack.pop next_rule) lexbuf } -| eof { next_s "$" (Stack.pop next_rule) lexbuf } +| eof { next_s "@" (Stack.pop next_rule) lexbuf }  | _ {       let c = lexeme_char lexbuf 0 in      if c <> !delimit_char then warn lexbuf (Printf.sprintf "weird \"%s\" in string" (lexeme lexbuf));      putback lexbuf 1; -    next_s "$" (Stack.pop next_rule) lexbuf +    next_s "@" (Stack.pop next_rule) lexbuf    }  and pattern_options = parse diff --git a/perl_checker.src/parser.mly b/perl_checker.src/parser.mly index a2e61dc..84655eb 100644 --- a/perl_checker.src/parser.mly +++ b/perl_checker.src/parser.mly @@ -12,7 +12,7 @@  %token <unit   * (Types.spaces * Types.raw_pos)> EOF -%token <string * (Types.spaces * Types.raw_pos)> NUM RAW_STRING BAREWORD BAREWORD_PAREN REVISION COMMENT POD LABEL PERL_CHECKER_COMMENT ONE_SCALAR_PARA +%token <string * (Types.spaces * Types.raw_pos)> NUM RAW_STRING BAREWORD BAREWORD_PAREN REVISION COMMENT POD LABEL PO_COMMENT PERL_CHECKER_COMMENT ONE_SCALAR_PARA  %token <(string * string) * (Types.spaces * Types.raw_pos)> PRINT_TO_STAR PRINT_TO_SCALAR  %token <string * (Types.spaces * Types.raw_pos)> QUOTEWORDS COMPACT_HASH_SUBSCRIPT  %token <(string * Types.raw_pos) * (Types.spaces * Types.raw_pos)> RAW_HERE_DOC @@ -425,6 +425,8 @@ bareword:  word_paren:  | BAREWORD_PAREN { Ident(None, fst $1, get_pos $1), snd $1}  | RAW_IDENT_PAREN { to_Ident $1, snd $1} +| PO_COMMENT word_paren { po_comment($1); fst $2, sp_pos_range $1 $2 } +  arraylen: ARRAYLEN_IDENT {deref_arraylen (to_Ident $1), snd $1} | ARRAYLEN  scalar {sp_0($2); deref_arraylen (fst $2), snd $1} | ARRAYLEN  bracket_subscript {deref_arraylen (fst $2), sp_pos_range $1 $2}  scalar:   SCALAR_IDENT   {Deref(I_scalar, to_Ident $1), snd $1} | DOLLAR    scalar {sp_0($2); Deref(I_scalar, fst $2), snd $1} | DOLLAR    bracket_subscript {Deref(I_scalar, fst $2), sp_pos_range $1 $2} | DOLLAR BRACKET BRACKET expr BRACKET_END BRACKET_END {sp_0($2); sp_0($3); sp_p($5); sp_0($6); Deref(I_scalar, Ref(I_hash, sndfst $4)), sp_pos_range $1 $6} diff --git a/perl_checker.src/parser_helper.ml b/perl_checker.src/parser_helper.ml index 7f723a6..e562d15 100644 --- a/perl_checker.src/parser_helper.ml +++ b/perl_checker.src/parser_helper.ml @@ -3,6 +3,9 @@ open Common  open Printf  let bpos = -1, -1 +let pot_strings = ref [] +let pot_strings_and_file = Hashtbl.create 16 +let po_comments = ref []  let raw_pos2pos(a, b) = !Info.current_file, a, b  let pos_range (_, (_, (a1, b1))) (_, (_, (a2, b2))) = raw_pos2pos((if a1 = -1 then a2 else a1), (if b2 = -1 then b1 else b2)) @@ -25,6 +28,7 @@ let is_parenthesized = function  let un_parenthesize = function    | List[List[e]] -> e +  | List[e] -> e    | _ -> internal_error "un_parenthesize"  let rec un_parenthesize_full = function @@ -484,7 +488,15 @@ let call_func is_a_func (e, para) =        | "N" | "N_" ->  	  (match para with -	  | [ List(String([ _s, List [] ], _) :: _) ] -> None +	  | [ List(String([ s, List [] ], (file, _, _)) :: _) ] ->  +	      if !Flags.generate_pot then ( +		lpush pot_strings (s, !po_comments) ; +		po_comments := [] ; +		Hashtbl.add pot_strings_and_file s file ; +	      ) ; +	      (*if String.contains s '\t' then warn_rule "tabulation in translated string must be written \\\\t";*) +	      (*if count_matching_char s '\n' > 10 then warn_rule "long string";*) +	      None  	  | [ List(String _ :: _) ] -> die_rule "don't use interpolated translated string, use %s or %d instead"  	  |  _ -> die_rule (sprintf "%s() must be used with a string" f)) @@ -595,3 +607,30 @@ let from_PATTERN_SUBST parse ((s1, s2, opts), (_, pos)) =    [ String(parse_interpolated parse s1, raw_pos2pos pos) ;       String(parse_interpolated parse s2, raw_pos2pos pos) ;       Raw_string(opts, raw_pos2pos pos) ] + +let po_comment (s, _) = lpush po_comments s + +let generate_pot file =  +  let fd = open_out file in    +  let rec print_formatted_char = function +    | '"'  -> output_char fd '\\'; output_char fd '"' +    | '\t' -> output_char fd '\\'; output_char fd 't' +    | '\\' -> output_char fd '\\'; output_char fd '\\' +    | '\n' -> output_string fd "\\n\"\n\"" +    | c -> output_char fd c +  in +  List.iter (fun (s, po_comments) -> +    match Hashtbl.find_all pot_strings_and_file s with +    | [] -> () +    | l -> +	List.iter (fun po_comment -> output_string fd ("#. " ^ po_comment ^ "\n")) po_comments; + +	List.iter (fun _ -> Hashtbl.remove pot_strings_and_file s) l ; +	fprintf fd "#: %s\n" (String.concat " " l) ; + +	output_string fd (if String.contains s '\n' then "msgid \"\"\n\"" else "msgid \"") ; +	String.iter print_formatted_char s ; +	output_string fd "\"\n" ; +	output_string fd "msgstr \"\"\n\n" +  ) !pot_strings ;       +  close_out fd diff --git a/perl_checker.src/parser_helper.mli b/perl_checker.src/parser_helper.mli index d3a1028..d1aba18 100644 --- a/perl_checker.src/parser_helper.mli +++ b/perl_checker.src/parser_helper.mli @@ -1,4 +1,7 @@  val bpos : int * int +val pot_strings : (string * string list) list ref +val pot_strings_and_file : (string, string) Hashtbl.t +val po_comments : string list ref  val raw_pos2pos : 'a * 'b -> string * 'a * 'b  val pos_range :    'a * ('b * (int * int)) -> 'c * ('d * (int * int)) -> string * int * int @@ -162,3 +165,5 @@ val from_PATTERN_SUBST :    ((string * ((int * int) * 'a) list) list *     (string * ((int * int) * 'a) list) list * string) *    ('b * (int * int)) -> Types.fromparser list +val po_comment : string * 'a -> unit +val generate_pot : string -> unit diff --git a/perl_checker.src/perl_checker.ml b/perl_checker.src/perl_checker.ml index 9d88c6c..eac011f 100644 --- a/perl_checker.src/perl_checker.ml +++ b/perl_checker.src/perl_checker.ml @@ -27,12 +27,12 @@ let findfile dirs f = List.find Sys.file_exists (List.map (fun dir -> dir ^ "/"  let rec parse_file state file =    try      if !Flags.verbose then print_endline_flush ("checking " ^ file) ; -    let channel = Unix.open_process_in (Printf.sprintf "expand \"%s\"" file) in +    let channel = Unix.open_process_in (Printf.sprintf "%s \"%s\"" (if !Flags.expand_tabs then "expand" else "cat") file) in      let lexbuf = Lexing.from_channel channel in      try        Info.start_a_new_file file ;        let tokens = Lexer.get_token Lexer.token lexbuf in -      let _ = Unix.close_process_in channel in +      (*let _ = Unix.close_process_in channel in*)        let t = Parser_helper.parse_tokens Parser.prog tokens (Some lexbuf) in        let packages, required_packages = get_global_info_from_package t in        List.fold_left (fun (required_packages, state) package -> @@ -69,13 +69,22 @@ let rec parse_required_packages state = function        let el, state = parse_package_if_needed state e in        parse_required_packages state (el @ l) +  let parse_options =    let args_r = ref [] in    let restrict_to_files = ref false in + +  let pot_file = ref "" in +  let generate_pot_chosen file = +    Flags.generate_pot := true ; +    Flags.expand_tabs := false ; +    pot_file := file +  in    let options = [      "-v", Arg.Set Flags.verbose, "  be verbose" ;      "-q", Arg.Set Flags.quiet, "  be quiet" ;      "--restrict-to-files", Arg.Set restrict_to_files, "  only display warnings concerning the file(s) given on command line" ; +    "--generate-pot", Arg.String generate_pot_chosen, "" ;    ] in    let usage = "Usage: perl_checker [-v] [-q] <files>\nOptions are:" in    Arg.parse options (lpush args_r) usage; @@ -83,6 +92,8 @@ let parse_options =    let files = if !args_r = [] then ["../t.pl"] else !args_r in    let required_packages, state = collect_withenv parse_file default_state files in +  if !Flags.generate_pot then Parser_helper.generate_pot !pot_file else ( +    if !restrict_to_files then Common.print_endline_flush_quiet := true ;    let state = parse_required_packages state required_packages in    if !restrict_to_files then Common.print_endline_flush_quiet := false ; @@ -94,3 +105,4 @@ let parse_options =    let l = if !restrict_to_files then List.filter (fun pkg -> List.mem pkg.file_name files) l else l in    List.iter (check_tree state) l +  ) | 
