123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- MODULE CompilerInterface; (** AUTHOR "staubesv"; PURPOSE "Generic compiler interface"; *)
- (**
- * The idea of this module is to make it possible for client applications to use multiple different compilers.
- * Compiler can be retrieve by name, file extension of filename.
- *)
- IMPORT
- KernelLog, Streams, Commands, Strings, Texts, Diagnostics;
- CONST
- ModuleName = "CompilerInterface";
- TYPE
- Name* = ARRAY 16 OF CHAR;
- Description* = ARRAY 128 OF CHAR;
- FileExtension* = ARRAY 16 OF CHAR;
- CompileTextProc* = PROCEDURE {DELEGATE} (t : Texts.Text; CONST source: ARRAY OF CHAR; pos: LONGINT; CONST pc,opt: ARRAY OF CHAR;
- log: Streams.Writer; diagnostics : Diagnostics.Diagnostics; VAR error: BOOLEAN);
- TYPE
- Compiler* = OBJECT
- VAR
- name- : Name;
- description- : Description;
- fileExtension- : FileExtension;
- compileText : CompileTextProc;
- next : Compiler;
- PROCEDURE CompileText*(t : Texts.Text; CONST source: ARRAY OF CHAR; pos: LONGINT; CONST pc,opt: ARRAY OF CHAR;
- log: Streams.Writer; diagnostics : Diagnostics.Diagnostics; VAR error: BOOLEAN);
- VAR
- trap : BOOLEAN;
- BEGIN
- trap := FALSE;
- IF (compileText # NIL) THEN
- compileText(t, source, pos, pc, opt, log, diagnostics, error);
- ELSIF (diagnostics # NIL) THEN
- diagnostics.Error(source, Streams.Invalid, "Text compile procedure not set");
- END;
- FINALLY
- IF trap THEN (* trap will be set in case a trap occurs in the block above *)
- error := TRUE;
- diagnostics.Error(source, Streams.Invalid, "COMPILER TRAPPED");
- log.String("COMPILER TRAPPED!!!"); log.Update;
- END;
- END CompileText;
- PROCEDURE Show(out : Streams.Writer);
- BEGIN
- out.String(name);
- out.String(" ("); out.String(description); out.String(") ");
- out.String("File Extension: "); out.String(fileExtension);
- out.Ln;
- END Show;
- PROCEDURE &Init*(
- CONST name : Name;
- CONST description : Description;
- CONST fileExtension : FileExtension;
- compileText : CompileTextProc
- );
- BEGIN
- SELF.name := name; SELF.description := description; SELF.fileExtension := fileExtension;
- SELF.compileText := compileText;
- END Init;
- END Compiler;
- VAR
- compilers : Compiler;
- PROCEDURE FindCompilerByName(CONST name : ARRAY OF CHAR) : Compiler;
- VAR c : Compiler;
- BEGIN
- c := compilers;
- WHILE (c # NIL) & (c.name # name) DO c := c.next; END;
- RETURN c;
- END FindCompilerByName;
- (** Get compiler object for a specific file extension. Returns NIL if no appropriate compiler found. *)
- PROCEDURE GetCompiler*(fileExtension : FileExtension) : Compiler;
- VAR c : Compiler;
- BEGIN {EXCLUSIVE}
- Strings.UpperCase(fileExtension);
- c := compilers;
- WHILE (c # NIL) & (c.fileExtension # fileExtension) DO c := c.next; END;
- RETURN c;
- END GetCompiler;
- PROCEDURE GetCompilerByName*(CONST name : ARRAY OF CHAR) : Compiler;
- BEGIN {EXCLUSIVE}
- RETURN FindCompilerByName(name);
- END GetCompilerByName;
- (** Get compiler object for a filename. A compiler is appropriate for a given file name
- if the file extension the compiler requires is part of the filename, e.g. Module.Mod.Bak for the file extension .Mod
- Returns NIL if no appropriate compiler found *)
- PROCEDURE GetCompilerByFilename*(filename : ARRAY OF CHAR) : Compiler;
- VAR c : Compiler; pos : LONGINT;
- BEGIN {EXCLUSIVE}
- Strings.UpperCase(filename);
- c := compilers;
- LOOP
- IF (c = NIL) THEN EXIT; END;
- pos := Strings.Pos(c.fileExtension, filename);
- IF (pos > 0) & (filename[pos-1] = ".") THEN
- EXIT;
- END;
- c := c.next;
- END;
- RETURN c;
- END GetCompilerByFilename;
- (** Show all registered compilers *)
- PROCEDURE Show*(context : Commands.Context);
- VAR c : Compiler;
- BEGIN {EXCLUSIVE}
- IF (compilers = NIL) THEN
- context.out.String("No compilers registered."); context.out.Ln;
- ELSE
- c := compilers;
- WHILE (c # NIL) DO c.Show(context.out); c := c.next; END;
- END;
- END Show;
- (** Register a compiler. The name of the compiler must be unique. *)
- PROCEDURE Register*(
- CONST name : Name;
- CONST description : Description;
- fileExtension : FileExtension;
- compileText : CompileTextProc);
- VAR
- c : Compiler;
- BEGIN {EXCLUSIVE}
- ASSERT(compileText # NIL);
- c := FindCompilerByName(name);
- IF (c = NIL) THEN
- Strings.UpperCase(fileExtension);
- NEW(c, name, description, fileExtension, compileText);
- c.next := compilers; compilers := c;
- ELSE
- KernelLog.Enter;
- KernelLog.String(ModuleName); KernelLog.String(": Cannot register compiler '");
- KernelLog.String(name); KernelLog.String("': Name is already in use.");
- KernelLog.Exit;
- END;
- END Register;
- (** Unregister a compiler *)
- PROCEDURE Unregister*(CONST name : Name);
- VAR prev : Compiler;
- BEGIN {EXCLUSIVE}
- IF (compilers = NIL) THEN RETURN; END;
- IF (compilers.name = name) THEN
- compilers := compilers.next;
- ELSE
- prev := compilers;
- WHILE(prev.next # NIL) & (prev.next.name # name) DO prev := prev.next; END;
- IF (prev.next # NIL) THEN
- prev.next := prev.next.next;
- END;
- END;
- END Unregister;
- BEGIN
- compilers := NIL;
- END CompilerInterface.
- CompilerInterface.Show ~
- System.Free CompilerInterface ~
|