(* M2Swig.mod generates a swig interface file for the main module.

Copyright (C) 2008-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.

This file is part of GNU Modula-2.

GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Modula-2; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  *)

IMPLEMENTATION MODULE M2Swig ;

FROM Storage IMPORT ALLOCATE ;
FROM M2Options IMPORT GenerateSwig ;
FROM SFIO IMPORT OpenToWrite ;
FROM FIO IMPORT File, Close ;
FROM NameKey IMPORT Name, KeyToCharStar ;
FROM M2Error IMPORT InternalError ;
FROM M2Printf IMPORT fprintf0, fprintf1, fprintf2, fprintf3, fprintf4 ;
FROM M2AsmUtil IMPORT GetFullScopeAsmName ;
FROM SYSTEM IMPORT WORD ;

FROM DynamicStrings IMPORT String, InitString, InitStringCharStar, ConCat, Mark,
                           KillString ;

FROM Lists IMPORT List, InitList, KillList, IsItemInList,
                  IncludeItemIntoList, RemoveItemFromList,
                  ForeachItemInListDo, NoOfItemsInList,
                  GetItemFromList ;

FROM M2Quads IMPORT IsProcedureScope ;
FROM M2System IMPORT IsSystemType, Address, Byte, Loc, Word ;
FROM M2Bitset IMPORT Bitset ;
FROM Indexing IMPORT Index, InitIndex, KillIndex, HighIndice, PutIndice, GetIndice ;
FROM M2Scope IMPORT ScopeBlock, InitScopeBlock, KillScopeBlock ;

FROM M2Base IMPORT IsBaseType, Char, Cardinal, Integer, Real, LongReal, ShortReal,
                   LongCard, ShortCard, LongInt, ShortInt, Boolean ;

FROM SymbolTable IMPORT GetSymName, IsType, IsProcedure, IsConst, IsVar,
                        GetType, GetNthParamAny, IsUnbounded, GetMode, ModeOfAddr,
                        NoOfParamAny, IsConstString, IsConstLit, IsPointer,
                        IsExported, ForeachExportedDo, IsUnboundedParamAny,
                        IsParameter, IsParameterUnbounded, IsParameterVar,
                        GetParameterShadowVar, GetReadQuads, GetWriteQuads,
                        NulSym ;

FROM M2BasicBlock IMPORT BasicBlock, InitBasicBlocks, KillBasicBlocks,
                         ForeachBasicBlockDo,
                         GetBasicBlockStart, GetBasicBlockEnd ;


TYPE
   UnboundedSig = POINTER TO RECORD
                                type: CARDINAL ;
                                name: Name ;
                             END ;

VAR
   includedArray: BOOLEAN ;
   uKey         : Index ;
   mainModule   : CARDINAL ;
   Done,
   ToDo         : List ;
   f            : File ;
   name         : String ;


(*
   DoExported - includes, sym, into the, ToDo, list.
*)

PROCEDURE DoExported (sym: CARDINAL) ;
BEGIN
   IncludeItemIntoList(ToDo, sym)
END DoExported ;


(*
   MoveToDone - moves a sym to the, Done, list,
                providing that it is not already on it.
                It returns TRUE if the lists were modified.
*)

PROCEDURE MoveToDone (sym: CARDINAL) : BOOLEAN ;
BEGIN
   IF IsItemInList(Done, sym)
   THEN
      RETURN( FALSE )
   ELSIF IsItemInList(ToDo, sym)
   THEN
      RemoveItemFromList(ToDo, sym) ;
      IncludeItemIntoList(Done, sym) ;
      RETURN( TRUE )
   END ;
   IncludeItemIntoList(Done, sym) ;
   RETURN( TRUE )
END MoveToDone ;


(*
   MoveToToDo - moves a sym to the, ToDo, list,
                providing that it is not already on it.
                It returns TRUE if the lists were modified.
*)

PROCEDURE MoveToToDo (sym: CARDINAL) : BOOLEAN ;
BEGIN
   IF IsItemInList(Done, sym)
   THEN
      InternalError ('not expecting to get here')
   ELSIF IsItemInList(ToDo, sym)
   THEN
      RETURN( FALSE )
   ELSE
      IncludeItemIntoList(ToDo, sym) ;
      RETURN( TRUE )
   END
END MoveToToDo ;


(*
   Trybase - returns TRUE
*)

