summaryrefslogtreecommitdiff
path: root/stdlib/format.ml
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/format.ml')
-rw-r--r--stdlib/format.ml471
1 files changed, 0 insertions, 471 deletions
diff --git a/stdlib/format.ml b/stdlib/format.ml
deleted file mode 100644
index 6ac6c247ce..0000000000
--- a/stdlib/format.ml
+++ /dev/null
@@ -1,471 +0,0 @@
-(* Tokens are one of the following : *)
-
-type pp_token =
- Pp_text of string (* normal text *)
- | Pp_break of int * int (* complete break *)
- | Pp_tbreak of int * int (* go to next tab *)
- | Pp_stab (* set a tabulation *)
- | Pp_begin of int * block_type (* beginning of a block *)
- | Pp_end (* end of a block *)
- | Pp_tbegin of tblock (* Beginning of a tabulation block *)
- | Pp_tend (* end of a tabulation block *)
- | Pp_newline (* to force a newline inside a block *)
- | Pp_if_newline (* to do something only if this very
- line has been broken *)
-
-and block_type =
- Pp_hbox (* Horizontal block no line breaking *)
- | Pp_vbox (* Vertical block each break leads to a new line *)
- | Pp_hvbox (* Horizontal-vertical block: same as vbox, except if this block
- is small enough to fit on a single line *)
- | Pp_hovbox (* Horizontal or Vertical block: breaks lead to new line
- only when necessary to print the content of the block *)
- | Pp_fits (* Internal usage: when a block fits on a single line *)
-
-and tblock = Pp_tbox of int list ref (* Tabulation box *)
-
-(* The Queue: contains all formatting elements.
- elements are tuples (size,token,length), where
- size is set when the size of the block is known
- len is the declared length of the token *)
-type pp_queue_elem =
- {mutable elem_size : int; token : pp_token; length : int}
-
-(* Scan stack
- each element is (left_total, queue element) where left_total
- is the value of pp_left_total when the element has been enqueued *)
-type pp_scan_elem = Scan_elem of int * pp_queue_elem
-let pp_scan_stack = ref ([] : pp_scan_elem list)
-
-(* Formatting Stack:
- used to break the lines while printing tokens.
- The formatting stack contains the description of
- the currently active blocks. *)
-type pp_format_elem = Format_elem of block_type * int
-let pp_format_stack = ref ([]:pp_format_elem list)
-
-let pp_tbox_stack = ref ([]:tblock list)
-
-(* Large value for default tokens size *)
-let pp_infinity = 9999
-
-(* Global variables: default initialization is
- set_margin 78
- set_min_space_left 0 *)
-(* value of right margin *)
-let pp_margin = ref 78
-
-(* Minimal space left before margin, when opening a block *)
-let pp_min_space_left = ref 10
-(* maximum value of indentation:
- no blocks can be opened further *)
-let pp_max_indent = ref (!pp_margin - !pp_min_space_left)
-
-let pp_space_left = ref !pp_margin(* space remaining on the current line *)
-and pp_current_indent = ref 0 (* current value of indentation *)
-and pp_left_total = ref 1 (* total width of tokens already printed *)
-and pp_right_total = ref 1 (* total width of tokens ever put in queue *)
-and pp_curr_depth = ref 0 (* current number of opened blocks *)
-and pp_max_boxes = ref 35 (* maximum number of blocks which can be
- opened at the same time *)
-and pp_ellipsis = ref "." (* ellipsis string *)
-and pp_out_channel = ref stdout (* out_channel of the pretty_printer *)
-
-(* Output functions for the formatter *)
-let pp_output s = output !pp_out_channel s
-and pp_output_string s = output_string !pp_out_channel s
-and pp_output_newline () = output_char !pp_out_channel '\n'
-
-(* The pretty-printer queue *)
-let pp_queue = (Queue.new () : pp_queue_elem Queue.t)
-
-let pp_clear_queue () =
- pp_left_total := 1; pp_right_total := 1;
- Queue.clear pp_queue
-
-(* Enter a token in the pretty-printer queue *)
-let pp_enqueue ({length=len} as token) =
- pp_right_total := !pp_right_total + len;
- Queue.add token pp_queue
-
-(* To output spaces *)
-let blank_line = String.make 80 ' '
-let display_blanks n =
- if n > 0 then
- if n <= 80 then pp_output blank_line 0 n
- else pp_output_string (String.make n ' ')
-
-(* To format a break, indenting a new line *)
-let break_new_line offset width =
- pp_output_newline ();
- let indent = !pp_margin - width + offset in
- (* Don't indent more than pp_max_indent *)
- let real_indent = min !pp_max_indent indent in
- pp_current_indent := real_indent;
- pp_space_left := !pp_margin - !pp_current_indent;
- display_blanks !pp_current_indent
-
-(* To force a line break inside a block: no offset is added *)
-let break_line width = break_new_line 0 width
-
-(* To format a break that fits on the current line *)
-let break_same_line width =
- pp_space_left := !pp_space_left - width;
- display_blanks width
-
-(* To indent no more than pp_max_indent, if one tries to open a block
- beyond pp_max_indent, then the block is rejected on the left
- by simulating a break. *)
-let pp_force_newline () =
- match !pp_format_stack with
- Format_elem (bl_ty, width) :: _ ->
- if width > !pp_space_left then
- (match bl_ty with
- Pp_fits -> () | Pp_hbox -> () | _ -> break_line width)
- | _ -> pp_output_newline()
-
-(* To skip a token, if the previous line has been broken *)
-let pp_skip_token () =
- (* When calling pp_skip_token the queue cannot be empty *)
- match Queue.take pp_queue with
- {elem_size = size; length = len} ->
- pp_left_total := !pp_left_total - len;
- pp_space_left := !pp_space_left + size
-
-(* To format a token *)
-let format_pp_token size = function
-
- Pp_text s -> pp_space_left := !pp_space_left - size; pp_output_string s
-
- | Pp_begin (off,ty) ->
- let insertion_point = !pp_margin - !pp_space_left in
- if insertion_point > !pp_max_indent then
- (* can't open a block right there ! *)
- pp_force_newline () else
- (* If block is rejected on the left current indentation will change *)
- if size > !pp_space_left & !pp_current_indent < insertion_point then
- pp_force_newline ();
- let offset = !pp_space_left - off in
- let bl_type =
- begin match ty with
- Pp_vbox -> Pp_vbox
- | _ -> if size > !pp_space_left then ty else Pp_fits
- end in
- pp_format_stack := Format_elem (bl_type, offset) :: !pp_format_stack
-
- | Pp_end ->
- begin match !pp_format_stack with
- x::(y::l as ls) -> pp_format_stack := ls
- | _ -> () (* No more block to close *)
- end
-
- | Pp_tbegin (Pp_tbox _ as tbox) -> pp_tbox_stack := tbox :: !pp_tbox_stack
-
- | Pp_tend ->
- begin match !pp_tbox_stack with
- x::ls -> pp_tbox_stack := ls
- | _ -> () (* No more tabulation block to close *)
- end
-
- | Pp_stab ->
- begin match !pp_tbox_stack with
- Pp_tbox tabs :: _ ->
- let rec add_tab n = function
- [] -> [n]
- | x::l as ls -> if n < x then n :: ls else x::add_tab n l in
- tabs := add_tab (!pp_margin - !pp_space_left) !tabs
- | _ -> () (* No opened tabulation block *)
- end
-
- | Pp_tbreak (n,off) ->
- let insertion_point = !pp_margin - !pp_space_left in
- begin match !pp_tbox_stack with
- Pp_tbox tabs :: _ ->
- let rec find n = function
- x :: l -> if x >= n then x else find n l
- | [] -> raise Not_found in
- let tab =
- match !tabs with
- x :: l ->
- begin try find insertion_point !tabs with Not_found -> x end
- | _ -> insertion_point in
- let offset = tab - insertion_point in
- if offset >= 0 then break_same_line (offset + n) else
- break_new_line (tab + off) !pp_margin
- | _ -> () (* No opened tabulation block *)
- end
-
- | Pp_newline ->
- begin match !pp_format_stack with
- Format_elem (_,width) :: _ -> break_line width
- | _ -> pp_output_newline()
- end
-
- | Pp_if_newline ->
- if !pp_current_indent != !pp_margin - !pp_space_left
- then pp_skip_token ()
-
- | Pp_break (n,off) ->
- begin match !pp_format_stack with
- Format_elem (ty,width) :: _ ->
- begin match ty with
- Pp_hovbox ->
- if size > !pp_space_left then break_new_line off width else
- (* break the line here leads to new indentation ? *)
- if (!pp_current_indent > !pp_margin - width + off)
- then break_new_line off width else break_same_line n
- | Pp_hvbox -> break_new_line off width
- | Pp_fits -> break_same_line n
- | Pp_vbox -> break_new_line off width
- | Pp_hbox -> break_same_line n
- end
- | _ -> () (* No opened block *)
- end
-
-(* Print if token size is known or printing is delayed
- Size is known when not negative
- Printing is delayed when the text waiting in the queue requires
- more room to format than List.exists on the current line *)
-let rec advance_left () =
- try
- match Queue.peek pp_queue with
- {elem_size = size; token = tok; length = len} ->
- if not (size < 0 &
- (!pp_right_total - !pp_left_total <= !pp_space_left)) then
- begin
- Queue.take pp_queue;
- format_pp_token (if size < 0 then pp_infinity else size) tok;
- pp_left_total := len + !pp_left_total;
- advance_left ()
- end
- with Queue.Empty -> ()
-
-let enqueue_advance tok = pp_enqueue tok; advance_left ()
-
-(* To enqueue a string : try to advance *)
-let enqueue_string_as n s =
- enqueue_advance {elem_size = n; token = Pp_text s; length = n}
-
-let enqueue_string s = enqueue_string_as (String.length s) s
-
-(* Routines for scan stack
- determine sizes of blocks *)
-(* scan_stack is never empty *)
-let empty_scan_stack =
- [Scan_elem (-1, {elem_size = (-1); token = Pp_text ""; length = 0})]
-let clear_scan_stack () = pp_scan_stack := empty_scan_stack
-
-(* Set size of blocks on scan stack:
- if ty = true then size of break is set else size of block is set
- in each case pp_scan_stack is popped *)
-(* Pattern matching on scan stack is exhaustive,
- since scan_stack is never empty.
- Pattern matching on token in scan stack is also exhaustive,
- since scan_push is used on breaks and opening of boxes *)
-let set_size ty =
- match !pp_scan_stack with
- Scan_elem (left_tot,
- ({elem_size = size; token = tok} as queue_elem)) :: t ->
- (* test if scan stack contains any data that is not obsolete *)
- if left_tot < !pp_left_total then clear_scan_stack () else
- begin match tok with
- Pp_break (_, _) | Pp_tbreak (_, _) ->
- if ty then
- begin
- queue_elem.elem_size <- !pp_right_total + size;
- pp_scan_stack := t
- end
- | Pp_begin (_, _) ->
- if not ty then
- begin
- queue_elem.elem_size <- !pp_right_total + size;
- pp_scan_stack := t
- end
- | _ -> () (* scan_push is only used for breaks and boxes *)
- end
- | _ -> () (* scan_stack is never empty *)
-
-(* Push a token on scan stack. If b is true set_size is called *)
-let scan_push b tok =
- pp_enqueue tok;
- if b then set_size true;
- pp_scan_stack := Scan_elem (!pp_right_total,tok) :: !pp_scan_stack
-
-(*
- To open a new block :
- the user may set the depth bound pp_max_boxes
- any text nested deeper is printed as the character the ellipsis
-*)
-let pp_open_box (indent,br_ty) =
- incr pp_curr_depth;
- if !pp_curr_depth < !pp_max_boxes then
- (scan_push false
- {elem_size = (- !pp_right_total);
- token = Pp_begin (indent, br_ty); length = 0}) else
- if !pp_curr_depth = !pp_max_boxes then enqueue_string !pp_ellipsis
-
-(* The box which is always opened *)
-let pp_open_sys_box () =
- incr pp_curr_depth;
- scan_push false
- {elem_size = (- !pp_right_total);
- token = Pp_begin (0, Pp_hovbox); length = 0}
-
-(* close a block, setting sizes of its subblocks *)
-let close_box () =
- if !pp_curr_depth > 1 then
- begin
- if !pp_curr_depth < !pp_max_boxes then
- begin
- pp_enqueue {elem_size = 0; token = Pp_end; length = 0};
- set_size true; set_size false
- end;
- decr pp_curr_depth
- end
-
-(* Initialize pretty-printer. *)
-let pp_rinit () =
- pp_clear_queue ();
- clear_scan_stack();
- pp_current_indent := 0;
- pp_curr_depth := 0; pp_space_left := !pp_margin;
- pp_format_stack := [];
- pp_tbox_stack := [];
- pp_open_sys_box ()
-
-(* Flushing pretty-printer queue. *)
-let pp_flush b =
- while !pp_curr_depth > 1 do
- close_box ()
- done;
- pp_right_total := pp_infinity; advance_left ();
- if b then pp_output_newline ();
- flush !pp_out_channel;
- pp_rinit()
-
-(**************************************************************
-
- Procedures to format objects, and use boxes
-
- **************************************************************)
-
-(* To format a string *)
-let print_as n s =
- if !pp_curr_depth < !pp_max_boxes then (enqueue_string_as n s)
-
-let print_string s = print_as (String.length s) s
-
-(* To format an integer *)
-let print_int i = print_string (string_of_int i)
-
-(* To format a float *)
-let print_float f = print_string (string_of_float f)
-
-(* To format a boolean *)
-let print_bool b = print_string (string_of_bool b)
-
-(* To format a char *)
-let print_char c = print_string (String.make 1 c)
-
-let open_hbox () = pp_open_box (0, Pp_hbox)
-and open_vbox indent = pp_open_box (indent, Pp_vbox)
-
-and open_hvbox indent = pp_open_box (indent, Pp_hvbox)
-and open_hovbox indent = pp_open_box (indent, Pp_hovbox)
-
-(* Print a new line after printing all queued text
- (same for print_flush but without a newline) *)
-let print_newline () = pp_flush true
-and print_flush () = pp_flush false
-
-(* To get a newline when one does not want to close the current block *)
-let force_newline () =
- if !pp_curr_depth < !pp_max_boxes
- then enqueue_advance {elem_size = 0; token = Pp_newline; length = 0}
-
-(* To format something if the line has just been broken *)
-let print_if_newline () =
- if !pp_curr_depth < !pp_max_boxes
- then enqueue_advance {elem_size = 0; token = Pp_if_newline ;length = 0}
-
-(* Breaks: indicate where a block may be broken.
- If line is broken then offset is added to the indentation of the current
- block else (the value of) width blanks are printed.
- To do (?) : add a maximum width and offset value *)
-let print_break (width, offset) =
- if !pp_curr_depth < !pp_max_boxes then
- scan_push true
- {elem_size = (- !pp_right_total); token = Pp_break (width,offset);
- length = width}
-
-let print_space () = print_break (1,0)
-and print_cut () = print_break (0,0)
-
-let open_tbox () =
- incr pp_curr_depth;
- if !pp_curr_depth < !pp_max_boxes then
- enqueue_advance
- {elem_size = 0;
- token = Pp_tbegin (Pp_tbox (ref [])); length = 0}
-
-(* Close a tabulation block *)
-let close_tbox () =
- if !pp_curr_depth > 1 then begin
- if !pp_curr_depth < !pp_max_boxes then
- enqueue_advance {elem_size = 0; token = Pp_tend; length = 0};
- decr pp_curr_depth end
-
-(* Print a tabulation break *)
-let print_tbreak (width, offset) =
- if !pp_curr_depth < !pp_max_boxes then
- scan_push true
- {elem_size = (- !pp_right_total); token = Pp_tbreak (width,offset);
- length = width}
-
-let print_tab () = print_tbreak (0,0)
-
-let set_tab () =
- if !pp_curr_depth < !pp_max_boxes
- then enqueue_advance {elem_size = 0; token = Pp_stab; length=0}
-
-(**************************************************************
-
- Procedures to control the pretty-printer
-
- **************************************************************)
-
-(* Fit max_boxes *)
-let set_max_boxes n = if n > 1 then pp_max_boxes := n
-
-(* To know the current maximum number of boxes allowed *)
-let get_max_boxes () = !pp_max_boxes
-
-(* Ellipsis *)
-let set_ellipsis_text s = pp_ellipsis := s
-and get_ellipsis_text () = !pp_ellipsis
-
-(* To set the margin of pretty-formater *)
-let set_margin n =
- if n >= 1 then
- begin
- pp_margin := n;
- pp_max_indent := !pp_margin - !pp_min_space_left;
- pp_rinit () end
-
-let get_margin () = !pp_margin
-
-let set_min_space_left n =
- if n >= 1 then
- begin
- pp_min_space_left := n;
- pp_max_indent := !pp_margin - !pp_min_space_left;
- pp_rinit () end
-
-let set_max_indent n = set_min_space_left (!pp_margin - n)
-let get_max_indent () = !pp_max_indent
-
-let set_formatter_output os = pp_out_channel := os
-let get_formatter_output () = !pp_out_channel
-
-(* Initializing formatter *)
-let _ = pp_rinit()