MODULE Importer; (* * REPERTOIRE * Release 1.6 * By Charles Bradford and Cole Brecheen * (c) Copyright 1985-1990 PMI * Green Bay, WI * All rights reserved * (414) 468-6040 * *) IMPORT EnvironUtils; IMPORT ErrorManager; IMPORT GenLists; IMPORT ImpLists; IMPORT KbdInput; IMPORT ListUtils; IMPORT LowLevel; IMPORT M2Strings; IMPORT Numbers; IMPORT Parser; IMPORT PosUtils; IMPORT StrEdit; IMPORT StringIO; IMPORT SYSTEM; IMPORT InitCompilerMods; (*# call(reg_param => (), near_call => off, ds_eq_ss => off) *) (*# data(near_ptr => off) *) VAR x, fname1, fname2, CurrentWord, LastWord: ARRAY [0..79] OF CHAR; Terminator: CHAR; StartOfImpList, EndOfImpList, LineCnt, ColCnt: CARDINAL; TextList, TmpList, Imports: GenLists.GenList; cnt, FoundSpot, dumc: CARDINAL; Sorting, Unqualifying, Qualifying : BOOLEAN; Dumstr: ARRAY [0..0] OF CHAR; PROCEDURE yes( TheQuestion: ARRAY OF CHAR ): BOOLEAN; VAR tmpkey: CARDINAL; BEGIN StringIO.WriteEol( StringIO.outp, '' ); StringIO.WriteStr( StringIO.outp, TheQuestion ); tmpkey := KbdInput.CAPkey( KbdInput.KeyHit( KbdInput.YorN ) ); IF ORD('Y') = tmpkey THEN StringIO.WriteStr( StringIO.outp, 'yes' ); RETURN TRUE; ELSIF ORD('Q') = tmpkey THEN ErrorManager.StraightToDOS(''); END; StringIO.WriteStr( StringIO.outp, 'no' ); RETURN FALSE; END yes; PROCEDURE NextWord( VAR TheStr: ARRAY OF CHAR ); BEGIN Parser.GetNextWord( TextList, LineCnt, ColCnt, TheStr, Terminator ); M2Strings.Assign( CurrentWord, LastWord ); M2Strings.Assign( TheStr, CurrentWord ); END NextWord; PROCEDURE StrInList( TheStr: ARRAY OF CHAR; TheList: GenLists.GenList ): BOOLEAN; VAR ListEnd, cnt: CARDINAL; tmpstr: ARRAY [0..79] OF CHAR; BEGIN ListEnd := GenLists.ListLength(TheList); FOR cnt := 1 TO ListEnd DO ListUtils.GetStr( TheList, cnt, tmpstr ); IF PosUtils.Equal( tmpstr, TheStr ) THEN RETURN TRUE; END; END; RETURN FALSE; END StrInList; PROCEDURE InsertElmts( ToBeInserted: GenLists.GenList; VAR IntoThis: GenLists.GenList; AtThisSpot: CARDINAL ); VAR lngth1, tmpsize, cnt, TypeCode: CARDINAL; tmpadr: SYSTEM.ADDRESS; BEGIN lngth1 := GenLists.ListLength( ToBeInserted ); FOR cnt := lngth1 TO 1 BY -1 DO (* it's simpler to insert backwards *) GenLists.GetElmtAdr( ToBeInserted, cnt, tmpadr, tmpsize, TypeCode ); GenLists.ListInsertAdr( tmpadr, tmpsize, TypeCode, IntoThis, AtThisSpot ); END; END InsertElmts; PROCEDURE Alphabetize( adr1: SYSTEM.ADDRESS; size1: CARDINAL; adr2: SYSTEM.ADDRESS; size2: CARDINAL ): INTEGER; VAR tmp1, tmp2: ARRAY [0..79] OF CHAR; BEGIN LowLevel.Move( adr1, SYSTEM.ADR(tmp1), Numbers.Min(size1, 79) ); tmp1[Numbers.Min(size1, 79)] := 0C; LowLevel.Move( adr2, SYSTEM.ADR(tmp2), Numbers.Min(size2, 79) ); tmp2[Numbers.Min(size2, 79)] := 0C; StrEdit.CAPstr( tmp1 ); StrEdit.CAPstr( tmp2 ); RETURN M2Strings.CompareStr( tmp1, tmp2 ); END Alphabetize; PROCEDURE MakeSortedImpList( TopList: GenLists.GenList; VAR OutList: GenLists.GenList ); VAR SubList: GenLists.GenList; TopListEnd, TopListCount: CARDINAL; SubListCount: CARDINAL; x: ARRAY [0..31] OF CHAR; WorkStr: ARRAY [0..1023] OF CHAR; BEGIN TopListCount := 0; TopListEnd := GenLists.ListLength(TopList); IF TopListEnd < 2 THEN RETURN; END; GenLists.NewList( OutList ); REPEAT WorkStr := ''; INC( TopListCount ); ListUtils.GetStr( TopList, TopListCount, x ); (* x now ought to contain a module name *) INC( TopListCount ); GenLists.GetChildList( TopList, TopListCount, SubList ); IF GenLists.Initialized( SubList ) THEN GenLists.SortList( SubList, Alphabetize ); StrEdit.Append( WorkStr, 'FROM ' ); StrEdit.Append( WorkStr, x ); StrEdit.Append( WorkStr, ' IMPORT ' ); SubListCount := 1; LOOP ListUtils.GetStr( SubList, SubListCount, x ); StrEdit.Append( WorkStr, x ); INC( SubListCount ); IF SubListCount > GenLists.ListLength(SubList) THEN StrEdit.Append( WorkStr, ';' ); EXIT; ELSE StrEdit.Append( WorkStr, ', ' ); END; END; ELSE (* This is a FromLess import *) StrEdit.Append( WorkStr, 'IMPORT ' ); StrEdit.Append( WorkStr, x ); StrEdit.Append( WorkStr, ';' ); END; GenLists.ListInsert( WorkStr, GenLists.StrCode, OutList, 65535 ); UNTIL TopListCount = TopListEnd; GenLists.SortList( OutList, Alphabetize ); ListUtils.CheckLength( OutList, 5, 75 ); END MakeSortedImpList; PROCEDURE InImportList( VAR TheWord: ARRAY OF CHAR; ImportList: GenLists.GenList; VAR ModuleName: ARRAY OF CHAR ): BOOLEAN; VAR SubList: GenLists.GenList; TopListCount: CARDINAL; BEGIN TopListCount := 0; REPEAT INC( TopListCount ); ListUtils.GetStr( ImportList, TopListCount, ModuleName ); INC( TopListCount ); GenLists.GetChildList( ImportList, TopListCount, SubList ); IF GenLists.Initialized( SubList ) AND StrInList(TheWord, SubList) THEN RETURN TRUE; END; UNTIL TopListCount = GenLists.ListLength(ImportList); RETURN FALSE; END InImportList; PROCEDURE IsModuleName( ModuleName: ARRAY OF CHAR; ImportList: GenLists.GenList; VAR SubList: GenLists.GenList ): BOOLEAN; VAR TopListCount: CARDINAL; tmpstr: ARRAY [0..79] OF CHAR; BEGIN TopListCount := 0; GenLists.NilList( SubList ); REPEAT INC( TopListCount ); ListUtils.GetStr( ImportList, TopListCount, tmpstr ); INC( TopListCount ); IF PosUtils.Equal( ModuleName, tmpstr ) THEN GenLists.GetChildList( ImportList, TopListCount, SubList ); RETURN TRUE; END; UNTIL TopListCount = GenLists.ListLength(ImportList); RETURN FALSE; END IsModuleName; PROCEDURE QualifyAll(); VAR TopListCount: CARDINAL; tmpstr: ARRAY [0..79] OF CHAR; ModuleName: ARRAY [0..31] OF CHAR; TextEnd, ImportsEnd, LastLine : CARDINAL; LocalNilList, SubList: GenLists.GenList; BEGIN LastLine := 0; TextEnd := GenLists.ListLength(TextList); ImportsEnd := GenLists.ListLength(Imports); REPEAT NextWord( CurrentWord ); IF InImportList( CurrentWord, Imports, ModuleName ) THEN M2Strings.Insert( '.', Parser.TheLine, Parser.LastIndex ); M2Strings.Insert( ModuleName, Parser.TheLine, Parser.LastIndex ); GenLists.ListReplace( Parser.TheLine, GenLists.StrCode, TextList, LineCnt ); INC( ColCnt, M2Strings.Length(ModuleName) + 1 ); END; IF LineCnt > LastLine THEN StringIO.WriteStr( StringIO.outp, '.' ); LastLine := LineCnt; END; UNTIL LineCnt >= TextEnd; TopListCount := 0; GenLists.NilList( LocalNilList ); REPEAT INC( TopListCount, 2 ); GenLists.ListReplace( LocalNilList, GenLists.ListCode, Imports, TopListCount ); (*ListReplace takes care of deallocating the old list. Note that we don't do GetChildList's and DisposeList's because that wouldn't nil out the copy of the pointer that's in the Imports list.*) UNTIL TopListCount >= ImportsEnd; END QualifyAll; PROCEDURE UnqualifyAll(); VAR ModuleName, tmpstr: ARRAY [0..31] OF CHAR; SubList: GenLists.GenList; LastLine : CARDINAL; BEGIN LastLine := 0; REPEAT NextWord( CurrentWord ); IF IsModuleName( CurrentWord, Imports, SubList ) AND (Terminator = '.') THEN M2Strings.Assign( CurrentWord, ModuleName ); NextWord( CurrentWord ); IF NOT GenLists.Initialized( SubList ) THEN GenLists.NewList( SubList ); GenLists.ListReplace( SubList, GenLists.ListCode, Imports, GenLists.ElmtNow(Imports) ); END; IF NOT StrInList( CurrentWord, SubList ) THEN GenLists.ListInsert( CurrentWord, GenLists.StrCode, SubList, 65535 ); END; StrEdit.Append( ModuleName, '.' ); StrEdit.ReplaceStr( ModuleName, '', Parser.TheLine ); GenLists.ListReplace( Parser.TheLine, GenLists.StrCode, TextList, LineCnt ); DEC( ColCnt, M2Strings.Length(ModuleName) + 1 ); END; IF LineCnt > LastLine THEN StringIO.WriteStr( StringIO.outp, '.' ); LastLine := LineCnt; END; UNTIL LineCnt >= GenLists.ListLength(TextList); END UnqualifyAll; BEGIN IF NOT EnvironUtils.ParsedParam( 1, fname1 ) THEN StringIO.WriteStr( StringIO.outp, 'File name: ' ); StringIO.ReadStr( StringIO.inp, fname1 ); IF M2Strings.Length(fname1) = 0 THEN RETURN; END; END; PosUtils.CaseSensitive := FALSE; IF NOT PosUtils.Present( '.', fname1 ) THEN StrEdit.Append( fname1, '.mod' ); END; PosUtils.CaseSensitive := TRUE; IF NOT EnvironUtils.ParsedParam( 2, Dumstr ) THEN Qualifying := yes( 'Qualify all imported identifiers? '); IF Qualifying THEN Unqualifying := FALSE; Sorting := FALSE; ELSE Unqualifying := yes( 'Unqualify all qualified identifiers? '); IF Unqualifying THEN Sorting := FALSE; ELSE Sorting := yes( 'Sort identifiers in present import list? '); END; END; ELSE Sorting := CAP(Dumstr[0]) = 'S'; Qualifying := CAP(Dumstr[0]) = 'Q'; Unqualifying := CAP(Dumstr[0]) = 'U'; END; LineCnt := 1; ColCnt := 0; StartOfImpList := 0; EndOfImpList := 0; GenLists.NewList( TextList ); StringIO.PrintMessage( ListUtils.TextFileToList( fname1, TextList ) ); LastWord := ''; CurrentWord := ''; ImpLists.ExtractImportList( TextList, Imports, StartOfImpList, EndOfImpList ); IF Qualifying THEN QualifyAll(); ELSIF Unqualifying THEN UnqualifyAll(); END; IF StartOfImpList > 0 THEN MakeSortedImpList( Imports, TmpList ); GenLists.DisposeList( Imports ); GenLists.ListDelete( TextList, StartOfImpList, EndOfImpList - StartOfImpList + 1 ); GenLists.ListInsert( '', GenLists.StrCode, TextList, StartOfImpList ); (* insert a blank line to separate imports from rest of program *) InsertElmts( TmpList, TextList, StartOfImpList ); GenLists.DisposeList( TmpList ); END; StringIO.PrintMessage( ListUtils.TextListToFile( TextList, fname1 ) ); GenLists.DisposeList( TextList ); END Importer.