open Printf let iterations = 100;; (*============================================================================*) let build_byte_triplet instr index = (*1*) let a = int_of_char instr.[index] (*2*) and b = int_of_char instr.[index+1] (*3*) and c = int_of_char instr.[index+2] (*4*) and d = int_of_char instr.[index+3] (*5*) in (((a-32) lsl 18) lor (((b-32) lsl 12) lor (((c-32) lsl 6) lor (d-32))));; (*6*) let build_byte_duo instr index = (*7*) let a = int_of_char instr.[index] (*8*) and b = int_of_char instr.[index+1] (*9*) and c = int_of_char instr.[index+2] (*10*) in (((a-32) lsl 10) lor (((b-32) lsl 4) lor (((c-32) land 15))));; (*11*) let build_byte instr index = (*12*) let a = int_of_char instr.[index] (*13*) and b = int_of_char instr.[index+1] (*14*) in (((a-32) lsl 2) lor ((b-32) land 3)) (*15*) let put_triplet str index triplet = (*16*) (str.[index] <- char_of_int ((triplet lsl 16) land 255) ; (*17*) str.[index+1] <- char_of_int ((triplet lsl 8) land 255); (*18*) str.[index+2] <- char_of_int (triplet land 255));; (*19*) let put_duo str index duo = (*20*) (str.[index] <- char_of_int ((duo lsl 8) land 255); (*21*) str.[index+1] <- char_of_int (duo land 255));; (*22*) let put_byte str index byte = (*23*) str.[index] <- char_of_int (byte land 255);; (*24*) let get_nof_octets instr index = (*25*) (int_of_char instr.[index]) - 32;; (*26*) let check_postamble instr inoff acc = (*27*) if (String.sub instr inoff 4) == "\nend" (*28*) then String.concat "" (List.rev acc) (*29*) else String.concat "" (List.rev acc);; (*30*) let rec uudecode_line instr outstr inoff outoff nof_octets acc = (*31*) if nof_octets>=3 (*32*) then (put_triplet outstr outoff (build_byte_triplet instr inoff); (*33*) uudecode_line instr outstr (inoff+4) (outoff+3) (nof_octets-3) acc) (*34*) else if nof_octets==0 (*35*) then skip_to_next_line instr inoff (outstr::acc) (*36*) else if nof_octets==1 (*37*) then (put_byte outstr outoff (build_byte instr inoff); (*38*) skip_to_next_line instr (inoff+4) (outstr::acc)) (*39*) else (put_duo outstr outoff (build_byte_duo instr inoff); (*40*) skip_to_next_line instr (inoff+4) (outstr::acc)) (*41*) and uudecode_lines instr inoff acc = (*42*) let nof_octets = ((int_of_char instr.[inoff]) - 32) (*43*) in if nof_octets == 0 (*44*) then check_postamble instr (inoff+1) acc (*45*) else uudecode_line instr (String.create nof_octets) (inoff+1) 0 nof_octets acc (*46*) and skip_to_next_line instr inoff acc = (*47*) if (int_of_char instr.[inoff]) == 10 (*48*) then uudecode_lines instr (inoff+1) acc (*49*) else skip_to_next_line instr (inoff+1) acc;; (*50*) let rec get_name str startoff size = (*51*) if (int_of_char str.[startoff+size]) == 32 (*52*) then if (int_of_char str.[startoff+size+1]) == 10 (*53*) then String.sub str startoff (size) (*54*) else get_name str startoff (size+1) (*55*) else get_name str startoff (size+1);; (*56*) let decode str = (*57*) match String.sub str 0 6 with (*58*) "begin " -> (*59*) let u = int_of_char str.[6] (*60*) and g = int_of_char str.[7] (*61*) and a = int_of_char str.[8] (*62*) and name = get_name str 10 0 (*63*) in ((u lsl 6) lor ((g lsl 3) lor a), name, (*64*) uudecode_lines str (12 + String.length name) []) (*65*) (*============================================================================*) let rec iter n f = if n>1 then (f(); iter (n-1) f) else f();; let get_file fname = let handle = open_in fname in let len = (in_channel_length handle); in let s = String.create len in (really_input handle s 0 len; s);; let main inname = let str = get_file inname in let start = Sys.time() in match (iter iterations (function () -> decode str)) with (access,name,outstr) -> let stop = Sys.time () in let time = (stop -. start) in let out = open_out_gen [Open_wronly] access name in (output out outstr 0 (String.length outstr); printf "%.3f" time; flush stdout) ;; let () = let infile = (Array.get Sys.argv 1); in main infile;;