1(* 	$Id: oo2c.Mod,v 1.74 2004/11/24 03:57:57 sgreenhill Exp $	 *)
2MODULE oo2c;
3(*  Main module for the Oberon-2 to C translator.
4    Copyright (C) 2002-2004  Michael van Acken
5
6    This file is part of OOC.
7
8    OOC is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    OOC is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with OOC. If not, write to the Free Software Foundation, 59
20    Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21*)
22
23IMPORT
24  IO:StdChannels, Out, Err, Object, URI, URI:Scheme:File, CfgData := Config,
25  ADT:StringBuffer, IO, OS:ProcessManagement, OS:Path, OS:Files,
26  Config:Section:Options,
27  OOC:Logger, OOC:Config, OOC:Config:CCompiler, OOC:Package,
28  OOC:SymbolTable:Builder, OOC:Config:StdPragmas, OOC:Error,
29  Rep := OOC:Repository, OOC:Repository:FileSystem, OOC:Make, OOC:SSA:Stats;
30
31
32CONST
33  buildPackage = -1;
34  installPackage = -2;
35  uninstallPackage = -3;
36  updateRepository = -4;
37  getOption = -5;
38  buildPackageDoc = -6;
39  packageInstalled = -7;
40  listPackages     = -8;
41
42VAR
43  cfgErrList, errList: Error.List;
44  i: LONGINT;
45  arg: STRING;
46  mode: SHORTINT;
47  command, forceUpdate, listUses, useStderr, writeStats,
48      verbose, errorStyle, showHelp, showVersion: Options.Option;
49  makeRules: Make.Rules;
50  rep: Rep.Repository;
51  r: Package.Repository;
52  pkg, pkgInfo: Package.Package;
53  ok, forceUpdateRepository, doInstall: BOOLEAN;
54  option: Options.Option;
55  module: Rep.Module;
56
57PROCEDURE NewConfig;
58  BEGIN
59    command := Config.AddOption("command", CfgData.NewIntegerVar(0));
60    forceUpdate := Config.AddOption("forceUpdate", CfgData.NewBooleanVar(FALSE));
61    listUses := Config.AddOption("listUses", CfgData.NewStringVar(""));
62    useStderr := Config.AddOption("useStderr", CfgData.NewBooleanVar(FALSE));
63    writeStats := Config.AddOption("writeStats", CfgData.NewBooleanVar(FALSE));
64    verbose := Config.AddOption("verbose", CfgData.NewBooleanVar(FALSE));
65    errorStyle := Config.AddOption("errorStyle",
66                                 CfgData.NewStringVar("file:line:column"));
67    showHelp := Config.AddOption("showHelp", CfgData.NewBooleanVar(FALSE));
68    showVersion := Config.AddOption("showVersion", CfgData.NewBooleanVar(FALSE));
69
70    Config.AddRepositoryListEnv();
71    Config.AddCmdLine ("--repository,-r",
72                 "<repositories><file-system>$1</file-system></repositories>");
73    Config.AddCmdLine ("--make,-M",
74                 "<options><set name='command'>1</set></options>");
75    Config.AddCmdLine ("--build-package",
76                       "<options><set name='command'>2</set></options>");
77    Config.AddCmdLine ("--install-package",
78                       "<options><set name='command'>3</set></options>");
79    Config.AddCmdLine ("--uninstall-package",
80                       "<options><set name='command'>4</set></options>");
81    Config.AddCmdLine ("--update-repository",
82                       "<options><set name='command'>5</set></options>");
83    Config.AddCmdLine ("--get-option",
84                       "<options><set name='command'>6</set></options>");
85    Config.AddCmdLine ("--build-pkg-doc",
86                       "<options><set name='command'>7</set></options>");
87    Config.AddCmdLine ("--package-installed",
88                       "<options><set name='command'>8</set></options>");
89    Config.AddCmdLine ("--list-packages",
90                       "<options><set name='command'>9</set></options>");
91
92    Config.AddCmdLine ("-h,--help",
93                       "<options><set name='showHelp'>TRUE</set></options>");
94    Config.AddCmdLine ("--version",
95                       "<options><set name='showVersion'>TRUE</set></options>");
96    Config.AddCmdLine ("--no-rtc",
97                       "<pragmas>"+
98                       "  <set name='Assertions'>FALSE</set>"+
99                       "  <set name='IndexCheck'>FALSE</set>"+
100                       "  <set name='DerefCheck'>FALSE</set>"+
101                       "  <set name='OverflowCheck'>FALSE</set>"+
102                       "  <set name='CaseSelectCheck'>FALSE</set>"+
103                       "  <set name='FunctResult'>FALSE</set>"+
104                       "  <set name='TypeGuard'>FALSE</set>"+
105                       "</pragmas>");
106    Config.AddCmdLine ("--verbose,-v",
107                       "<options><set name='verbose'>TRUE</set></options>");
108    Config.AddCmdLine ("--warnings,-w", ""); (* ignored for now *)
109
110    Config.AddCmdLine ("-A,--all",
111                       "<options><set name='forceUpdate'>TRUE</set></options>");
112    Config.AddCmdLine ("--uses",
113                       "<options>"+
114                       "  <set name='listUses'>$1</set>"+
115                       "  <set name='command'>1</set>"+  (* --make *)
116                       "</options>");
117    Config.AddCmdLine ("--error-style",
118                       "<options><set name='errorStyle'>$1</set></options>");
119    Config.AddCmdLine ("--use-stderr",
120                       "<options><set name='useStderr'>TRUE</set></options>");
121    Config.AddCmdLine ("--stats",
122                       "<options><set name='writeStats'>TRUE</set></options>");
123    CCompiler.RegisterConfig;
124  END NewConfig;
125
126PROCEDURE GetModule (moduleName: STRING): Rep.Module;
127  VAR
128    m: Rep.Module;
129    chars: Object.CharsLatin1;
130    str: Object.String8;
131  BEGIN
132    str := moduleName.ToString8("?");
133    chars := str.CharsLatin1();
134    m := Config.repositories.GetModule(chars^);
135    IF (m = NIL) THEN
136      Err.String ("Error: Cannot locate module ");
137      Err.String (chars^);
138      Err.Ln;
139      HALT (1)
140    END;
141    RETURN m;
142  END GetModule;
143
144PROCEDURE BuildPackage(pkg: Package.Package; rep: Rep.Repository;
145                       install: BOOLEAN): BOOLEAN
146RAISES IO.Error;
147  VAR
148    ok: BOOLEAN;
149    i: LONGINT;
150    lib: Package.Library;
151    exec: Package.Executable;
152    normSet: Package.FileSet;
153    module: Rep.Module;
154    installObjects: BOOLEAN;
155
156  PROCEDURE InstallDirectory(prefix, path: STRING): BOOLEAN;
157    VAR
158      cmd: STRING;
159    BEGIN
160      IF (prefix.length # 0) THEN
161        path := prefix+"/"+path;
162      END;
163
164      IF Files.Exists(path) THEN
165        (* path name exists (although it may be a non-directory *)
166        RETURN TRUE;
167      ELSE
168        cmd := CCompiler.InstallDirectoryCmd(path);
169        Logger.ShellCommand(cmd);
170        RETURN (ProcessManagement.system(cmd) = 0);
171      END;
172    END InstallDirectory;
173
174  PROCEDURE InstallLibrary(module: Rep.Module; makeRules: Make.Rules): BOOLEAN;
175  (* Note: This procedure adds symbol files to the package's
176     @ofield{pkg.fileSet}.
177
178     pre: Full update has been done for the library's main module.  *)
179    VAR
180      uri: URI.URI;
181      cmd: STRING;
182      m: Rep.Module;
183      i: LONGINT;
184      installObjects: BOOLEAN;
185    BEGIN
186      installObjects := ~CCompiler.HaveLibtool();
187
188      (* For every symbol file, its doc string file, and the header file, add
189         an entry to the package's file list.  The source and destination name
190         is the file name relative to the repository.  Upon installation, the
191         former is interpreted relative to the providing repository, and the
192         latter relative to the installation directory.  *)
193      FOR i := 0 TO LEN(makeRules.imports^)-1 DO
194        m := makeRules.imports[i];
195
196        IF (m.origin = module.origin) THEN
197          IF installObjects & ~m.ifData.NoObjectFile() THEN
198            pkg.fileSet.Append(Package.NewFile(m.origin.GetLocalPath(m, Rep.modObjectFile), NIL));
199          END;
200
201          pkg.fileSet.Append(Package.NewFile(m.origin.GetLocalPath(m, Rep.modSymbolFile), NIL));
202          pkg.fileSet.Append(Package.NewFile(m.origin.GetLocalPath(m, Rep.modSymbolFileDoc), NIL));
203          pkg.fileSet.Append(Package.NewFile(m.origin.GetLocalPath(m, Rep.modHeaderFileC), NIL));
204        END;
205      END;
206
207      IF installObjects THEN
208        RETURN TRUE;
209      ELSIF InstallDirectory("", CCompiler.libdir.value(CfgData.StringVar).string) THEN
210        uri := module.GetURI(Rep.modLibrary, TRUE);
211        cmd := CCompiler.InstallProgramCmd(uri, TRUE);
212        Logger.ShellCommand(cmd);
213        RETURN (ProcessManagement.system(cmd) = 0);
214      ELSE
215        RETURN FALSE;
216      END;
217    END InstallLibrary;
218
219  PROCEDURE InstallExecutable(module: Rep.Module): BOOLEAN;
220  (* pre: Full update has been done for the program's main module.  *)
221    VAR
222      uri: URI.URI;
223      cmd: STRING;
224    BEGIN
225      IF InstallDirectory("", CCompiler.bindir.value(CfgData.StringVar).string) THEN
226        uri := module.GetURI(Rep.modExecutable, TRUE);
227        cmd := CCompiler.InstallProgramCmd(uri, FALSE);
228        Logger.ShellCommand(cmd);
229        RETURN (ProcessManagement.system(cmd) = 0);
230      ELSE
231        RETURN FALSE;
232      END;
233    END InstallExecutable;
234
235  PROCEDURE InstallFiles(list: Package.FileData): BOOLEAN;
236    VAR
237      end: Package.FileData;
238      dir, str, sourcePrefix: STRING;
239      cmd: StringBuffer.StringBuffer;
240      baseURI: URI.URI;
241      chars: Object.CharsLatin1;
242
243    (*PROCEDURE SameDirectory(a, b: Package.File): BOOLEAN;
244      VAR
245        sa, sb: STRING;
246        i, j: LONGINT;
247      BEGIN
248        sa := a.destName; sb := b.destName;
249        i := 0;
250        WHILE (i # sa.length) & (i # sb.length) &
251              (sa.CharAt(i) = sb.CharAt(i)) DO
252          INC(i);
253        END;
254        WHILE (i # 0) & (sa.CharAt(i-1) # "/") DO
255          DEC(i);
256        END;
257
258        IF (i = 0) OR
259           ((sa.CharAt(i-1) = "/") &
260            (sb.CharAt(i-1) = "/")) THEN
261          (* sa and sb have the same prefix ending with a "/"; check that both
262             have no "/" in the rest of their path *)
263          j := i;
264          WHILE (j # sa.length) & (sa.CharAt(j) # "/") DO
265            INC (j);
266          END;
267          IF (j = sa.length) THEN
268            j := i;
269            WHILE (j # sb.length) & (sb.CharAt(j) # "/") DO
270              INC (j);
271            END;
272            RETURN (j = sb.length)
273          END;
274        END;
275        RETURN FALSE;
276      END SameDirectory;*)
277
278    BEGIN
279      baseURI := rep(FileSystem.Repository).relativeBaseURI;
280      sourcePrefix := baseURI(File.URI).GetPath();
281
282      WHILE (list # NIL) DO
283        end := list.nextFileData;
284        (* don't call install with multiple input files: the fallback script
285           install-sh does not support this
286
287           WHILE (end # NIL) &
288              SameDirectory(list(Package.File), end(Package.File)) DO
289          end := end.nextFileData;
290        END;*)
291
292        dir := Path.DirName(list(Package.File).destName);
293
294        chars := dir(Object.String8).CharsLatin1();
295        IF InstallDirectory(CCompiler.oocdir.value(CfgData.StringVar).string,
296                            dir(Object.String8)) THEN
297          cmd := StringBuffer.New(CCompiler.installData.value(CfgData.StringVar).string);
298          WHILE (list # end) DO
299            cmd.Append(" ");
300            cmd.Append(Path.QuoteForShell(sourcePrefix+list(Package.File).name));
301            list := list.nextFileData;
302          END;
303
304          cmd.Append(" ");
305          IF (CCompiler.oocdir.value(CfgData.StringVar).string.length # 0) THEN
306            cmd.Append(Path.QuoteForShell(CCompiler.oocdir.value(CfgData.StringVar).string));
307            IF (dir.length # 0) THEN
308              cmd.Append("/");
309            END;
310          END;
311          cmd.Append(Path.QuoteForShell(dir));
312
313          str := cmd.ToString();
314          Logger.ShellCommand(str);
315          IF (ProcessManagement.system(str) # 0) THEN
316            RETURN FALSE;
317          END;
318        ELSE
319          RETURN FALSE;
320        END;
321      END;
322      RETURN TRUE;
323    END InstallFiles;
324
325  PROCEDURE BuildDocs(module: Rep.Module; makeRules: Make.Rules;
326                      install: BOOLEAN): BOOLEAN
327  RAISES IO.Error;
328    VAR
329      m: Rep.Module;
330      ok: BOOLEAN;
331      i: LONGINT;
332    BEGIN
333      ok := TRUE;
334      IF Config.HaveXsltProc() THEN
335        i := 0;
336        WHILE ok & (i #  LEN(makeRules.imports^)) DO
337          m := makeRules.imports[i];
338          IF (m.origin = module.origin) THEN
339            IF install THEN
340              pkg.fileSet.Append(Package.NewFile(m.origin.GetLocalPath(m, Rep.modInterfaceDescr), NIL));
341              pkg.fileSet.Append(Package.NewFile(m.origin.GetLocalPath(m, Rep.modInterfaceHTML), NIL));
342            ELSE
343              ok := makeRules.Update(m, Rep.modInterfaceHTML);
344            END;
345          END;
346          INC(i);
347        END;
348      END;
349      RETURN ok;
350    END BuildDocs;
351
352  BEGIN
353    Rep.readDocStrings := TRUE;
354    installObjects := ~CCompiler.HaveLibtool();
355    ok := TRUE;
356
357    i := 0;
358    WHILE ok & (i # pkg.library.size) DO
359      lib := pkg.library.array[i];
360
361      module := GetModule(lib.mainModule);
362      IF installObjects THEN
363        ok := makeRules.Update(module, Rep.modExecutable)
364            & (~install OR InstallLibrary(module, makeRules));
365      ELSE
366        makeRules.SetLibrary(lib);
367        ok := makeRules.Update(module, Rep.modLibrary)
368            & (~install OR InstallLibrary(module, makeRules));
369      END;
370
371      IF ok THEN
372        (* build HTML documentation for modules in library *)
373        ok := BuildDocs(module, makeRules, install);
374      END;
375
376      makeRules.SetLibrary(NIL);
377      INC(i);
378    END;
379
380    i := 0;
381    WHILE ok & (i # pkg.executable.size) DO
382      exec := pkg.executable.array[i];
383      module := GetModule(exec.mainModule);
384      ok := makeRules.Update(module, Rep.modExecutable)
385          & (~install OR InstallExecutable(module));
386      INC(i);
387    END;
388
389    IF ok & install THEN
390      normSet := Package.Normalize(pkg.fileSet);
391      ok := InstallFiles(normSet.head);
392    END;
393
394    IF ok & install THEN
395      Package.WritePackage(pkg,
396                           CCompiler.oocdir.value(CfgData.StringVar).string);
397    END;
398
399    RETURN ok;
400  END BuildPackage;
401
402PROCEDURE UninstallPackage(pkg: Package.Package);
403  VAR
404    i: LONGINT;
405    normSet: Package.FileSet;
406
407  PROCEDURE UninstallLibrary(library: Package.Library);
408    VAR
409      cmd: STRING;
410      ok: BOOLEAN;
411      b: StringBuffer.StringBuffer;
412    BEGIN
413      b := StringBuffer.NewLatin1("");
414      b.Append(CCompiler.libdir.value(CfgData.StringVar).string);
415      b.Append("/lib");
416      b.Append(library.name);
417      b.Append(".la");
418      cmd := CCompiler.UninstallProgramCmd(b.ToString(), TRUE);
419      Logger.ShellCommand(cmd);
420      ok := (ProcessManagement.system(cmd) = 0);
421    END UninstallLibrary;
422
423  PROCEDURE UninstallExecutable(executable: Package.Executable);
424    VAR
425      cmd: STRING;
426      ok: BOOLEAN;
427      b: StringBuffer.StringBuffer;
428    BEGIN
429      b := StringBuffer.NewLatin1("");
430      b.Append(CCompiler.bindir.value(CfgData.StringVar).string);
431      b.Append("/");
432      b.Append(executable.mainModule);
433      cmd := CCompiler.UninstallProgramCmd(b.ToString(), FALSE);
434      Logger.ShellCommand(cmd);
435      ok := (ProcessManagement.system(cmd) = 0);
436    END UninstallExecutable;
437
438  PROCEDURE UninstallFiles(list: Package.FileData);
439    VAR
440      str: STRING;
441      ok: BOOLEAN;
442      b: StringBuffer.StringBuffer;
443    BEGIN
444      WHILE (list # NIL) DO
445        b := StringBuffer.New(CCompiler.uninstall.value(CfgData.StringVar).string);
446        b.Append(" ");
447        b.Append(Path.QuoteForShell(CCompiler.oocdir.value(CfgData.StringVar).string));
448        b.Append("/");
449        b.Append(list(Package.File).destName);
450
451        str := b.ToString();
452        Logger.ShellCommand(str);
453        ok := (ProcessManagement.system(str) = 0);
454        list := list.nextFileData;
455      END;
456    END UninstallFiles;
457
458  PROCEDURE UninstallPkgInfo(pkg: Package.Package);
459    VAR
460      ok: BOOLEAN;
461      cmd: STRING;
462    BEGIN
463      cmd := Package.RemovePkgInfoCmd
464          (pkg,
465           CCompiler.oocdir.value(CfgData.StringVar).string,
466           CCompiler.uninstall.value(CfgData.StringVar).string);
467      Logger.ShellCommand(cmd);
468      ok := (ProcessManagement.system(cmd) = 0);
469    END UninstallPkgInfo;
470
471  BEGIN
472    i := 0;
473    WHILE (i # pkg.library.size) DO
474      UninstallLibrary(pkg.library.array[i]);
475      INC(i);
476    END;
477
478    i := 0;
479    WHILE (i # pkg.executable.size) DO
480      UninstallExecutable(pkg.executable.array[i]);
481      INC(i);
482    END;
483
484    normSet := Package.Normalize(pkg.fileSet);
485    UninstallFiles(normSet.head);
486
487    UninstallPkgInfo(pkg);
488  END UninstallPackage;
489
490PROCEDURE BuildPackageDoc(pkg: Package.Package): BOOLEAN
491RAISES IO.Error;
492  VAR
493    ok: BOOLEAN;
494    i: LONGINT;
495    lib: Package.Library;
496    exec: Package.Executable;
497
498  PROCEDURE BuildDocs(module: Rep.Module): BOOLEAN
499  RAISES IO.Error;
500    VAR
501      ok: BOOLEAN;
502      i: LONGINT;
503      list: Make.ModuleList;
504    BEGIN
505      ok := makeRules.Update(module, Rep.modSymbolFile);
506
507      list := Make.ModuleClosure(module);
508      i := 0;
509      WHILE ok & (i #  LEN(list^)) DO
510        IF (list[i].origin = module.origin) THEN
511          ok := makeRules.Update(list[i], Rep.modInterfaceHTML);
512        END;
513        INC(i);
514      END;
515      RETURN ok;
516    END BuildDocs;
517
518  BEGIN
519    Rep.readDocStrings := TRUE;
520    ok := TRUE;
521
522    i := 0;
523    WHILE ok & (i # pkg.library.size) DO
524      lib := pkg.library.array[i];
525      ok := BuildDocs(GetModule(lib.mainModule));
526      INC(i);
527    END;
528
529    i := 0;
530    WHILE ok & (i # pkg.executable.size) DO
531      exec := pkg.executable.array[i];
532      ok := BuildDocs(GetModule(exec.mainModule));
533      INC(i);
534    END;
535
536    RETURN ok;
537  END BuildPackageDoc;
538
539PROCEDURE WriteHelp();
540  BEGIN
541    Out.String("Usage:"); Out.Ln;
542    Out.String("  oo2c [options] <module>..."); Out.Ln;
543    Out.String("  oo2c (--make|-M) [options] <module>"); Out.Ln;
544    Out.String("  oo2c --uses <ext-ident> [options] <module> ..."); Out.Ln;
545    Out.String("  oo2c --build-package [options] <package>"); Out.Ln;
546    Out.String("  oo2c --install-package [options] <package>"); Out.Ln;
547    Out.String("  oo2c --uninstall-package [options] <package>"); Out.Ln;
548    Out.String("  oo2c --build-pkg-doc [options] <package>"); Out.Ln;
549    Out.String("  oo2c --package-installed [options] <package>"); Out.Ln;
550    Out.String("  oo2c --list-packages [options]"); Out.Ln;
551    Out.String("Options:"); Out.Ln;
552    Out.String("  --config <file>"); Out.Ln;
553    Out.String("  --repository <directory>, -r <directory>"); Out.Ln;
554    Out.String("  --no-rtc"); Out.Ln;
555    Out.String("  (--all|-A)"); Out.Ln;
556    Out.String("  --error-style (file:line:column|char-pos|attributes)");
557    Out.Ln;
558  END WriteHelp;
559
560BEGIN  <*Warnings:=FALSE*>
561  Error.minErrorDistance := 16;
562  Builder.doAutoImport := Builder.fullAutoImport;
563  cfgErrList := Error.NewList ("");
564  NewConfig;
565  Config.Read (cfgErrList);
566
567  makeRules := Make.NewRules();
568  IF useStderr.value(CfgData.BooleanVar).boolean THEN
569    makeRules.SetErrOut(StdChannels.stderr);
570  END;
571  makeRules.SetForceUpdate(forceUpdate.value(CfgData.BooleanVar).boolean);
572  ok := makeRules.UsageTracking(listUses.value(CfgData.StringVar).string);
573  IF ~ok THEN
574    Err.String ("Error: Invalid selector string for `--uses'");
575    Err.Ln;
576    HALT (1)
577  END;
578  Make.writeStats := writeStats.value(CfgData.BooleanVar).boolean;
579  Logger.silence := ~verbose.value(CfgData.BooleanVar).boolean;
580
581  CASE command.value(CfgData.IntegerVar).integer OF
582  | 0:
583    mode := Rep.modCodeFileC;
584  | 1:
585    mode := Rep.modExecutable;
586  | 2:
587    mode := buildPackage;
588  | 3:
589    mode := installPackage;
590  | 4:
591    mode := uninstallPackage;
592  | 5:
593    mode := updateRepository;
594  | 6:
595    mode := getOption; Logger.silence := TRUE;
596  | 7:
597    mode := buildPackageDoc;
598  | 8:
599    mode := packageInstalled; Logger.silence := TRUE;
600  | 9:
601    mode := listPackages; Logger.silence := TRUE;
602  END;
603  IF errorStyle.value(CfgData.StringVar).string.Equals("file:line:column") THEN
604    Error.style := Error.styleFileLineColumn;
605  ELSIF errorStyle.value(CfgData.StringVar).string.Equals("char-pos") THEN
606    Error.style := Error.styleCharPos;
607  END;
608
609  IF (cfgErrList. msgCount # 0) THEN
610    cfgErrList. Write (StdChannels.stderr);
611    HALT(1);
612  ELSIF showVersion.value(CfgData.BooleanVar).boolean THEN
613    Out.String("oo2c/");
614    Out.String(StdPragmas.defaultTargetArch);
615    Out.String(" ");
616    Out.String(StdPragmas.defaultCompilerVersion);
617    Out.Ln;
618    HALT(0);
619  ELSIF showHelp.value(CfgData.BooleanVar).boolean THEN
620    WriteHelp;
621  ELSIF ((mode = updateRepository) OR (mode = listPackages))
622    # (Config.arguments. ArgNumber() = 0) THEN
623    WriteHelp;
624    HALT (1)
625  ELSE
626    ok := TRUE;
627
628    IF (mode = updateRepository) THEN
629      ok := Package.UpdateRepository(CCompiler.oocdir.value(CfgData.StringVar).string);
630
631    ELSIF (mode = listPackages) THEN
632      r := Package.GetRepository(CCompiler.oocdir.value(CfgData.StringVar).string, errList);
633      errList.Write(StdChannels.stderr);
634      FOR i := 0 TO r.installedPkgs.size-1 DO
635        Out.Object(r.installedPkgs.array[i]); Out.Ln;
636      END;
637
638    ELSE
639      IF ~Package.ParseMetaData(Config.options, Config.pragmas) THEN
640        HALT(1);
641      END;
642
643      forceUpdateRepository := FALSE;
644      i := 0;
645      WHILE ok & (i # Config.arguments. ArgNumber()) DO
646        arg := Config.arguments. Get (i);
647        CASE mode OF
648        | buildPackage, installPackage:
649          doInstall := (mode = installPackage);
650          pkg := Package.GetPackage(arg, rep);
651          IF (pkg = NIL) THEN
652            Err.String ("Error: Cannot locate package ");
653            Err.Object (arg);
654            Err.Ln;
655            HALT (1)
656          ELSE
657            IF doInstall THEN
658              pkgInfo := Package.GetPkgInfo(CCompiler.oocdir.value(CfgData.StringVar).string, arg, errList);
659              IF (pkgInfo # NIL) & (errList.msgCount = 0) THEN
660                UninstallPackage(pkgInfo);
661              END;
662            END;
663            ok := BuildPackage(pkg, rep, doInstall);
664            forceUpdateRepository := doInstall;
665          END;
666
667        | uninstallPackage:
668          pkg := Package.GetPkgInfo(CCompiler.oocdir.value(CfgData.StringVar).string, arg, errList);
669          IF (errList.msgCount # 0) THEN
670            errList.Write(StdChannels.stdout);
671          END;
672          IF (pkg = NIL) THEN
673            Err.String ("Error: Cannot locate package ");
674            Err.Object (arg);
675            Err.Ln;
676            HALT (1)
677          ELSE
678            UninstallPackage(pkg);
679            forceUpdateRepository := TRUE;
680          END;
681
682
683        | getOption:
684          option := Config.options.Get(arg);
685          IF (option = NIL) THEN
686            Out.String("(none)");
687          ELSE
688            Out.Object(option.value(CfgData.StringVar).string);
689          END;
690          Out.Ln;
691
692        | buildPackageDoc:
693          pkg := Package.GetPackage(arg, rep);
694          IF (pkg = NIL) THEN
695            Err.String ("Error: Cannot locate package ");
696            Err.Object (arg);
697            Err.Ln;
698            HALT (1)
699          ELSE
700            ok := BuildPackageDoc(pkg);
701          END;
702
703        | packageInstalled:
704          r := Package.GetRepository(CCompiler.oocdir.value(CfgData.StringVar).string, errList);
705          errList.Write(StdChannels.stderr);
706          IF r.PackageInstalled(arg) THEN
707            HALT(0);
708          ELSE
709            HALT(1);
710          END;
711
712        ELSE
713          module := GetModule(arg);
714          IF (mode = Rep.modCodeFileC) THEN
715            makeRules.SetAllImportsModule(module);
716          END;
717          ok := makeRules.Update(module, mode);
718          makeRules.SetAllImportsModule(NIL);
719        END;
720        INC(i);
721      END;
722
723      IF ok & forceUpdateRepository THEN
724        ok := Package.UpdateRepository(CCompiler.oocdir.value(CfgData.StringVar).string);
725      END;
726    END;
727
728    IF ok THEN
729      IF Make.writeStats THEN
730        Stats.Write();
731      END;
732    ELSE
733      HALT (1)
734    END
735  END
736END oo2c.
737