(** * cat.ml * ColorML_v2 project * (C) Lilian Besson, 2014 *) open Types;; open Parser;; open Lexer;; open Print;; open ANSITerminal;; let print_string = Pervasives.print_string;; let print_titre fichier = ANSITerminal.print_string [ANSITerminal.Bold; ANSITerminal.Underlined] ("\n["^fichier^"]:\n");; (** Fonction ecrire_sortie : plus pratique que output. *) let ecrire_sortie monoutchanel machaine = output monoutchanel machaine 0 (String.length machaine); flush monoutchanel;; (** Fonction ecrire_dans_fichier : pour écrire la chaine dans le fichier à l'adresse renseignée. *) let ecrire_dans_fichier ~chaine ~adresse = let mon_out_channel = open_out adresse in ecrire_sortie mon_out_channel chaine;; (** Fonction in_list : tail recursive plus pratique que List.exists (fun x -> x=a) l. *) let rec in_list element = function |[] -> false; |el :: ssl -> if (element = el) then true else (in_list element ssl);; (** Pour extraire une sous-string, plus pratique que String.sub. *) let monsub mastr idebut taille = let res = ref "" in if taille >= 0 then res := (String.sub mastr idebut taille); !res;; (** Decoupe_custom ~e: : découpe la chaine d'entree en morceau, en commancant un nouveau morceau pour chaque "e" trouvé. *) let rec decoupe_custom ?(e = ['#']) ma_string = let n = (String.length ma_string); and result = ref []; and i = ref 0; in if (n > 0) then begin while ( (!i < (n - 1)) && not(in_list ma_string.[!i] e)) do incr i; done; if (!i = (n - 1)) then result := [ma_string]; if (!i <= (n - 2)) then result := [(monsub ma_string 0 !i)]@(decoupe_custom ~e (monsub ma_string (!i + 1) (n - !i - 1) )); end; !result;; (** {5 Différentes fonctions parse} *) (** Renvoie le contenu de la première ligne d'un fichier texte. *) let parse_file ~file = (* fichiers a une seule lignes *) input_line (open_in file);; (** Renvoie le contenu du fichier texte en entier. *) let parse_file_full ?(n = false) ~file = (*(** file : correspond à l'adresse (relative ou absolue) du fichier que l'on veut lire. *) (** /!\ CONVENTION : on utilise toujours la réprésentation fichier de Unix : /home/superman/Bureau/puzzle_de_la_mort_qui_tue.instance *) *) (** On ouvre le canal. *) let canal_entree = open_in file; in let finlecture = ref false; in let nb_ligne = ref 0; in let result = ref "" in let ( ^= ) s a = s := !s ^ a; in (** On commence à lire, *) let rec auxi mon_ce = let res_input = (try (((input_line mon_ce))) with End_of_file -> (finlecture := true; "")); in (** Si on a pas finit de lire, on analyse : *) if (not !finlecture) then ( if n then result ^= ((string_of_int (!nb_ligne))^"\t|"); result ^= res_input; (** On a encore des lignes à lire (on écrit donc un caractère nouvelle ligne) *) result ^= "\n"; incr nb_ligne; (auxi mon_ce); ) else close_in canal_entree; (** Sinon, on clos le canal d'entrée, et on passe a la suite. *) in auxi canal_entree; (** On conclut en fermant le canal d'entréé et en renvoyant le contenu. *) close_in canal_entree; !result;; (** {6 Module MOCamlStd : quelques fonctions de lecture de fichiers }*) type 'a _mut_list = { hd : 'a; mutable tl : 'a _mut_list; } let input_list ch = let _empty = Obj.magic [] in let rec loop dst = let r = { hd = input_line ch; tl = _empty } in dst.tl <- r; loop r in let r = { hd = Obj.magic(); tl = _empty } in try loop r with End_of_file -> Obj.magic r.tl (** Returns the list of lines read from an input channel. *) let buf_len = 8192 let input_all ic = let rec loop acc total buf ofs = let n = input ic buf ofs (buf_len - ofs) in if n = 0 then let res = String.create total in let pos = total - ofs in let _ = String.blit buf 0 res pos ofs in let coll pos buf = let new_pos = pos - buf_len in String.blit buf 0 res new_pos buf_len; new_pos in let _ = List.fold_left coll pos acc in res else let new_ofs = ofs + n in let new_total = total + n in if new_ofs = buf_len then loop (buf :: acc) new_total (String.create buf_len) 0 else loop acc new_total buf new_ofs in loop [] 0 (String.create buf_len) 0 (** Returns the list of lines read from an input channel. *) let input_file ?(bin=false) fname = let ch = (if bin then open_in_bin else open_in) fname in let str = input_all ch in close_in ch; str (** returns the data of a given filename. *) (** Affiche une liste de fichiers. *) let cat f = Array.iter (fun s -> ( if (s <> "") then( print_titre s; print_string (parse_file_full ~n:true ~file:s); ))) f;; (** L'exception qui est renvoyé si le processus appelé par la fonction faireZ retourne un code d'erreur UNIX spécifiant une erreur. *) exception CatAll_Erreur of int;; (** Exécute une commande système, mais lève une exception en cas de problème du processus appelé. *) let faireZ cmd = match (Sys.command cmd) with | 0 -> (); | n -> raise (CatAll_Erreur(n));; let catml s = affiche_fichierquiet ~adresse_in:s ~adresse_out:"stdout" ~stat:false ~adresse_stat:"stdout" ~color:true ();; (** Application *) if !(Sys.interactive) then ( print_titre "Erreur : CatAll ne fonctionne qu'en exécutable pour ligne de commandes.\n"; (* exit(1);*) ) else ( ANSITerminal.print_string [ANSITerminal.Bold] ""; (* print_titre "";*) flush_all (); Array.iter catml ((fun a -> (try (Array.sub a 1 (-1 + Array.length a)) with _ -> [||] ) ) Sys.argv) ) ;;