MODULE---------------------------------------------------------- internal ---; IMPORT FS, M3File, M3Timers, OSError, Params, Process, Text, Thread, Wr; IMPORT Arg, M3Build, M3Options, M3Path, Msg, Utils, TextSeq, TextTextTbl; IMPORT MxConfig; IMPORT Dirs, Version; TYPE NK = M3Path.Kind; MM = M3Options.Mode; CONST ModeName = ARRAY MM OF TEXT { "-build", "-clean", "-ship", "-find", "-depend", "-realclean" }; ModeFlag = ARRAY MM OF TEXT { "_all", "_clean", "_ship", "_find", "_depend", "_realclean" }; TYPE State = RECORD args : Arg.List := NIL; wr : Wr.T := NIL; keep_files : BOOLEAN := FALSE; use_overrides : BOOLEAN := FALSE; mode_set : BOOLEAN := FALSE; found_work : BOOLEAN := FALSE; prepend_files : TextSeq.T; append_files : TextSeq.T; END; PROCEDURE Makefile Build (src_dir: TEXT): TEXT = CONST Makefile = "m3make.args"; VAR s: State; src_makefile := M3Path.New (src_dir, "m3makefile"); src_overrides := M3Path.New (src_dir, "m3overrides"); PROCEDURE Emit (wr: Wr.T) RAISES {Wr.Failure, Thread.Alerted} = BEGIN s.wr := wr; Out (wr, "set_config_options ()"); Out (wr, "readonly ", ModeFlag [M3Options.major_mode], " = TRUE % cm3 ", ModeName [M3Options.major_mode]); CASE M3Options.major_mode OF | MM.Find => Out (wr, "M3_FIND_UNITS = []") | MM.Build, MM.Clean, MM.RealClean, MM.Ship, MM.Depend => (* skip *) END; ConvertArgList (s); CASE M3Options.major_mode OF | MM.Build => Out (wr, "M3_MODE = ", "\"build\""); | MM.Clean => Out (wr, "M3_MODE = ", "\"clean\""); | MM.Find => Out (wr, "M3_MODE = ", "\"find\""); | MM.Depend => Out (wr, "M3_MODE = ", "\"depend\""); | MM.Ship => Out (wr, "M3_MODE = ", "\"ship\""); | MM.RealClean => Out (wr, "M3_MODE = ", "\"realclean\""); ELSE Out (wr, "M3_MODE = ", "\"other\""); END; CASE M3Options.major_mode OF | MM.Build, MM.Clean, MM.Find, MM.Depend => IncludeOverrides (s, src_overrides); FOR i := 0 TO s.prepend_files.size() - 1 DO IncludeFile (s, s.prepend_files.get(i)); END; IncludeMakefile (s, src_makefile, src_dir); FOR i := 0 TO s.append_files.size() - 1 DO IncludeFile (s, s.append_files.get(i)); END; | MM.Ship => IF M3File.IsReadable (".M3OVERRIDES") THEN Msg.Out ("package was built with overrides, not shipping.", Wr.EOL); ELSIF NOT M3File.IsReadable (".M3SHIP") THEN Msg.Out ("missing \".M3SHIP\" file, build the package first.", Wr.EOL); ELSE Out (wr, "include (\".M3SHIP\")"); s.found_work := TRUE; END; | MM.RealClean => (* we don't bother to include anything since it will be erased soon *) END; END Emit; BEGIN Msg.Debug( "Build(", src_dir, ")", Wr.EOL ); s.args := Arg.NewList (); s.prepend_files := NEW(TextSeq.T).init(); s.append_files := NEW(TextSeq.T).init(); FOR i := 1 TO Params.Count - 1 DO Arg.Append (s.args, Params.Get (i)); END; Utils.WriteFile (Makefile, Emit, append := FALSE); IF s.found_work THEN IF NOT s.keep_files AND M3Options.major_mode # MM.RealClean THEN Utils.NoteTempFile (Makefile); END; RETURN Makefile; ELSE Msg.Out ("cm3: found nothing to build.", Wr.EOL); IF NOT s.keep_files THEN Utils.Remove (Makefile); END; RETURN NIL; END; END Build;
PROCEDURE----------------------------------------- pre-scan command line ---ConvertArgList (VAR s: State) RAISES {Wr.Failure, Thread.Alerted} = VAR len: INTEGER; arg: TEXT; noMoreOptions := FALSE; BEGIN WHILE (s.args.cnt > 0) DO arg := Arg.Pop (s.args); len := Text.Length (arg); IF (len < 1) THEN (* empty argument ignore *) ELSIF (Text.GetChar (arg, 0) # '-') OR (len < 2) OR noMoreOptions THEN NoteSourceFile (s, NIL, arg, cmd_line := TRUE); ELSIF Text.Equal (arg, "--") THEN noMoreOptions := TRUE; ELSIF NOT noMoreOptions THEN (* it's an option *) ConvertOption (s, arg, len); END; END; END ConvertArgList; PROCEDUREConvertOption (VAR s: State; arg: TEXT; arg_len: INTEGER) RAISES {Wr.Failure, Thread.Alerted} = VAR ok := FALSE; wr := s.wr; BEGIN IF Text.GetChar (arg, 1) = '-' THEN arg := Text.Sub (arg, 1); END; CASE Text.GetChar (arg, 1) OF | '?' => IF (arg_len = 2) THEN ok := TRUE; (* printed during the pre-scan *) END; | 'a' => IF (arg_len = 2) THEN Out (wr, "library (\"", GetArg (arg, s.args), "\")"); ok := TRUE; s.found_work := TRUE; ELSIF Text.Equal(arg, "-append") THEN ok := TRUE; WITH fn = GetArg (arg, s.args) DO s.append_files.addhi(fn); END; END; | 'A' => IF (arg_len = 2) THEN Out (wr, "M3_OPTIONS += \"-NoAsserts\""); ok := TRUE; END; | 'b' => IF Text.Equal (arg, "-boot") THEN Out (wr, "M3_BOOTSTRAP = TRUE"); ok := TRUE; ELSIF Text.Equal(arg, "-build") THEN ok := TRUE; (* mode set during the pre-scan *) END; | 'c' => IF (arg_len = 2) THEN Out (wr, "m3_compile_only ()"); ok := TRUE; s.found_work := TRUE; ELSIF Text.Equal (arg, "-commands") THEN Msg.SetLevel (Msg.Level.Commands); ok := TRUE; Out (wr, "m3_option (\"-commands\")"); ELSIF Text.Equal (arg, "-config") THEN ok := TRUE; (* printed during the pre-scan *) ELSIF Text.Equal (arg, "-console") THEN Out (wr, "M3_WINDOWS_GUI = FALSE"); ok := TRUE; ELSIF Text.Equal(arg, "-clean") THEN ok := TRUE; (* mode set during the pre-scan *) s.found_work := TRUE; END; | 'd' => IF Text.Equal(arg, "-debug") THEN Msg.SetLevel (Msg.Level.Debug); ok := TRUE; Out (wr, "m3_option (\"-debug\")"); ELSIF Text.Equal (arg, "-depend") THEN ok := TRUE; END; | 'D' => ProcessDefine (arg, wr); ok := TRUE; | 'f' => IF Text.Equal(arg, "-find") THEN ok := TRUE; (* mode set during the pre-scan *) s.found_work := TRUE; END; | 'F' => IF Text.Equal(arg, "-F") (* for backward compatibility *) OR Text.Equal(arg, "-FP") THEN ok := TRUE; WITH fn = GetArg (arg, s.args) DO s.prepend_files.addhi(fn); END; ELSIF Text.Equal(arg, "-FA") THEN ok := TRUE; WITH fn = GetArg (arg, s.args) DO s.append_files.addhi(fn); END; END; | 'g' => IF (arg_len = 2) THEN Out (wr, "m3_debug (TRUE)"); ok := TRUE; ELSIF Text.Equal(arg, "-gui") THEN Out (wr, "M3_WINDOWS_GUI = TRUE"); ok := TRUE; ELSIF Text.Equal(arg, "-gw") OR Text.Equal(arg, "-group-writable") THEN M3Build.groupWritable := TRUE; ok := TRUE; END; | 'h' => IF Text.Equal (arg, "-heap_stats") THEN M3Options.heap_stats := TRUE; ok := TRUE; ELSIF Text.Equal (arg, "-help") THEN ok := TRUE; (* printed during the pre-scan *) END; | 'k' => IF (arg_len = 2) OR Text.Equal (arg, "-keep") THEN Out (wr, "M3_KEEP_FILES = TRUE"); s.keep_files := TRUE; ok := TRUE; END; | 'l' => IF Text.Equal (arg, "-lazy") THEN Out (wr, "M3_LAZY_MODULE_INIT = TRUE"); ok := TRUE; ELSIF Text.Equal (arg, "-linkall") THEN Out (wr, "M3_LAZY_MODULE_INIT = FALSE"); ok := TRUE; END; | 'n' => IF Text.Equal (arg, "-no-m3ship-resolution") THEN M3Build.noM3ShipResolution := TRUE; ok := TRUE; END; | 'o' => IF (arg_len = 2) THEN Out (wr, "program (\"", GetArg (arg, s.args), "\")"); ok := TRUE; s.found_work := TRUE; ELSIF Text.Equal (arg, "-override") THEN s.use_overrides := TRUE; ok := TRUE; ELSIF Text.Equal (arg, "-once") THEN Out (wr, "M3_COMPILE_ONCE = TRUE"); ok := TRUE; END; | 'p' => IF Text.Equal(arg, "-pretend") OR Text.Equal(arg, "-profile") THEN ok := TRUE; ELSIF Text.Equal(arg, "-prepend") THEN ok := TRUE; WITH fn = GetArg (arg, s.args) DO s.prepend_files.addhi(fn); END; ELSIF Text.Equal (arg, "-pb") THEN Out (wr, "M3_PARALLEL_BACK = ", GetArg (arg, s.args)); ok := TRUE; END; | 'O' => IF (arg_len = 2) THEN Out (wr, "m3_optimize (TRUE)"); ok := TRUE; END; | 'r' => IF Text.Equal(arg, "-realclean") THEN ok := TRUE; (* mode set during the pre-scan *) s.found_work := TRUE; END; | 's' => IF Text.Equal (arg, "-silent") THEN Msg.SetLevel (Msg.Level.Silent); ok := TRUE; Out (wr, "m3_option (\"-silent\")"); ELSIF Text.Equal (arg, "-skiplink") THEN Out (wr, "M3_SKIP_LINK = TRUE"); ok := TRUE; ELSIF Text.Equal (arg, "-ship") THEN ok := TRUE; (* mode set during the pre-scan *) s.found_work := TRUE; END; | 't' => IF Text.Equal (arg, "-times") THEN M3Timers.Start (); ok := TRUE; ELSIF Text.Equal (arg, "-trace") THEN Out (wr, "TRACE_INSTR()"); ok := TRUE; END; | 'v' => IF Text.Equal (arg, "-verbose") THEN Msg.SetLevel (Msg.Level.Verbose); Out (wr, "m3_option (\"-verbose\")"); M3Timers.Start (); ok := TRUE; ELSIF Text.Equal (arg, "-version") THEN ok := TRUE; (* printed during the pre-scan *) END; | 'w' => IF Text.Equal (arg, "-why") THEN Msg.SetLevel (Msg.Level.Explain); ok := TRUE; Out (wr, "m3_option (\"-why\")"); ELSIF Text.Equal (arg, "-windows") THEN Out (wr, "M3_WINDOWS_GUI = TRUE"); ok := TRUE; ELSIF Text.Equal (arg, "-w0") THEN Out (wr, "M3_OPTIONS += \"-w0\""); ok := TRUE; ELSIF Text.Equal (arg, "-w1") THEN Out (wr, "M3_OPTIONS += \"-w1\""); ok := TRUE; ELSIF Text.Equal (arg, "-w2") THEN Out (wr, "M3_OPTIONS += \"-w2\""); ok := TRUE; ELSIF Text.Equal (arg, "-w3") THEN Out (wr, "M3_OPTIONS += \"-w3\""); ok := TRUE; END; | 'x' => IF (arg_len = 2) THEN s.use_overrides := TRUE; ok := TRUE; END; | 'Z' => IF (arg_len = 2) THEN Out (wr, "M3_COVERAGE = TRUE"); ok := TRUE; END; ELSE (* error *) END; IF (NOT ok) THEN Msg.UsageError ("unrecognized option \"", arg, "\"") END; END ConvertOption; PROCEDUREGetArg (arg: TEXT; rest: Arg.List): TEXT = BEGIN IF (rest.cnt <= 0) THEN Msg.UsageError ("missing argument to \"", arg, "\" option"); END; RETURN Arg.Pop (rest); END GetArg; PROCEDUREProcessDefine (arg: TEXT; wr: Wr.T) RAISES {Wr.Failure, Thread.Alerted} = VAR len := Text.Length (arg); eq: INTEGER; sym, val: TEXT; BEGIN IF (len <= 2) THEN Msg.UsageError ("missing argument to \"-D\" option"); RETURN; END; eq := Text.FindChar (arg, '='); IF (eq < 0) THEN (* -Dsymbol ==> symbol = TRUE *) Out (wr, Text.Sub (arg, 2), " = TRUE"); RETURN; END; sym := Text.Sub (arg, 2, eq-2); val := Text.Sub (arg, eq+1); len := Text.Length (val); IF (len = 0) THEN (* -Dsymbol= ==> symbol = "" *) Out (wr, sym, " = \"\""); ELSIF Text.GetChar (arg, 0) = '"' AND Text.GetChar (arg, len-1) = '"' THEN (* -Dsymbol="foo" ==> symbol = "foo" *) Out (wr, sym, " = ", val); ELSIF Text.Equal (val, "TRUE") OR Text.Equal (val, "FALSE") THEN Out (wr, sym, " = ", val); ELSE (* -Dsymbol=val ==> symbol = "val" *) Out (wr, sym, " = \"", val, "\""); END; END ProcessDefine; CONST SourceTag = ARRAY NK OF TEXT { NIL, (* unknown *) "interface", NIL, NIL, "import_obj", (* i3, ic, is, io *) "implementation", NIL, NIL, "import_obj", (* m3, mc, ms, mo *) "generic_interface", "generic_implementation", (* ig, mg *) "c_source", "h_source", "s_source", "import_obj", (* c, h, s, o *) "import_lib", "import_lib", NIL, (* m3lib, lib, m3x *) NIL, NIL, NIL (* pgm, mx, tmpl *) }; PROCEDURENoteSourceFile (VAR s: State; dir, name: TEXT; cmd_line: BOOLEAN) RAISES {Wr.Failure, Thread.Alerted} = VAR file := M3Path.New (dir, name); info := M3Path.Parse (file); tag : TEXT; BEGIN Msg.Debug (" file ", file, Wr.EOL); IF (M3Options.major_mode = MM.Find) AND (cmd_line) THEN Out (s.wr, "M3_FIND_UNITS += \"", M3Path.Join (NIL, info.base, info.kind), "\""); s.found_work := TRUE; RETURN; END; tag := SourceTag [info.kind]; IF (tag # NIL) THEN file := M3Path.Convert (M3Path.New (info.dir, info.base)); Out (s.wr, tag, " (\"", file, "\")"); s.found_work := TRUE; ELSE VisitSourceDir (s, file, cmd_line); END; END NoteSourceFile; VAR normalizedDerivedDir: TEXT := NIL; PROCEDUREVisitSourceDir (VAR s: State; dir: TEXT; cmd_line: BOOLEAN) RAISES {Wr.Failure, Thread.Alerted} = VAR iter: FS.Iterator; name: TEXT; normalizedDir: TEXT; BEGIN Msg.Debug ("--- dir ", dir, " ---", Wr.EOL); IF NOT M3File.IsDirectory (dir) THEN IF (cmd_line) THEN Msg.FatalError (NIL, "unsupported file type \"", dir, "\""); END; Msg.Verbose ("ignoring ", dir, " (not a directory)"); RETURN; END; IF normalizedDerivedDir = NIL THEN TRY normalizedDerivedDir := FS.GetAbsolutePathname(Dirs.derived); EXCEPT OSError.E (args) => Msg.FatalError (args, "unable to get absolute path for \"", Dirs.derived, "\""); END; END; TRY normalizedDir := FS.GetAbsolutePathname(dir); EXCEPT OSError.E (args) => Msg.FatalError (args, "unable to get absolute path for \"", dir, "\""); END; IF Text.Equal(normalizedDir, normalizedDerivedDir) THEN Msg.Verbose ("ignoring ", dir, " (derived object directory)"); RETURN; END; TRY Msg.Verbose ("Looking in ", dir); iter := FS.Iterate (dir); TRY WHILE iter.next (name) DO NoteSourceFile (s, dir, name, cmd_line := FALSE); END; FINALLY iter.close(); END; EXCEPT OSError.E (args) => Msg.FatalError (args, "unable to scan directory \"", dir, "\""); END; END VisitSourceDir; PROCEDUREIncludeOverrides (VAR s: State; overrides: TEXT) RAISES {Wr.Failure, Thread.Alerted} = BEGIN IF M3File.IsReadable (overrides) THEN IF (s.use_overrides) THEN Out (s.wr, "include (\"", M3Path.Convert (overrides), "\")"); s.found_work := TRUE; ELSE IF (M3Options.major_mode = MM.Depend) THEN Msg.Verbose ("ignoring ", overrides, Wr.EOL); ELSE Msg.Info ("ignoring ", overrides, Wr.EOL); END; END; ELSE IF (s.use_overrides) THEN IF (M3Options.major_mode = MM.Depend) THEN Msg.Verbose ("unable to read ", overrides, ", options \"-override\" and \"-x\" ignored.", Wr.EOL); ELSE Msg.Out ("unable to read ", overrides, ", options \"-override\" and \"-x\" ignored.", Wr.EOL); END; END; END; END IncludeOverrides; PROCEDUREIncludeFile (VAR s: State; file: TEXT) RAISES {Wr.Failure, Thread.Alerted} = BEGIN IF M3File.IsReadable (file) THEN Out (s.wr, "include (\"", M3Path.Convert (file), "\")"); s.found_work := TRUE; ELSE IF (M3Options.major_mode = MM.Depend) THEN Msg.Verbose ("unable to read ", file, Wr.EOL); ELSE Msg.Out ("unable to read ", file, Wr.EOL); END; END; END IncludeFile; PROCEDUREIncludeMakefile (VAR s: State; makefile, dir: TEXT) RAISES {Wr.Failure, Thread.Alerted} = BEGIN IF M3File.IsReadable (makefile) THEN Out (s.wr, "include_dir (\"", M3Path.Convert (dir), "\")"); s.found_work := TRUE; ELSE Msg.Debug ("Dirs.derived = ", Dirs.derived, Wr.EOL); Msg.Debug ("Dirs.to_source = ", Dirs.to_source, Wr.EOL); Msg.Debug ("dir = ", dir, Wr.EOL); Out (s.wr, "import (\"libm3\")"); VisitSourceDir (s, dir, cmd_line := FALSE); Out (s.wr, "program (\"prog\")"); END; END IncludeMakefile;
PROCEDURE---------------------------------------------------------- misc ---ScanCommandLine1 () = VAR arg: TEXT; BEGIN FOR i := 1 TO Params.Count-1 DO arg := Params.Get (i); IF Text.Length(arg) > 1 AND Text.GetChar (arg, 1) = '-' THEN arg := Text.Sub (arg, 1); END; IF Text.Equal (arg, "-?") THEN PrintHelp (); ELSIF Text.Equal (arg, "-help") THEN PrintHelp (); ELSIF Text.Equal (arg, "-config") THEN PrintVersion (TRUE); ELSIF Text.Equal (arg, "-version") THEN PrintVersion (TRUE); END; END; END ScanCommandLine1; PROCEDUREScanCommandLine2 () : TextTextTbl.T = VAR use_overrides := FALSE; cnt := 0; arg: TEXT; BEGIN FOR i := 1 TO Params.Count-1 DO arg := Params.Get (i); IF Text.Length(arg) > 1 AND Text.GetChar (arg, 1) = '-' THEN arg := Text.Sub (arg, 1); END; IF Text.Equal (arg, "-build") THEN SetMode (cnt, MM.Build); ELSIF Text.Equal (arg, "-clean") THEN SetMode (cnt, MM.Clean); ELSIF Text.Equal (arg, "-realclean") THEN SetMode (cnt, MM.RealClean); ELSIF Text.Equal (arg, "-find") THEN SetMode (cnt, MM.Find); ELSIF Text.Equal (arg, "-ship") THEN SetMode (cnt, MM.Ship); ELSIF Text.Equal (arg, "-depend") THEN SetMode (cnt, MM.Depend); ELSIF Text.Equal (arg, "-silent") THEN Msg.SetLevel (Msg.Level.Silent); ELSIF Text.Equal (arg, "-why") THEN Msg.SetLevel (Msg.Level.Explain); ELSIF Text.Equal (arg, "-commands") THEN Msg.SetLevel (Msg.Level.Commands); ELSIF Text.Equal (arg, "-verbose") THEN Msg.SetLevel (Msg.Level.Verbose); ELSIF Text.Equal (arg, "-debug") THEN Msg.SetLevel (Msg.Level.Debug); ELSIF Text.Equal (arg, "-profile") THEN EVAL defs.put("M3_PROFILING", "TRUE"); ELSIF Text.Equal (arg, "-trace") THEN traceQuake := TRUE; ELSIF Text.Equal (arg, "-x") OR Text.Equal (arg, "-override") THEN use_overrides := TRUE; ELSIF Text.Equal (arg, "-parallelback") THEN ELSIF Text.Equal (arg, "-pretend") THEN IF i < Params.Count - 1 THEN EVAL defs.put("CM3_VERSION", Params.Get(i+1)); ELSE Msg.Error(NIL, "missing argument for -pretend"); END; END; END; IF (cnt <= 0) THEN SetMode (cnt, MM.Build); END; EVAL defs.put("M3_USE_OVERRIDES", ARRAY BOOLEAN OF TEXT {"", "TRUE"}[use_overrides]); RETURN defs; END ScanCommandLine2; PROCEDURESetMode (VAR cnt: INTEGER; mode: MM) = BEGIN INC (cnt); IF (cnt > 1) THEN Msg.Error (NIL, "mode \"", ModeName [M3Options.major_mode], "\" already set, \"", ModeName [mode] & "\" ignored."); ELSE M3Options.major_mode := mode; END; END SetMode; PROCEDUREPrintVersion (exit: BOOLEAN) = BEGIN IF traceQuake THEN MxConfig.EnableQuakeTrace() END; Msg.Out ("Critical Mass Modula-3 version ", Val("CM3_RELEASE"), Wr.EOL); Msg.Out (" last updated: ", Val("CM3_CHANGED"), Wr.EOL); Msg.Out (" compiled: ", Val("CM3_COMPILED"), Wr.EOL); Msg.Out (" configuration: ", MxConfig.FindFile(), Wr.EOL); Msg.Out (" host: ", MxConfig.HOST, Wr.EOL); Msg.Out (" target: ", MxConfig.Get("TARGET"), Wr.EOL); Msg.Out (Wr.EOL); IF exit THEN Process.Exit (0); END; END PrintVersion; PROCEDUREPrintHelp () = BEGIN PrintVersion (FALSE); FOR i := FIRST (HelpMsg) TO LAST (HelpMsg) DO Msg.Out (HelpMsg[i], Wr.EOL); END; Process.Exit (0); END PrintHelp; CONST HelpMsg = ARRAY OF TEXT { "command line options:", "", "modes: (default: -build)", " -build compile and link", " -ship install package", " -clean delete derived files", " -realclean delete derived target directory", " -find locate source files", " -depend output package dependencies", "", "compile options: (default: -g -w1)", " -g produce symbol table information for debugger", " -O optimize code", " -A disable code generation for assertions", " -once don't recompile to improve opaque object code", " -w0 .. -w3 limit compiler warning messages", " -Z generate coverage analysis code", " -profile generate profiling code", " -lazy generate lazy module initialization code", " (main module and imports only) This is the default.", " -linkall generate module initialization code for all modules,", " even those that are not imported directly or indirectly", " by Main. This is currently experimental and does not", " always work as expected.", "", "program and library options: (default: -o prog)", " -c compile only, produce no program or library", " -a <foo> build library <foo>", " -o <foo> build program <foo>", " -skiplink skip the final link step", "", "messages: (default: -why)", " -silent produce no diagnostic output", " -why explain why code is being recompiled", " -commands list system commands as they are performed", " -verbose list internal steps as they are performed", " -debug dump internal debugging information", " -trace trace quake code execution", "", "information and help:", " -help print this help message", " -? print this help message", " -version print the version number header", " -config print the version number header", "", "misc:", " -- end of options", " -keep preserve intermediate and temporary files", " -times produce a dump of elapsed times", " -override include the \"m3overrides\" file", " -x include the \"m3overrides\" file", " -D<symbol> define <symbol> with the value TRUE", " -D<sym>=<val> define <sym> with the value <val>", " -F <fn> prepend the quake code of file <fn>", " -FP <fn> \"", " -prepend <fn> \"", " -FA <fn> append the quake code of file <fn>", " -append <fn> \"", " -console produce a Windows CONSOLE subsystem program", " -gui produce a Windows GUI subsystem program", " -windows produce a Windows GUI subsystem program", " -pretend <val> pretend to run as CM3_Version <val>", " -gw install group writable files", " -group-writable \"", " -pb <n> allow <n> parallelism in running back-end (experimental)", " -no-m3ship-resolution use quake variables in .M3SHIP (experimental)", "", "environment variables:", " M3CONFIG platform dependent configuration file to use (cm3.cfg)", " used if no suitable file is found in the local package", " QUAKE_SHELL shell to be used by the quake interpreter for exec()", " QUAKE_SHELL_OPTION command option for quake shell (-c, /c)", " QUAKE_TMPDIR directory for temporary files used by quake", " ", " CM3_INSTALL_PREFIX path prefix to prepend to filenames being installed,", " \"make DESTDIR=\" behaviour for cm3", " " };
PROCEDUREOut (wr: Wr.T; a, b, c, d, e: TEXT := NIL) RAISES {Wr.Failure, Thread.Alerted} = BEGIN IF (a # NIL) THEN Wr.PutText (wr, a); END; IF (b # NIL) THEN Wr.PutText (wr, b); END; IF (c # NIL) THEN Wr.PutText (wr, c); END; IF (d # NIL) THEN Wr.PutText (wr, d); END; IF (e # NIL) THEN Wr.PutText (wr, e); END; Wr.PutText (wr, Wr.EOL); END Out; PROCEDUREVal (name: TEXT) : TEXT = VAR res: TEXT := "undefined"; BEGIN EVAL defs.get(name, res); RETURN res; END Val; VAR defs := NEW(TextTextTbl.Default).init(); traceQuake := FALSE; BEGIN EVAL defs.put("CM3_RELEASE", Version.Text); (* readable release version *) EVAL defs.put("CM3_VERSION", Version.Number);(* version as number *) EVAL defs.put("CM3_CHANGED", Version.LastChanged); (* date of last change *) EVAL defs.put("CM3_CREATED", Version.LastChanged); (* backw. compatibility *) EVAL defs.put("CM3_COMPILED", Version.Created); (* date of compilation *) EVAL defs.put("M3_PROFILING", ""); (* no profiling by default *) EVAL defs.put("EOL", Wr.EOL); END Makefile.