PROCEDURE TryBase (sym: CARDINAL) : BOOLEAN ;
BEGIN
   IF (sym=Cardinal) OR (sym=Integer) OR (sym=LongInt) OR
      (sym=LongCard) OR (sym=Char) OR (sym=ShortCard) OR
      (sym=ShortInt) OR (sym=Real) OR (sym=LongReal) OR
      (sym=ShortReal) OR (sym=Boolean)
   THEN
      RETURN( MoveToDone(sym) )
   ELSE
      RETURN( FALSE )
   END
END TryBase ;


(*
   TrySystem - returns TRUE if sym can be moved to the done list.
*)

PROCEDURE TrySystem (sym: CARDINAL) : BOOLEAN ;
BEGIN
   IF (sym=Bitset) OR (sym=Address) OR (sym=Byte) OR (sym=Loc) OR
      (sym=Word)
   THEN
      RETURN( MoveToDone(sym) )
   ELSE
      RETURN( FALSE )
   END
END TrySystem ;


(*
   TryMove - tries to move sym to the done queue as long
             as type is known.
*)

PROCEDURE TryMove (sym, type: CARDINAL) : BOOLEAN ;
BEGIN
   IF IsItemInList(Done, type)
   THEN
      IF MoveToDone(sym)
      THEN
         RETURN( TRUE )
      END
   ELSE
      IF MoveToToDo(sym)
      THEN
         RETURN( TRUE )
      END
   END ;
   RETURN( FALSE )
END TryMove ;


(*
   TryType -
*)

PROCEDURE TryType (sym: CARDINAL) : BOOLEAN ;
VAR
   type  : CARDINAL ;
   result: BOOLEAN ;
BEGIN
   type := GetType(sym) ;
   result := TryDependents(type) ;
   IF TryMove(sym, type)
   THEN
      RETURN( TRUE )
   ELSE
      RETURN( result )
   END
END TryType ;


(*
   TryVar -
*)

PROCEDURE TryVar (sym: CARDINAL) : BOOLEAN ;
VAR
   type  : CARDINAL ;
   result: BOOLEAN ;
BEGIN
   type := GetType(sym) ;
   result := TryDependents(type) ;
   IF TryMove(sym, type)
   THEN
      RETURN( TRUE )
   ELSE
      RETURN( result )
   END
END TryVar ;


(*
   TryProcedure -
*)

PROCEDURE TryProcedure (sym: CARDINAL) : BOOLEAN ;
VAR
   son,
   p, i,
   type  : CARDINAL ;
   solved,
   result: BOOLEAN ;
BEGIN
   type := GetType(sym) ;
   result := FALSE ;
   solved := TRUE ;
   IF type#NulSym
   THEN
      IF TryDependents(type)
      THEN
         result := TRUE
      END ;
      IF NOT IsItemInList(Done, type)
      THEN
         solved := FALSE
      END
   END ;
   p := NoOfParamAny (sym) ;
   i := 1 ;
   WHILE i<=p DO
      son := GetNthParamAny(sym, i) ;
      IF TryDependents(son)
      THEN
         result := TRUE
      END ;
      IF NOT IsItemInList(Done, son)
      THEN
         solved := FALSE
      END ;
      INC(i)
   END ;
   IF solved
   THEN
      IF MoveToDone(sym)
      THEN
         RETURN( TRUE )
      END
   ELSE
      IF MoveToToDo(sym)
      THEN
         RETURN( TRUE )
      END
   END ;
   RETURN( result )
END TryProcedure ;


(*
   TryUnbounded -
*)

PROCEDURE TryUnbounded (sym: CARDINAL) : BOOLEAN ;
VAR
   type  : CARDINAL ;
   result: BOOLEAN ;
BEGIN
   type := GetType(sym) ;
   result := TryDependents(type) ;
   IF TryMove(sym, type)
   THEN
      RETURN( TRUE )
   ELSE
      RETURN( result )
   END
END TryUnbounded ;


(*
   TryParameter -
*)

PROCEDURE TryParameter (sym: CARDINAL) : BOOLEAN ;
VAR
   type  : CARDINAL ;
   result: BOOLEAN ;
BEGIN
   type := GetType(sym) ;
   result := TryDependents(type) ;
   IF TryMove(sym, type)
   THEN
      RETURN( TRUE )
   ELSE
      RETURN( result )
   END
