Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/cm/util/autodir.sml
ViewVC logotype

Annotation of /sml/trunk/src/cm/util/autodir.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 772 - (view) (download)

1 : blume 354 (*
2 :     * Opening files for output while automagically creating any
3 :     * necessary directories.
4 :     *
5 :     * Copyright (c) 1999 by Lucent Technologies, Bell Laboratories
6 :     *
7 :     * Author: Matthias Blume (blume@cs.princeton.edu)
8 :     *)
9 :     structure AutoDir :> sig
10 :     val openBinOut : string -> BinIO.outstream
11 :     val openTextOut : string -> TextIO.outstream
12 : blume 678 val makeDirs : string -> unit
13 : blume 354 end = struct
14 :    
15 :     structure P = OS.Path
16 :     structure F = OS.FileSys
17 :    
18 :     fun fileExists n = F.access (n, []) handle _ => false
19 :    
20 : blume 678 fun openEither fileopener p = let
21 : blume 452 fun mkDir d =
22 :     F.mkDir d handle exn => (if fileExists d then () else raise exn)
23 : blume 354 fun generic (maker, pmaker, p) =
24 :     maker p
25 :     handle exn => let
26 : blume 376 val dir = P.dir p
27 : blume 354 in
28 : blume 452 (* If the parent dir exists, then we must consider
29 :     * these cases:
30 :     * - non-parallel: we should signal an error
31 :     * - parallel: somebody else may have made this dir
32 :     * in the meantime, so we should try again
33 :     * Both cases can be handled by simply calling maker
34 :     * again. (It will fail in the non-parallel case, but
35 :     * that's actually what we want.) *)
36 :     if dir = "" orelse fileExists dir then maker p
37 : blume 354 else (pmaker dir; maker p)
38 :     end
39 : blume 376 fun makedirs dir = generic (mkDir, makedirs, dir)
40 : blume 354 fun advertisemakedirs dir =
41 : blume 772 (Say.vsay ["[creating directory ", dir, "]\n"];
42 : blume 354 makedirs dir)
43 :     in
44 : blume 678 generic (fileopener, advertisemakedirs, p)
45 : blume 354 end
46 :    
47 : blume 678 (* In the open-for-output case we first get rid of the file if it
48 : blume 772 * already existed... *)
49 : blume 678 fun openOut fileopener =
50 :     openEither (fn n => (if fileExists n then (F.remove n handle _ => ())
51 :     else ();
52 :     fileopener n))
53 :    
54 : blume 354 val openTextOut = openOut TextIO.openOut
55 :     val openBinOut = openOut BinIO.openOut
56 : blume 678
57 :     (* makeDirs is supposed to make all directories leading up to a
58 :     * given file. The file itself is supposed to be left alone if
59 :     * it already existed. The trick here is to (ab)use our openOut
60 :     * function with a "maker" parameter set to "BinIO.openIn". This
61 :     * is pretty hack-ish, but it allows us to reuse the existing logic. *)
62 :     local
63 :     exception NonexistentFile
64 :     fun boi f = BinIO.openIn f handle _ => raise NonexistentFile
65 :     in
66 :     fun makeDirs f = BinIO.closeIn (openEither boi f)
67 :     handle NonexistentFile => ()
68 :     end
69 : blume 354 end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0