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/main/cm-boot.sml
ViewVC logotype

Annotation of /sml/trunk/src/cm/main/cm-boot.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 651 - (view) (download)

1 : blume 375 (*
2 :     * This is the module that actually puts together the contents of the
3 : blume 587 * structure CM that people find in smlnj/cm/full.cm. A "minimal" structure
4 : blume 375 * CM is defined in CmHook, but it needs to be initialized at bootstrap
5 : blume 495 * time.
6 : blume 375 *
7 :     * Copyright (c) 1999 by Lucent Bell Laboratories
8 :     *
9 :     * author: Matthias Blume (blume@cs.princeton.edu)
10 :     *)
11 :     functor LinkCM (structure HostMachDepVC : MACHDEP_VC) = struct
12 :    
13 :     datatype envrequest = AUTOLOAD | BARE
14 :    
15 :     local
16 :     structure E = GenericVC.Environment
17 : blume 569 structure DE = DynamicEnv
18 : blume 375 structure SE = GenericVC.StaticEnv
19 :     structure ER = GenericVC.EnvRef
20 :     structure S = GenericVC.Symbol
21 :     structure EM = GenericVC.ErrorMsg
22 :     structure BF = HostMachDepVC.Binfile
23 : blume 380 structure P = OS.Path
24 :     structure F = OS.FileSys
25 : blume 451 structure DG = DependencyGraph
26 : blume 587 structure GG = GroupGraph
27 : blume 375
28 :     val os = SMLofNJ.SysInfo.getOSKind ()
29 : blume 464 val my_archos =
30 :     concat [HostMachDepVC.architecture, "-", FilenamePolicy.kind2name os]
31 : blume 375
32 :     structure SSV =
33 :     SpecificSymValFn (structure MachDepVC = HostMachDepVC
34 :     val os = os)
35 :    
36 :     val emptydyn = E.dynamicPart E.emptyEnv
37 : blume 569 val system_values = ref (SrcPathMap.empty: E.dynenv SrcPathMap.map)
38 : blume 375
39 : blume 588 structure StabModmap = StabModmapFn ()
40 :    
41 : blume 400 structure Compile =
42 : blume 448 CompileFn (structure MachDepVC = HostMachDepVC
43 : blume 588 structure StabModmap = StabModmap
44 : blume 464 val compile_there = Servers.compile o SrcPath.descr)
45 : blume 400
46 : blume 537 structure BFC =
47 :     BfcFn (structure MachDepVC = HostMachDepVC)
48 :    
49 : blume 399 structure Link =
50 :     LinkFn (structure MachDepVC = HostMachDepVC
51 : blume 537 structure BFC = BFC
52 : blume 399 val system_values = system_values)
53 : blume 375
54 :     structure AutoLoad = AutoLoadFn
55 : blume 399 (structure C = Compile
56 : blume 403 structure L = Link
57 :     structure BFC = BFC)
58 : blume 375
59 : blume 537 val mkBootList = #l o MkBootList.group (fn p => p)
60 :    
61 : blume 587 fun init_servers (GG.GROUP { grouppath, ... }) =
62 : blume 464 Servers.cm { archos = my_archos, project = SrcPath.descr grouppath }
63 : blume 587 | init_servers GG.ERRORGROUP = ()
64 : blume 456
65 : blume 399 fun recomp_runner gp g = let
66 : blume 456 val _ = init_servers g
67 : blume 403 fun store _ = ()
68 :     val { group, ... } = Compile.newTraversal (Link.evict, store, g)
69 : blume 399 in
70 : blume 450 isSome (Servers.withServers (fn () => group gp))
71 :     before Link.cleanup gp
72 : blume 399 end
73 : blume 375
74 :     (* This function combines the actions of "recompile" and "exec".
75 :     * When successful, it combines the results (thus forming a full
76 :     * environment) and adds it to the toplevel environment. *)
77 : blume 587 fun make_runner _ _ GG.ERRORGROUP = false
78 :     | make_runner add_bindings gp (g as GG.GROUP grec) = let
79 :     val { required = rq, ... } = grec
80 :     val { store, get } = BFC.new ()
81 :     val _ = init_servers g
82 :     val { group = c_group, ... } =
83 :     Compile.newTraversal (Link.evict, store, g)
84 :     val { group = l_group, ... } = Link.newTraversal (g, get)
85 :     in
86 :     case Servers.withServers (fn () => c_group gp) of
87 :     NONE => false
88 :     | SOME { stat, sym} =>
89 : blume 537 (* Before executing the code, we announce the privileges
90 : blume 399 * that are being invoked. (For the time being, we assume
91 :     * that everybody has every conceivable privilege, but at
92 :     * the very least we announce which ones are being made
93 :     * use of.) *)
94 : blume 400 (Link.cleanup gp;
95 : blume 399 if StringSet.isEmpty rq then ()
96 :     else Say.say ("$Execute: required privileges are:\n" ::
97 :     map (fn s => (" " ^ s ^ "\n")) (StringSet.listItems rq));
98 :     case l_group gp of
99 : blume 375 NONE => false
100 : blume 518 | SOME dyn =>
101 :     (if add_bindings then
102 :     let val delta = E.mkenv { static = stat,
103 :     symbolic = sym,
104 :     dynamic = dyn }
105 :     val base = #get ER.topLevel ()
106 : blume 587 val new = E.concatEnv (delta, base)
107 : blume 518 in
108 :     #set ER.topLevel new;
109 :     Say.vsay ["[New bindings added.]\n"]
110 :     end
111 :     else ();
112 :     true))
113 : blume 587 end
114 : blume 375
115 :     val al_greg = GroupReg.new ()
116 :    
117 :     (* Instantiate the stabilization mechanism. *)
118 :     structure Stabilize =
119 : blume 403 StabilizeFn (structure MachDepVC = HostMachDepVC
120 : blume 588 structure StabModmap = StabModmap
121 : blume 403 fun recomp gp g = let
122 :     val { store, get } = BFC.new ()
123 : blume 456 val _ = init_servers g
124 : blume 403 val { group, ... } =
125 :     Compile.newTraversal (Link.evict, store, g)
126 :     in
127 : blume 450 case Servers.withServers (fn () => group gp) of
128 : blume 403 NONE => NONE
129 :     | SOME _ => SOME get
130 :     end
131 :     val getII = Compile.getII)
132 : blume 375
133 :     (* Access to the stabilization mechanism is integrated into the
134 :     * parser. I'm not sure if this is the cleanest way, but it works
135 :     * well enough. *)
136 :     structure Parse = ParseFn (structure Stabilize = Stabilize
137 : blume 588 structure StabModmap = StabModmap
138 : blume 537 fun evictStale () =
139 :     (Compile.evictStale ();
140 :     Link.evictStale ())
141 : blume 375 val pending = AutoLoad.getPending)
142 :    
143 :     local
144 : blume 592 type kernelValues = { init_group : GG.group }
145 : blume 375
146 :     val fnpolicy = FilenamePolicy.colocate
147 :     { os = os, arch = HostMachDepVC.architecture }
148 :    
149 :     val theValues = ref (NONE: kernelValues option)
150 :    
151 :     in
152 : blume 645 val pcmode = PathConfig.new ()
153 :    
154 : blume 377 (* cancelling anchors cannot affect the order of existing paths
155 :     * (it may invalidate some paths; but all other ones stay as
156 :     * they are) *)
157 : blume 569 fun setAnchor a NONE = PathConfig.cancel (pcmode, a)
158 :     | setAnchor a (SOME s) = (PathConfig.set (pcmode, a, s);
159 :     SrcPath.sync ())
160 : blume 377 (* same goes for reset because it just cancels all anchors... *)
161 : blume 375 fun resetPathConfig () = PathConfig.reset pcmode
162 : blume 569 (* get the current binding for an anchor *)
163 :     fun getAnchor a () =
164 :     Option.map (fn f => f ()) (PathConfig.configAnchor pcmode a)
165 : blume 375
166 : blume 525 fun mkStdSrcPath s =
167 :     SrcPath.standard pcmode { context = SrcPath.cwdContext (),
168 : blume 643 spec = s,
169 :     err = fn s => raise Fail s }
170 : blume 525
171 : blume 479 fun getPending () = let
172 : blume 375 fun one (s, _) = let
173 :     val nss = Symbol.nameSpaceToString (Symbol.nameSpace s)
174 :     val n = Symbol.name s
175 :     in
176 : blume 479 concat [" ", nss, " ", n, "\n"]
177 : blume 375 end
178 :     in
179 : blume 479 map one (SymbolMap.listItemsi (AutoLoad.getPending ()))
180 : blume 375 end
181 :    
182 :     fun initPaths () = let
183 : blume 433 val lpcth = #get StdConfig.local_pathconfig ()
184 : blume 375 val p = case lpcth () of
185 :     NONE => []
186 :     | SOME f => [f]
187 : blume 433 val p = #get StdConfig.pathcfgspec () :: p
188 : blume 375 fun processOne f = PathConfig.processSpecFile (pcmode, f)
189 :     handle _ => ()
190 :     in
191 :     app processOne p
192 :     end
193 :    
194 : blume 537 fun getTheValues () = valOf (!theValues)
195 :     handle Option => raise Fail "CMBoot: theParam not initialized"
196 :    
197 : blume 375 fun param () = let
198 : blume 537 val v = getTheValues ()
199 : blume 375 in
200 : blume 537 { fnpolicy = fnpolicy,
201 : blume 375 pcmode = pcmode,
202 : blume 433 symval = SSV.symval,
203 : blume 592 keep_going = #get StdConfig.keep_going () }
204 : blume 375 end
205 :    
206 : blume 537 val init_group = #init_group o getTheValues
207 :    
208 : blume 507 fun dropPickles () =
209 :     if #get StdConfig.conserve_memory () then
210 :     Parse.dropPickles ()
211 :     else ()
212 :    
213 : blume 537 fun parse_arg (gr, sflag, p) =
214 :     { load_plugin = load_plugin, gr = gr, param = param (),
215 : blume 569 stabflag = sflag, group = p,
216 :     init_group = init_group (), paranoid = false }
217 : blume 537
218 :     and autoload s = let
219 : blume 525 val p = mkStdSrcPath s
220 : blume 375 in
221 : blume 537 (case Parse.parse (parse_arg (al_greg, NONE, p)) of
222 : blume 505 NONE => false
223 :     | SOME (g, _) =>
224 : blume 537 (AutoLoad.register (GenericVC.EnvRef.topLevel, g);
225 :     true))
226 : blume 507 before dropPickles ()
227 : blume 375 end
228 :    
229 : blume 578 and run mkSrcPath sflag f s = let
230 :     val p = mkSrcPath s
231 : blume 537 val gr = GroupReg.new ()
232 : blume 375 in
233 : blume 537 (case Parse.parse (parse_arg (gr, sflag, p)) of
234 : blume 505 NONE => false
235 :     | SOME (g, gp) => f gp g)
236 : blume 507 before dropPickles ()
237 : blume 375 end
238 :    
239 : blume 578 and load_plugin context x = let
240 : blume 518 val _ = Say.vsay ["[attempting to load plugin ", x, "]\n"]
241 : blume 643 fun badname s = Say.say ["[bad plugin name: ", s, "]\n"]
242 : blume 578 fun mkSrcPath s =
243 : blume 643 SrcPath.standard pcmode { context = context,
244 :     spec = s, err = badname }
245 : blume 518 val success =
246 : blume 578 run mkSrcPath NONE (make_runner false) x handle _ => false
247 : blume 518 in
248 :     if success then
249 :     Say.vsay ["[plugin ", x, " loaded successfully]\n"]
250 :     else
251 :     Say.vsay ["[unable to load plugin ", x, "]\n"];
252 :     success
253 :     end
254 :    
255 : blume 578 fun cwd_load_plugin x = load_plugin (SrcPath.cwdContext ()) x
256 :    
257 : blume 449 fun stabilize_runner gp g = true
258 :    
259 : blume 578 fun stabilize recursively =
260 :     run mkStdSrcPath (SOME recursively) stabilize_runner
261 :     val recomp = run mkStdSrcPath NONE recomp_runner
262 :     val make = run mkStdSrcPath NONE (make_runner true)
263 : blume 449
264 : blume 642
265 :     fun sources archos group = let
266 :     val policy =
267 :     case archos of
268 :     NONE => fnpolicy
269 :     | SOME ao => FilenamePolicy.colocate_generic ao
270 :     fun sourcesOf ((p, g), (v, a)) =
271 :     if SrcPathSet.member (v, p) then (v, a)
272 :     else
273 :     let val v = SrcPathSet.add (v, p)
274 :     in case g of
275 :     GG.ERRORGROUP => (v, a)
276 :     | GG.GROUP { kind, sources, ... } => let
277 :     fun add (p, x, a) =
278 :     StringMap.insert
279 :     (a, SrcPath.osstring p, x)
280 :     val a = SrcPathMap.foldli add a sources
281 :     fun sg subgroups =
282 :     foldl sourcesOf (v, a) subgroups
283 :     in
284 :     case kind of
285 :     GG.LIB { kind, version } =>
286 :     (case kind of
287 :     GG.STABLE _ => let
288 :     val file = SrcPath.osstring p
289 :     val (a, x) =
290 :     StringMap.remove (a, file)
291 :     val sfile =
292 :     FilenamePolicy.mkStableName
293 :     policy (p, version)
294 :     in
295 :     (v,
296 :     StringMap.insert (a, sfile, x))
297 :     end
298 :     | GG.DEVELOPED d => sg (#subgroups d))
299 :     | GG.NOLIB n => sg (#subgroups n)
300 :     end
301 :     end
302 : blume 632 val p = mkStdSrcPath group
303 :     val gr = GroupReg.new ()
304 :     in
305 :     (case Parse.parse (parse_arg (gr, NONE, p)) of
306 : blume 642 SOME (g, _) => let
307 :     val (_, sm) =
308 :     sourcesOf ((p, g),
309 :     (SrcPathSet.empty,
310 :     StringMap.singleton
311 :     (SrcPath.osstring p,
312 :     { class = "cm",
313 :     derived = false })))
314 :     fun add (s, { class, derived }, l) =
315 :     { file = s, class = class, derived = derived } :: l
316 : blume 632 in
317 : blume 642 SOME (StringMap.foldli add [] sm)
318 :     end
319 :     | _ => NONE)
320 : blume 632 before dropPickles ()
321 :     end
322 :    
323 : blume 537 (* I would have liked to express this using "run", but "run"
324 :     * thinks it has to return a bool... *)
325 :     fun mk_standalone sflag s = let
326 :     val p = mkStdSrcPath s
327 :     val gr = GroupReg.new ()
328 :     in
329 :     (case Parse.parse (parse_arg (gr, sflag, p)) of
330 :     NONE => NONE
331 :     | SOME (g, gp) =>
332 :     if isSome sflag orelse recomp_runner gp g then
333 :     SOME (mkBootList g)
334 :     else NONE)
335 :     before dropPickles ()
336 :     end
337 :    
338 : blume 518 fun slave () = let
339 : blume 537 val gr = GroupReg.new ()
340 :     fun parse p = Parse.parse (parse_arg (gr, NONE, p))
341 : blume 518 in
342 : blume 480 Slave.slave { pcmode = pcmode,
343 : blume 518 parse = parse,
344 : blume 480 my_archos = my_archos,
345 :     sbtrav = Compile.newSbnodeTraversal,
346 :     make = make }
347 : blume 518 end
348 : blume 456
349 : blume 518 fun al_ginfo () = { param = param (),
350 :     groupreg = al_greg,
351 :     errcons = EM.defaultConsumer () }
352 :    
353 :     val al_manager =
354 :     AutoLoad.mkManager { get_ginfo = al_ginfo,
355 :     dropPickles = dropPickles }
356 :    
357 :     fun al_manager' (ast, _, ter) = al_manager (ast, ter)
358 :    
359 : blume 375 fun reset () =
360 : blume 399 (Compile.reset ();
361 :     Link.reset ();
362 : blume 375 AutoLoad.reset ();
363 :     Parse.reset ();
364 : blume 588 SmlInfo.reset ();
365 :     StabModmap.reset ())
366 : blume 375
367 : blume 569 fun initTheValues (bootdir, de, er, autoload_postprocess) = let
368 : blume 375 val _ = let
369 :     fun listDir ds = let
370 :     fun loop l =
371 : blume 380 case F.readDir ds of
372 : blume 375 "" => l
373 :     | x => loop (x :: l)
374 :     in
375 :     loop []
376 :     end
377 :     val fileList = SafeIO.perform
378 : blume 380 { openIt = fn () => F.openDir bootdir,
379 :     closeIt = F.closeDir,
380 : blume 375 work = listDir,
381 : blume 459 cleanup = fn _ => () }
382 : blume 380 fun isDir x = F.isDir x handle _ => false
383 : blume 375 fun subDir x = let
384 : blume 380 val d = P.concat (bootdir, x)
385 : blume 375 in
386 :     if isDir d then SOME (x, d) else NONE
387 :     end
388 :     val pairList = List.mapPartial subDir fileList
389 :     in
390 :     app (fn (x, d) => PathConfig.set (pcmode, x, d)) pairList
391 :     end
392 : blume 569
393 :     val pidmapfile = P.concat (bootdir, BtNames.pidmap)
394 :     fun readpidmap s = let
395 :     fun loop m = let
396 :     fun enter (d, pids) = let
397 :     fun enter1 (hexp, e) =
398 :     case GenericVC.PersStamps.fromHex hexp of
399 :     SOME p => (DE.bind (p, DE.look de p, e)
400 :     handle DE.Unbound => e)
401 :     | NONE => e
402 :     in
403 :     SrcPathMap.insert (m, SrcPath.fromDescr pcmode d,
404 :     foldl enter1 emptydyn pids)
405 :     end
406 :     in
407 :     case TextIO.inputLine s of
408 :     "" => m
409 :     | line => (case String.tokens Char.isSpace line of
410 :     d :: pids => loop (enter (d, pids))
411 :     | _ => loop m)
412 :     end
413 :     in
414 :     system_values := loop SrcPathMap.empty
415 :     end
416 :    
417 :     val _ =
418 :     SafeIO.perform { openIt = fn () => TextIO.openIn pidmapfile,
419 :     closeIt = TextIO.closeIn,
420 :     work = readpidmap,
421 :     cleanup = fn _ => () }
422 :    
423 : blume 525 val initgspec = mkStdSrcPath BtNames.initgspec
424 : blume 537 val ginfo = { param = { fnpolicy = fnpolicy,
425 : blume 375 pcmode = pcmode,
426 : blume 433 symval = SSV.symval,
427 : blume 592 keep_going = false },
428 : blume 375 groupreg = GroupReg.new (),
429 :     errcons = EM.defaultConsumer () }
430 : blume 537 fun loadInitGroup () =
431 :     Stabilize.loadStable ginfo
432 :     { getGroup = fn _ => raise Fail "CMBoot: initial getGroup",
433 :     anyerrors = ref false }
434 : blume 632 (initgspec, NONE)
435 : blume 375 in
436 : blume 537 case loadInitGroup () of
437 :     NONE => raise Fail "CMBoot: unable to load init group"
438 :     | SOME init_group => let
439 :     val _ = Compile.reset ()
440 :     val _ = Link.reset ()
441 : blume 375
442 : blume 537 val { exports = ctm, ... } =
443 :     Compile.newTraversal (fn _ => fn _ => (),
444 :     fn _ => (),
445 :     init_group)
446 :     val { exports = ltm, ... } = Link.newTraversal
447 :     (init_group, fn _ => raise Fail "init: get bfc?")
448 :    
449 :     fun getSymTrav (tr_m, sy) =
450 :     case SymbolMap.find (tr_m, sy) of
451 :     NONE => raise Fail "init: bogus init group (1)"
452 :     | SOME tr => tr
453 :    
454 : blume 592 val perv_ct = getSymTrav (ctm, PervAccess.pervStrSym)
455 :     val perv_lt = getSymTrav (ltm, PervAccess.pervStrSym)
456 : blume 537
457 :     fun doTrav t =
458 :     case t ginfo of
459 :     SOME r => r
460 :     | NONE => raise Fail "init: bogus init group (2)"
461 :    
462 :     val { stat = pervstat, sym = pervsym } = doTrav perv_ct
463 :     val pervdyn = doTrav perv_lt
464 :    
465 :     val pervasive = E.mkenv { static = pervstat,
466 :     symbolic = pervsym,
467 :     dynamic = pervdyn }
468 :    
469 : blume 495 fun bare_autoload x =
470 :     (Say.say
471 :     ["!* ", x,
472 :     ": \"autoload\" not available, using \"make\"\n"];
473 :     make x)
474 :     val bare_preload =
475 :     Preload.preload { make = make,
476 :     autoload = bare_autoload }
477 :     val standard_preload =
478 :     Preload.preload { make = make, autoload = autoload }
479 : blume 375 in
480 : blume 592 #set ER.pervasive pervasive;
481 : blume 587 #set ER.topLevel E.emptyEnv;
482 : blume 592 theValues := SOME { init_group = init_group };
483 : blume 375 case er of
484 :     BARE =>
485 : blume 495 (bare_preload BtNames.bare_preloads;
486 : blume 569 system_values := SrcPathMap.empty;
487 : blume 495 NONE)
488 : blume 375 | AUTOLOAD =>
489 :     (HostMachDepVC.Interact.installCompManager
490 :     (SOME al_manager');
491 : blume 495 standard_preload BtNames.standard_preloads;
492 : blume 375 CmHook.init
493 :     { stabilize = stabilize,
494 :     recomp = recomp,
495 :     make = make,
496 : blume 495 autoload = autoload };
497 : blume 507 (* unconditionally drop all library pickles *)
498 :     Parse.dropPickles ();
499 : blume 495 SOME (autoload_postprocess ()))
500 : blume 375 end
501 :     end
502 :     end
503 :     in
504 : blume 495 fun init (bootdir, de, er) = let
505 :     fun procCmdLine () = let
506 :     val autoload = ignore o autoload
507 :     val make = ignore o make
508 :     fun p (f, ("sml" | "sig"), mk) = HostMachDepVC.Interact.useFile f
509 :     | p (f, "cm", mk) = mk f
510 :     | p (f, e, mk) = Say.say ["!* unable to process `", f,
511 :     "' (unknown extension `", e, "')\n"]
512 :     fun arg ("-a", _) = autoload
513 :     | arg ("-m", _) = make
514 :     | arg (f, mk) =
515 :     (p (f,
516 :     String.map Char.toLower (getOpt (OS.Path.ext f, "<none>")),
517 :     mk);
518 :     mk)
519 :     in
520 :     case SMLofNJ.getArgs () of
521 :     ["@CMslave"] => (#set StdConfig.verbose false; slave ())
522 :     | l => ignore (foldl arg autoload l)
523 :     end
524 : blume 448 in
525 : blume 569 initTheValues (bootdir, de, er,
526 :     fn () => (Cleanup.install initPaths;
527 :     procCmdLine))
528 : blume 448 end
529 : blume 479
530 :     structure CM :> CM = struct
531 :     type 'a controller = { get : unit -> 'a, set : 'a -> unit }
532 :    
533 :     structure Anchor = struct
534 : blume 569 fun anchor a = { get = getAnchor a, set = setAnchor a }
535 : blume 479 val reset = resetPathConfig
536 :     end
537 :    
538 :     structure Control = struct
539 :     val keep_going = StdConfig.keep_going
540 :     val verbose = StdConfig.verbose
541 :     val parse_caching = StdConfig.parse_caching
542 :     val warn_obsolete = StdConfig.warn_obsolete
543 :     val debug = StdConfig.debug
544 : blume 505 val conserve_memory = StdConfig.conserve_memory
545 : blume 643 val implicit_anchors = StdConfig.implicit_anchors
546 : blume 479 end
547 :    
548 :     structure Library = struct
549 :     type lib = SrcPath.t
550 :     val known = Parse.listLibs
551 :     val descr = SrcPath.descr
552 :     val osstring = SrcPath.osstring
553 :     val dismiss = Parse.dismissLib
554 : blume 632 fun unshare lib = (Link.unshare lib; dismiss lib)
555 : blume 479 end
556 :    
557 :     structure State = struct
558 :     val synchronize = SrcPath.sync
559 :     val reset = reset
560 :     val pending = getPending
561 :     end
562 :    
563 :     structure Server = struct
564 :     type server = Servers.server
565 :     fun start x = Servers.start x before SrcPath.invalidateCwd ()
566 :     val stop = Servers.stop
567 :     val kill = Servers.kill
568 :     val name = Servers.name
569 :     end
570 :    
571 :     val autoload = autoload
572 :     val make = make
573 :     val recomp = recomp
574 :     val stabilize = stabilize
575 :    
576 : blume 642 val sources = sources
577 : blume 632
578 : blume 479 val symval = SSV.symval
579 : blume 578 val load_plugin = cwd_load_plugin
580 : blume 537 val mk_standalone = mk_standalone
581 : blume 479 end
582 : blume 525
583 : blume 578 structure Tools = ToolsFn (val load_plugin = cwd_load_plugin
584 : blume 645 val pcmode = pcmode)
585 : blume 578
586 :     val load_plugin = load_plugin
587 : blume 375 end
588 :     end

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