END TryParameter ;


(*
   TryDependents - returns TRUE if any alteration occurred to any
                   of the lists.
*)

PROCEDURE TryDependents (sym: CARDINAL) : BOOLEAN ;
BEGIN
   IF IsBaseType(sym)
   THEN
      RETURN( TryBase(sym) )
   ELSIF IsSystemType(sym)
   THEN
      RETURN( TrySystem(sym) )
   ELSIF IsType(sym)
   THEN
      RETURN( TryType(sym) )
   ELSIF IsParameter(sym)
   THEN
      RETURN( TryParameter(sym) )
   ELSIF IsProcedure(sym)
   THEN
      RETURN( TryProcedure(sym) )
   ELSIF IsConstString(sym)
   THEN
      RETURN( MoveToDone(sym) )
   ELSIF IsConstLit(sym)
   THEN
      RETURN( MoveToDone(sym) )
   ELSIF IsVar(sym) AND (GetMode(sym)=ImmediateValue)
   THEN
      RETURN( MoveToDone(sym) )
   ELSIF IsVar(sym)
   THEN
      RETURN( TryVar(sym) )
   ELSIF IsUnbounded(sym)
   THEN
      RETURN( TryUnbounded(sym) )
   ELSE
      RETURN( FALSE )
   END
END TryDependents ;


(*
   DoResolveOrder - resolves the declaration order for swig (C).
*)

PROCEDURE DoResolveOrder ;
VAR
   sym,
   i, n    : CARDINAL ;
   movement: BOOLEAN ;
BEGIN
   REPEAT
      n := NoOfItemsInList(ToDo) ;
      movement := FALSE ;
      i := 1 ;
      WHILE (i<=n) AND (NOT movement) DO
         sym := GetItemFromList(ToDo, i) ;
         movement := TryDependents(sym) ;
         INC(i)
      END
   UNTIL NOT movement
END DoResolveOrder ;


(*
   DoName -
*)

PROCEDURE DoName (sym: CARDINAL) ;
VAR
   n: Name ;
BEGIN
   n := GetFullScopeAsmName(sym) ;
   fprintf1(f, "%a", n)
END DoName ;


(*
   DoParamName -
*)

PROCEDURE DoParamName (sym: CARDINAL) ;
VAR
   n: Name ;
BEGIN
   n := GetSymName(sym) ;
   fprintf1(f, "%a", n)
END DoParamName ;


(*
   DoVar -
*)

PROCEDURE DoVar (sym: CARDINAL) ;
BEGIN
   fprintf0(f, 'extern "C" ') ;
   DoType(GetType(sym)) ;
   fprintf0(f, ' ') ;
   DoName(sym) ;
   fprintf0(f, ';\n')
END DoVar ;


(*
   DoType -
*)

PROCEDURE DoType (sym: CARDINAL) ;
BEGIN
   IF IsPointer(sym)
   THEN
      DoType(GetType(sym)) ;
      fprintf0(f, ' *')
   ELSIF sym=Cardinal
   THEN
      fprintf0(f, "unsigned int")
   ELSIF sym=Integer
   THEN
      fprintf0(f, "int")
   ELSIF sym=Boolean
   THEN
      fprintf0(f, "unsigned int")
   ELSIF sym=LongInt
   THEN
      fprintf0(f, "long long int")
   ELSIF sym=LongCard
   THEN
      fprintf0(f, "long long unsigned int")
   ELSIF sym=Char
   THEN
      fprintf0(f, "char")
   ELSIF sym=ShortCard
   THEN
      fprintf0(f, "short unsigned int")
   ELSIF sym=ShortInt
   THEN
      fprintf0(f, "short int")
   ELSIF sym=Real
   THEN
      fprintf0(f, "double")
   ELSIF sym=LongReal
   THEN
      fprintf0(f, "long double")
   ELSIF sym=ShortReal
   THEN
      fprintf0(f, "float")
   ELSIF sym=Bitset
   THEN
      fprintf0(f, "unsigned int")
   ELSIF sym=Address
   THEN
      fprintf0(f, "void *")
   ELSIF sym=Byte
   THEN
      fprintf0(f, "unsigned char")
   ELSIF sym=Loc
   THEN
      fprintf0(f, "unsigned char")
   ELSIF sym=Word
   THEN
      fprintf0(f, "unsigned int")
   END
END DoType ;


(*
   DoUnbounded -
*)

PROCEDURE DoUnbounded (sym: CARDINAL) ;
VAR
   n   : Name ;
   type: CARDINAL ;
BEGIN
   type := GetType(sym) ;
   DoType(GetType(type)) ;
   n := GetSymName(sym) ;
   fprintf2(f, ' *_m2_address_%a, int _m2_high_%a', n, n)
END DoUnbounded ;


VAR
   FirstBasicBlock,
   Input,
   Output,
   InOut,
   CanGuess,
   IsKnown        : BOOLEAN ;
   rs, ws         : CARDINAL ;


(*
   DoBasicBlock -
*)

PROCEDURE DoBasicBlock (bb: BasicBlock) ;
VAR
   start, end: CARDINAL ;
BEGIN
   start := GetBasicBlockStart (bb) ;
   end := GetBasicBlockEnd (bb) ;
   IF IsProcedureScope(start)
   THEN
      (* skip this basic block, as this will not modify the parameter *)
      RETURN
   ELSIF IsKnown OR CanGuess
   THEN
      (* already resolved *)
      RETURN
   ELSE
      IF (ws=0) AND (rs=0)
      THEN
         FirstBasicBlock := FALSE
      ELSIF rs=0
      THEN
         (* only written *)
         IF ws<=end
         THEN
            Output := TRUE ;
            IF FirstBasicBlock
            THEN
               IsKnown := TRUE
            ELSE
               CanGuess := TRUE
            END ;
            FirstBasicBlock := FALSE
         END
      ELSIF ws=0
      THEN
         (* only read *)
         Input := TRUE ;
         IF (rs<=end) AND FirstBasicBlock
         THEN
            IsKnown := TRUE
         ELSE
            CanGuess := TRUE
         END ;
         FirstBasicBlock := FALSE
      ELSIF rs<=ws
      THEN
         (* read before write *)
         InOut := TRUE ;
         IF (rs<=end) AND (ws<=end) AND FirstBasicBlock
         THEN
            IsKnown := TRUE
         ELSE
            CanGuess := TRUE
         END ;
         FirstBasicBlock := FALSE
      ELSE
         (* must be written before read *)
         Output := TRUE ;
         IF (rs<=end) AND (ws<=end) AND FirstBasicBlock
         THEN
            IsKnown := TRUE
         ELSE
            CanGuess := TRUE
         END ;
         FirstBasicBlock := FALSE
      END
   END
END DoBasicBlock ;


(*
   DetermineParameter -
*)

PROCEDURE DetermineParameter (procedure, param: CARDINAL) ;
VAR
   sb: ScopeBlock ;
   bb: BasicBlock ;
   we,
   re: CARDINAL ;
BEGIN
   sb := InitScopeBlock(procedure) ;
   bb := InitBasicBlocks(sb) ;
   Input := FALSE ;
   Output := FALSE ;
   InOut := FALSE ;
   CanGuess := FALSE ;
   IsKnown := FALSE ;
   FirstBasicBlock := TRUE ;
   GetReadQuads(param, RightValue, rs, re) ;
   GetWriteQuads(param, RightValue, ws, we) ;
   ForeachBasicBlockDo(bb, DoBasicBlock) ;
   KillBasicBlocks(bb) ;
   KillScopeBlock(sb)
END DetermineParameter ;


(*
   PrintDirection -
*)

PROCEDURE PrintDirection ;
BEGIN
   IF Input
   THEN
      fprintf0(f, 'INPUT')
   ELSIF Output
   THEN
      fprintf0(f, 'OUTPUT')
   ELSE
      fprintf0(f, 'INOUT')
   END
END PrintDirection ;


(*
   CalculateVarDirective -
*)

PROCEDURE CalculateVarDirective (procedure, param: CARDINAL; annotate: BOOLEAN) ;
VAR
   sym: CARDINAL ;
BEGIN
   sym := GetParameterShadowVar(param) ;
   IF sym=NulSym
   THEN
      InternalError ('why did we get here')
   ELSE
      DetermineParameter(procedure, sym) ;
      IF annotate
      THEN
         DoParamName(sym) ;
         IF IsKnown
         THEN
            fprintf0(f, ' is known to be an ') ;
            PrintDirection
         ELSIF CanGuess
         THEN
            fprintf0(f, ' is guessed to be an ') ;
            PrintDirection
         ELSE
            fprintf0(f, ' is unknown')
         END
      ELSE
         fprintf0(f, '*') ;
         IF IsKnown OR CanGuess
         THEN
            PrintDirection
         ELSE
            DoParamName(sym)
         END
      END
   END
END CalculateVarDirective ;


(*
   AnnotateProcedure -
*)

PROCEDURE AnnotateProcedure (sym: CARDINAL) ;
VAR
   son, p, i: CARDINAL ;
   needComma: BOOLEAN ;
BEGIN
   fprintf0(f, '/* Parameter: ') ;
   p := NoOfParamAny (sym) ;
   i := 1 ;
   needComma := FALSE ;
   WHILE i<=p DO
      son := GetNthParamAny(sym, i) ;
      IF IsParameterVar(son)
      THEN
         IF needComma
         THEN
            fprintf0(f, ',\n   ')
         END ;
         CalculateVarDirective(sym, son, TRUE) ;
         needComma := TRUE
      END ;
      INC(i)
   END ;
   fprintf0(f, '.  */\n\n')
END AnnotateProcedure ;


(*
   DoProcedure -
*)

PROCEDURE DoProcedure (sym: CARDINAL) : BOOLEAN ;
VAR
   son,
   p, i : CARDINAL ;
   found: BOOLEAN ;
BEGIN
   found := FALSE ;
   fprintf0(f, 'extern "C" ') ;
   IF GetType(sym)=NulSym
   THEN
      fprintf0(f, 'void') ;
   ELSE
      DoType(GetType(sym))
   END ;
   fprintf0(f, ' ') ;
   DoName(sym) ;
   fprintf0(f, ' (') ;
   p := NoOfParamAny (sym) ;
   IF p=0
   THEN
      fprintf0(f, 'void') ;
   ELSE
      i := 1 ;
      WHILE i<=p DO
         son := GetNthParamAny(sym, i) ;
         IF IsUnboundedParamAny (sym, i)
         THEN
            DoUnbounded(son)
         ELSE
            DoType(GetType(son)) ;
            fprintf0(f, ' ') ;
            IF IsParameterVar(son)
            THEN
               found := TRUE ;
               CalculateVarDirective(sym, son, FALSE)
            ELSE
               DoParamName(son)
            END
         END ;
         IF i<p
         THEN
            fprintf0(f, ', ')
         END ;
         INC(i)
      END
   END ;
   fprintf0(f, ');\n') ;
   RETURN( found )
END DoProcedure ;


(*
   DoWriteSymbol -
*)

PROCEDURE DoWriteSymbol (sym: CARDINAL) ;
BEGIN
   IF IsBaseType(sym)
   THEN
   ELSIF IsSystemType(sym)
   THEN
   ELSIF IsType(sym)
   THEN
   ELSIF IsProcedure(sym)
   THEN
      IF DoProcedure(sym)
      THEN
         AnnotateProcedure(sym)
      END
   ELSIF IsConstString(sym)
   THEN
   ELSIF IsConstLit(sym)
   THEN
   ELSIF IsVar(sym) AND (GetMode(sym)=ImmediateValue)
   THEN
   ELSIF IsVar(sym)
   THEN
      DoVar(sym)
   END
END DoWriteSymbol ;


(*
   DoCheckExported -
*)

PROCEDURE DoCheckExported (sym: WORD) ;
BEGIN
   IF IsExported(mainModule, sym)
   THEN
      DoWriteSymbol(sym)
   END
END DoCheckExported ;


(*
   IsUnique - returns TRUE if the combination of, n, and, t,
              is unique.
*)

PROCEDURE IsUnique (n: Name; t: CARDINAL) : BOOLEAN ;
VAR
   p   : UnboundedSig ;
   h, i: CARDINAL ;
BEGIN
   i := 1 ;
   h := HighIndice(uKey) ;
   WHILE i<=h DO
      p := GetIndice(uKey, i) ;
      IF (p^.type=t) AND (p^.name=n)
      THEN
         RETURN( FALSE )
      END ;
      INC(i)
   END ;
   INC(h) ;
   NEW(p) ;
   WITH p^ DO
      type := t ;
      name := n
   END ;
   PutIndice(uKey, h, p) ;
   RETURN( TRUE )
