La fonction counts est chargée du comptage d'une ligne.
# letseps=" \t";;val seps : string = " \t"
# letnl=ref0;;val nl : int ref = {contents=0}
# letnw=ref0;;val nw : int ref = {contents=0}
# letnc=ref0;;val nc : int ref = {contents=0}
La fonction count itère la fonction de comptage d'une ligne sur l'ensemble des lignes d'un fichier.
# letcountss=letwas_sep=reftrueinletn=String.lengthsinfori=0ton-1doletis_sep=String.containssepss.[i]inifis_sep&&(not!was_sep)thenincrnw;was_sep:=is_sepdone;ifnot!was_septhenincrnw;nc:=!nc+n+1;incrnl;;val counts : string -> unit = <fun>
La fonction principale appelle la fonction de comptage sur le nom de fichier passé en argument et affiche les résultats.
# letcountf=nl:=0;nw:=0;nc:=0;letf_in=open_infintrywhiletruedocounts(input_linef_in)donewithEnd_of_file->close_inf_in;;val count : string -> unit = <fun>
# letprint_count()=Printf.printf"\t%d"!nl;Printf.printf"\t%d"!nw;Printf.printf"\t%d\n"!nc;;val print_count : unit -> unit = <fun>
# letmain()=tryifArray.lengthSys.argv<2thenprint_string"wc1: missing file name\n"else(countSys.argv.(1);print_count())withe->Printf.printf"wc1: %s\n"(Printexc.to_stringe);;val main : unit -> unit = <fun>
On redéfinit l'affichage en fonction du statut des options.
# letl_opt=reffalseandw_opt=reffalseandc_opt=reffalse;;val l_opt : bool ref = {contents=false}val w_opt : bool ref = {contents=false}val c_opt : bool ref = {contents=false}
La ligne de commande est analysée pour mettre à jour le statut des options ainsi que la liste des fichiers à traiter.
# letprint_countf=Printf.printf"%s:"f;if!l_optthenPrintf.printf"\t%d"!nl;if!w_optthenPrintf.printf"\t%d"!nw;if!c_optthenPrintf.printf"\t%d"!nc;print_newline();;val print_count : string -> unit = <fun>
La fonction principale itère le comptage sur la liste des fichiers.
# letf_list=ref([]:stringlist);;val f_list : string list ref = {contents=[]}
# letread_args()=letusage_msg="wc2 [-l] [-w] [-w] files..."inletadd_ff=f_list:=f::!f_listinletspec_list=[("-l",Arg.Setl_opt,"affichage nombre de lignes");("-w",Arg.Setw_opt,"affichage nombre de mots");("-c",Arg.Setc_opt,"affichage nombre de caractères")]inArg.parsespec_listadd_fusage_msg;;val read_args : unit -> unit = <fun>
# letmain()=tryread_args();List.iter(funf->countf;print_countf)!f_listwithe->Printf.printf"wc2: %s\n"(Printexc.to_stringe);;val main : unit -> unit = <fun>
| .
# letpipe_two_progs(p1,args1)(p2,args2)=letin2,out1=Unix.pipe()inmatchUnix.fork()with0->Unix.closein2;Unix.closeUnix.stdout;ignore(Unix.dupout1);Unix.closeout1;Unix.execvpp1(Array.of_listargs1)|_->Unix.closeout1;Unix.closeUnix.stdin;ignore(Unix.dupin2);Unix.closein2;Unix.execvpp2(Array.of_listargs2);;val pipe_two_progs : string * string list -> string * string list -> unit =<fun>
# letorthographediconom=letf=open_innomintrywhiletruedolets=input_linefinletls=motssinList.iter(Printf.printf"%s\n")(verifiedicols)done;failwith"cas impossible"withEnd_of_file->close_inf|x->close_inf;raisex;;val orthographe : arbre_lex -> string -> unit = <fun>
# lettrie()=letl=ref[]intrywhiletruedol:=Sort.list(<)((input_linestdin)::!l)donewithEnd_of_file->List.iter(Printf.printf"%s\n")!l;;val trie : unit -> unit = <fun>
# pipe_two_progs("orthographe",["";Sys.argv.(1)])("tri",[]);;
Pour itérer le pipeline, on définit une fonction récursive dont le premier argument donne le canal d'entrée du premier processus à chaîner.
# letdup_stdinin_descr=ifin_descr<>Unix.stdinthenUnix.dup2in_descrUnix.stdin;Unix.closein_descr;;val dup_stdin : Unix.file_descr -> unit = <fun>
# letdup_stdoutout_descr=ifout_descr<>Unix.stdoutthenUnix.dup2out_descrUnix.stdout;Unix.closeout_descr;;val dup_stdout : Unix.file_descr -> unit = <fun>
# letrecpipe_n_progs_loopin_descr=function[p,args]->dup_stdinin_descr;Unix.execvpp(Array.of_listargs)|(p,args)::ps->letin2,out1=Unix.pipe()in(matchUnix.fork()with0->Unix.closein2;dup_stdinin_descr;dup_stdoutout1;Unix.execvpp(Array.of_listargs)|_->Unix.closeout1;pipe_n_progs_loopin2ps)|_->();;val pipe_n_progs_loop :Unix.file_descr -> (string * string list) list -> unit = <fun>
# letpipe_n_progsps=pipe_n_progs_loopUnix.stdinps;;val pipe_n_progs : (string * string list) list -> unit = <fun>
# letrmdup()=letl=ref[]intrywhiletruedoletx=input_linestdininifnot(List.memx!l)thenl:=x::!ldonewithEnd_of_file->List.iter(Printf.printf"%s\n")!l;;val rmdup : unit -> unit = <fun>
# pipe_n_progs[("orthographe",["";Sys.argv.(1)]);("tri",[]);("rmdup",[])];;
# letresult=ref0;;val result : int ref = {contents=0}
# letreceras=function[]->[]|p::q->result:=p;p::(eras(List.filter(funx->xmodp<>0)q));;val eras : int list -> int list = <fun>
# letsigint_handle(_:int)=Printf.printf"Current prime number : %d\n"!result;flushstdout;;val sigint_handle : int -> unit = <fun>
# Sys.set_signalSys.sigint(Sys.Signal_handlesigint_handle);;- : unit = ()
$ ocamlc premiers.ml $ premiers 15000 Current prime number : 2539 Current prime number : 8263 2 3 5 7 11 13 17 19 23 29 31 37 41 43 ............