-*- Mode: Modula-3 -*-
*
* For information about this program, contact Blair MacIntyre
* (bm@cs.columbia.edu) or Steven Feiner (feiner@cs.columbia.edu)
* at the Computer Science Dept., Columbia University,
* 1214 Amsterdam Ave. Mailstop 0401, New York, NY, 10027.
*
* Copyright (C) 1995, 1996 by The Trustees of Columbia University in the
* City of New York. Blair MacIntyre, Computer Science Department.
*
* Author : Blair MacIntyre
* Created On : Wed Mar 12 12:17:06 1997
* Last Modified By: Blair MacIntyre
* Last Modified On: Sat May 17 14:45:02 1997
* Update Count : 4
*
* $Source: /usr/cvs/cm3/m3-obliq/obliqlibemb/src/ObLoader.m3,v $
* $Date: 2001-01-24 21:52:38 $
* $Author: wagner $
* $Revision: 1.1.1.1 $
*
* $Log: ObLoader.m3,v $
* Revision 1.1.1.1 2001-01-24 21:52:38 wagner
* import of Critical Mass sources of release 5.1
*
* Revision 1.3 1997/05/25 20:40:53 bm
* small fix.
*
* Revision 1.2 1997/03/12 21:34:59 bm
* Moved sharedobj from coterie
*
*
* HISTORY
MODULE ObLoader;
IMPORT Bundle, ObLibOnline, ObValue, Obliq, ObliqParser, SynScan, SynWr,
SynParse, TextRd, ObCommand, Text, TextWr, RdCopy, Pathname,
OSError, FileRd, Rd, Fmt, Wr, Thread, Process, TextSeq;
REVEAL
T = Public BRANDED OBJECT
parser : SynParse.T;
env : Obliq.Env := NIL;
alt : T := NIL;
METHODS
getRd(name: TEXT): Rd.T;
getText(name: TEXT): TEXT;
OVERRIDES
get := Get;
load := Load;
help := Help;
END;
REVEAL
BundleT = BundlePublic BRANDED OBJECT
bundle : Bundle.T;
OVERRIDES
init := BundleInit;
getRd := BundleGetRd;
getText := BundleGetText;
END;
REVEAL
DirT = DirPublic BRANDED OBJECT
root : Pathname.Arcs;
OVERRIDES
init := DirInit;
getRd := DirGetRd;
getText := DirGetText;
END;
PROCEDURE Get (self : T; qualName : TEXT) : Obliq.Val =
BEGIN
ObliqParser.ReadFrom (self.parser, "", TextRd.New (qualName & ";"), TRUE);
TRY
RETURN Obliq.EvalPhrase (ObliqParser.ParsePhrase (self.parser),
self.env);
EXCEPT
| ObValue.Error (packet) =>
ObValue.ErrorMsg(SynWr.err, packet);
Process.Crash("Fatal error attempting to get '" & qualName &
"' in ObLoader.Get");
<*ASSERT FALSE*>
| ObValue.Exception (packet) =>
ObValue.ExceptionMsg(SynWr.err, packet);
Process.Crash("Fatal error attempting to get '" & qualName &
"' in ObLoader.Get");
<*ASSERT FALSE*>
| ObliqParser.Eof =>
Process.Crash("Parser.EOF error attempting to get '" & qualName &
"' in ObLoader.Get");
<*ASSERT FALSE*>
END;
END Get;
PROCEDURE Load (self : T; name : TEXT) =
BEGIN
TRY
WITH rd = self.getRd(name) DO
ObliqParser.ReadFrom (self.parser, "", rd, TRUE, TRUE);
END;
LOOP
TRY
SynScan.FirstPrompt (self.parser.Scanner());
WITH phrase = ObliqParser.ParsePhrase (self.parser) DO
EVAL ObliqParser.EvalPhrase (self.parser, phrase, self.env);
END;
EXCEPT
| ObliqParser.Eof => RETURN;
END;
END;
EXCEPT
| ObValue.Error (packet) =>
ObValue.ErrorMsg(SynWr.err, packet);
Process.Crash("Fatal error attempting to get '" & name &
"' in ObLoader.Load");
| ObValue.Exception (packet) =>
ObValue.ExceptionMsg(SynWr.err, packet);
Process.Crash("Fatal error attempting to get '" & name &
"' in ObLoader.Load");
END;
END Load;
PROCEDURE Help (self: T; cmd: ObCommand.T; arg, pkgname, m3name : TEXT) =
BEGIN
IF m3name = NIL THEN
m3name := pkgname;
END;
IF Text.Equal (arg, "!") THEN
SynWr.Text (SynWr.out,
" " & Fmt.Pad (pkgname, 18, ' ', Fmt.Align.Left) &
"(interface to the " & m3name & " module)\n");
ELSIF Text.Equal (arg, "?") THEN
WITH text = self.getText(m3name & ".hlp") DO
IF text # NIL THEN
SynWr.Text (SynWr.out, text);
END;
SynWr.NewLine (SynWr.out);
END;
ELSE
SynWr.Text(SynWr.out, "Command " & cmd.name & ": bad argument: " & arg);
SynWr.NewLine (SynWr.out);
END;
END Help;
PROCEDURE BundleInit (self : BundleT; bundle: Bundle.T; parent: T; alt: T) : T=
BEGIN
self.alt := alt;
IF parent # NIL THEN
self.env := parent.env;
ELSE
self.env := Obliq.EmptyEnv ();
END;
self.parser := ObliqParser.New (SynWr.out);
self.bundle := bundle;
ObLibOnline.RegisterScanner (self.parser.Scanner ());
RETURN self;
END BundleInit;
PROCEDURE BundleGetRd (self: BundleT; name : TEXT) : Rd.T =
BEGIN
RETURN TextRd.New (self.getText(name));
END BundleGetRd;
PROCEDURE BundleGetText (self: BundleT; name : TEXT) : TEXT =
VAR text: TEXT;
BEGIN
text := Bundle.Get (self.bundle, name);
IF text = NIL THEN
IF self.alt # NIL THEN
RETURN self.alt.getText (name);
END;
Process.Crash("Could not find load file '" & name & "'.");
END;
RETURN text;
END BundleGetText;
PROCEDURE DirInit (self : DirT; root: TEXT; parent: T; alt: T) : T =
BEGIN
self.alt := alt;
IF parent # NIL THEN
self.env := parent.env;
ELSE
self.env := Obliq.EmptyEnv ();
END;
self.parser := ObliqParser.New (SynWr.out);
TRY
self.root := Pathname.Decompose(root);
EXCEPT
| Pathname.Invalid =>
Process.Crash("Invalid Pathname '" & root & "'");
END;
ObLibOnline.RegisterScanner (self.parser.Scanner ());
RETURN self;
END DirInit;
PROCEDURE DirGetRd (self: DirT; name : TEXT) : Rd.T =
BEGIN
self.root.addhi(name);
TRY
WITH file = Pathname.Compose(self.root) DO
EVAL self.root.remhi();
TRY
RETURN FileRd.Open(file);
EXCEPT
| OSError.E =>
IF self.alt # NIL THEN
RETURN self.alt.getRd(name);
END;
Process.Crash("Error opening file '" & file & "'");
RETURN NIL; (* To shut up the compiler *)
END;
END;
EXCEPT
| Pathname.Invalid =>
Process.Crash("Invalid filename '" & name & "'");
RETURN NIL; (* To shut up the compiler *)
END;
END DirGetRd;
PROCEDURE DirGetText (self: DirT; name : TEXT) : TEXT =
BEGIN
TRY
WITH rd = self.getRd(name),
wr = TextWr.New() DO
EVAL RdCopy.ToWriter(rd, wr);
RETURN TextWr.ToText(wr);
END;
EXCEPT
| Rd.Failure, Thread.Alerted, Wr.Failure =>
Process.Crash("Error reading from file '" & name & "'");
RETURN NIL; (* To shut up the compiler *)
END;
END DirGetText;
PROCEDURE NewDirs(roots: TextSeq.T; parent: T := NIL; alt: T := NIL): T =
VAR root: T := NIL;
BEGIN
FOR i := roots.size()-1 TO 0 BY -1 DO
root := NEW(DirT).init(roots.get(i), parent, alt);
alt := root;
END;
RETURN root;
END NewDirs;
BEGIN
END ObLoader.