END IsUnique ;


(*
   IsTypeUnique - returns TRUE if type, t, has not been entered yet.
*)

PROCEDURE IsTypeUnique (t: CARDINAL) : BOOLEAN ;
VAR
   p   : UnboundedSig ;
   h, i: CARDINAL ;
BEGIN
   i := 1 ;
   h := HighIndice(uKey) ;
   WHILE i<=h DO
      p := GetIndice(uKey, i) ;
      IF p^.type=t
      THEN
         RETURN( FALSE )
      END ;
      INC(i)
   END ;
   RETURN( TRUE )
END IsTypeUnique ;


(*
   DoCheckUnbounded -
*)

PROCEDURE DoCheckUnbounded (sym: WORD) ;
VAR
   name      : Name ;
   type      : CARDINAL ;
   typeUnique: BOOLEAN ;
BEGIN
   IF IsParameter(sym) AND IsParameterUnbounded(sym)
   THEN
      name := GetSymName(sym) ;
      type := GetType(GetType(sym)) ;
      typeUnique := IsTypeUnique(type) ;
      IF IsUnique(name, type)
      THEN
         IF NOT includedArray
         THEN
            includedArray := TRUE ;
            fprintf0(f, '%%include "carrays.i"\n')
         END ;
         fprintf0(f, '%%') ;
         fprintf0(f, 'apply (char *STRING, int LENGTH) { (') ;
         DoUnbounded(sym) ;
         fprintf0(f, ') };\n') ;
         IF typeUnique
         THEN
            fprintf0(f, '%%array_functions(') ;
            DoType(type) ;
            fprintf0(f, ', ') ;
            DoType(type) ;
            fprintf0(f, 'Array);\n')
         END
      END
   END
END DoCheckUnbounded ;


(*
   DoWriteFile -
*)

PROCEDURE DoWriteFile (sym: CARDINAL) ;
VAR
   n: Name ;
BEGIN
   mainModule := sym ;
   n := GetSymName(sym) ;
   fprintf0(f, '/* Automatically generated by gm2 -fswig.  */\n') ;
   fprintf0(f, '%%') ;
   fprintf1(f, 'module %a\n\n', n) ;
   fprintf0(f, '%%') ;
   fprintf1(f, 'include exception.i\n\n', n) ;
   fprintf0(f, '%%') ;
   fprintf0(f, 'exception {\n') ;
   fprintf0(f, '  try {\n') ;
   fprintf0(f, '     $action\n') ;
   fprintf0(f, '  } catch (int i) {\n') ;
   fprintf0(f, '     return NULL;\n') ;
   fprintf0(f, '  }\n') ;
   fprintf0(f, '}\n\n') ;
   ForeachItemInListDo(Done, DoCheckUnbounded) ;
   fprintf0(f, '\n%%{\n') ;
   ForeachItemInListDo(Done, DoCheckExported) ;
   fprintf0(f, '%%}\n\n') ;
   ForeachItemInListDo(Done, DoCheckExported)
END DoWriteFile ;


(*
   DoGenerateSwig -
*)

PROCEDURE DoGenerateSwig (sym: CARDINAL) ;
BEGIN
   Init ;
   name := ConCat (InitStringCharStar (KeyToCharStar (GetSymName (sym))),
                   Mark (InitString ('.i'))) ;
   f := OpenToWrite (name) ;
   ForeachExportedDo (sym, DoExported) ;
   DoResolveOrder ;
   DoWriteFile (sym) ;
   Close (f) ;
   name := KillString (name) ;
   Kill
END DoGenerateSwig ;


(*
   GenerateSwigFile - if the -fswig option was specified then generate
                      a swig interface file for the main module.
*)

PROCEDURE GenerateSwigFile (sym: CARDINAL) ;
BEGIN
   IF GenerateSwig
   THEN
      DoGenerateSwig(sym)
   END
END GenerateSwigFile ;


(*
   Init -
*)

PROCEDURE Init ;
BEGIN
   InitList(Done) ;
   InitList(ToDo) ;
   uKey := InitIndex(1) ;
   includedArray := FALSE
END Init ;


(*
   Kill -
*)

PROCEDURE Kill ;
BEGIN
   KillList(Done) ;
   KillList(ToDo) ;
   uKey := KillIndex(uKey)
END Kill ;


END M2Swig.