diff --git a/Changes b/Changes index e9e89bc..3711fd1 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,9 @@ 2.5 (Upcoming) o Environment variable CPDF_REPRODUCIBLE_DATES for testing +o Environment variable CPDF_DEBUG for -debug o Effectively make stderr unbuffered +o Prepend NOT to a page range to invert it 2.4 (June 2021) diff --git a/cpdf.ml b/cpdf.ml index 2d87686..39f0202 100644 --- a/cpdf.ml +++ b/cpdf.ml @@ -435,38 +435,45 @@ let fixup_negatives endpage = function Pdfgenlex.LexInt (endpage + 1 + ~-(int_of_string (implode (tl (explode s))))) | x -> x -let parse_pagespec_inner endpage pdf spec = +let invert_range endpage r = + option_map (fun p -> if mem p r then None else Some p) (ilist 1 endpage) + +let rec parse_pagespec_inner endpage pdf spec = let spec = space_string spec in if endpage < 1 then raise (Pdf.PDFError "This PDF file has no pages and is therefore malformed") else let numbers = try - match rev (explode spec) with - | ['n'; 'e'; 'v'; 'e'] -> - keep even (ilist 1 endpage) - | ['d'; 'd'; 'o'] -> - keep odd (ilist 1 endpage) - | ['t'; 'i'; 'a'; 'r'; 't'; 'r'; 'o'; 'p'] -> - select_portrait pdf (ilist 1 endpage) - | ['e'; 'p'; 'a'; 'c'; 's'; 'd'; 'n'; 'a'; 'l'] -> - select_landscape pdf (ilist 1 endpage) - | 't'::'i'::'a'::'r'::'t'::'r'::'o'::'p'::more -> - select_portrait - pdf - (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) - | 'e'::'p'::'a'::'c'::'s'::'d'::'n'::'a'::'l'::more -> - select_landscape - pdf - (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) - | 'd'::'d'::'o'::more -> - keep - odd - (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) - | 'n'::'e'::'v'::'e'::more -> - keep - even - (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) + match explode spec with + | 'N'::'O'::'T'::r -> + invert_range endpage (parse_pagespec_inner endpage pdf (implode r)) | _ -> - mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string spec)) + match rev (explode spec) with + | ['n'; 'e'; 'v'; 'e'] -> + keep even (ilist 1 endpage) + | ['d'; 'd'; 'o'] -> + keep odd (ilist 1 endpage) + | ['t'; 'i'; 'a'; 'r'; 't'; 'r'; 'o'; 'p'] -> + select_portrait pdf (ilist 1 endpage) + | ['e'; 'p'; 'a'; 'c'; 's'; 'd'; 'n'; 'a'; 'l'] -> + select_landscape pdf (ilist 1 endpage) + | 't'::'i'::'a'::'r'::'t'::'r'::'o'::'p'::more -> + select_portrait + pdf + (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) + | 'e'::'p'::'a'::'c'::'s'::'d'::'n'::'a'::'l'::more -> + select_landscape + pdf + (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) + | 'd'::'d'::'o'::more -> + keep + odd + (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) + | 'n'::'e'::'v'::'e'::more -> + keep + even + (mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string (implode (rev more))))) + | _ -> + mk_numbers pdf endpage (map (fixup_negatives endpage) (Pdfgenlex.lex_string spec)) with e -> raise PageSpecBadSyntax in diff --git a/cpdfcommand.ml b/cpdfcommand.ml index b12785b..a6d6786 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -4408,6 +4408,12 @@ let gs_malformed_force fi fo = ensure that all memory is cleaned. See clearance of filenames hashtable, for example. *) +let process_env_vars () = + match Sys.getenv_opt "CPDF_DEBUG" with + | Some "true" -> args.debug <- true + | Some "false" -> args.debug <- false + | _ -> () + (* Main function. *) let go_withargv argv = (* Check for the standalone -gs-malformed-force special command line. This @@ -4450,6 +4456,7 @@ let go_withargv argv = (*Printf.printf "AND:%b, %s\n" islast (Array.fold_left (fun x y -> x ^ " " ^ y) "" s); flprint "\n";*) reset_arguments (); + process_env_vars (); parse_argv () s (align_specs specs) anon_fun usage_msg; parse_argv () (Array.of_list ("cpdf"::!control_args)) (align_specs specs) anon_fun usage_msg; let addrange pdf = AlreadyInMemory pdf, args.dashrange, "", "", ref false, None in diff --git a/cpdfmanual.pdf b/cpdfmanual.pdf index 18eed60..43d7f26 100644 Binary files a/cpdfmanual.pdf and b/cpdfmanual.pdf differ diff --git a/cpdfmanual.tex b/cpdfmanual.tex index 726b1bc..e67a6bd 100644 --- a/cpdfmanual.tex +++ b/cpdfmanual.tex @@ -459,6 +459,7 @@ at least five pages. \item The word \texttt{all} is the same as \texttt{1-end}. \item A range must contain no spaces. \item A tilde (\texttt{\~{}}) defines a page number counting from the end of the document rather than the beginning. Page \texttt{\~{}1} is the last page, \texttt{\~{}2} the penultimate page etc. + \item Prepending \texttt{NOT} to a whole page range inverts it. \end{itemize} \noindent For example: