|
|
|
|
||
|
DEFINITION MODULE DMOpSys; (******************************************************************* Module DMOpSys ('Dialog Machine' DM_V3.0) Copyright (c) 1990-2006 by Andreas Fischlin, Olivier Roth and ETH Zurich. Purpose Provides operating system and/or platform dependent procedures such as directory management. You risk to introduce platform dependencies if you use this module. Remarks Enables in particular the sub-launching of Modula-2 subprograms or any Macintosh applications, e.g. an editor, from within a Modula-2 program. Typically this module is used to access the operating system to perform these tasks and is used from within a shell (see e.g. the RAMSES shell, Fischlin, 1990). In this context arises also the needs to have some of the other utilities readily available, e.g. to find out about the location and other properties of files and applications etc. Note that this implementation has been made with and for the underlying MacMETH compiler and linking loader (Wirth et al., 1988). Especially the latter deserves special mentioning, since it does perform a dynamic-linking loading, features which are especially supported by this module in various ways. Hints for the usage of the exported routines: The separate module DMFileNames serves for typical path and filename operations. Whenever a path parameter is required it may be used to denote a directory. E.g. 'HD:M2:Work:' denotes the folder 'Work' within the folder 'M2' within the volume with name 'HD', a hard disk. In case you wish to use the MacMETH compiler from within a Modula-2 program linked as a stand-alone application, you should call procedure EmulateMacMETHCopyProtection at least once during application start up; otherwise be warned that the compiler will refuse to work. Calling Modula-2 programs allows to profit from the very efficient dynamic-linking loader capability of the MacMETH language implementation. Note that normally any Modula-2 program module can be called as a subprogram by any other Modula-2 program. For instance the compiler or debugger are just such subprograms. Note that subprograms form a stack (LIFO-queue (Last in, First out)). As long as these subprograms are 'Dialog Machine' programs all elements on this stack, not just the top of the stack, remain visible to all others, in particular also to the user. A 'Dialog Machine' menu or window belongs always (together with its content etc.) to a particular (sub)program level. The maximum level of programs supported is exported by constant DMSystem.maxLevel. References Fischlin, A. 1990. Interactive Simulation of Environmental Systems on Working Stations. In, Möller, D. (ed.), Proc. 4. Ebernburger Gespräche, 4.-9. April 1990, Münster a. Stein/ Ebernburg, BRD, Vieweg Verlag. In prep. Wirth, N., Gutknecht, J., Heiz, W., Schär, H., Seiler, H. & Vetterli, C. 1988: MacMETH. A fast Modula-2 language system for the Apple Macintosh. User Manual. 2nd ed. Institut für Informatik ETH Zürich, Switzerland, 100pp This module belongs to the 'Dialog Machine'. Programming o Design Andreas Fischlin 06/09/1990 o Implementation Andreas Fischlin 06/09/1990 Olivier Roth 23/05/1991 ETH Zurich Systems Ecology CHN E 35.1 Universitaetstrasse 16 8092 Zurich SWITZERLAND URLs: <mailto:RAMSES@env.ethz.ch> <http://www.sysecol.ethz.ch> <http://www.sysecol.ethz.ch/SimSoftware/RAMSES> Last revision of definition: 21/04/2010 AF *******************************************************************) CONST noError = 0; notDone = -2; VAR profileFName: ARRAY [0..127] OF CHAR; (* read only, normally = 'User.Profile' *) (***************************************) (*##### Results of operations #####*) (***************************************) PROCEDURE GetLastResultCode(): INTEGER; (* Returns result code obtained from the last call to an internal system routine. If noError is returned, this means that no error was detected during the last operation. Otherwise a code >= notDone will be returned. See module DMLanguage for the interpretation of result codes. For any code not defined in there you have to refer to the platform specific information. Macintosh: Inside Macintosh, Volumes I-VI, Addison Wesley Publishing Company, Inc., Reading a.o., 1986-1991. IBM PC: Windows. Unix: System calls or routine specific error codes. *) (*************************) (*##### Volumes #####*) (*************************) PROCEDURE EjectDisk( volName: ARRAY OF CHAR; VAR done: BOOLEAN ); (* Flushes and ejects the volume volName. 'done' returns the success of the operation. The success depends on the actual hardware and the platform. *) PROCEDURE GetStartupVolName(VAR volName: ARRAY OF CHAR); (* Returns the name of the startup volume, i.e. the disk or disk partition from which the system has been booted. This function is of minor interest for Unix systems where the startup volume is the known root '/'. However, under OS X (Macintosh platform) this function returns the actual name of the startup volume. This routine is available on all platforms. *) (*****************************) (*##### Directories #####*) (*****************************) TYPE DirectoryProc = PROCEDURE (INTEGER, ARRAY OF CHAR, BOOLEAN, VAR BOOLEAN); (* Meaning of arguments: nr - position number of the file (starts with 1) dirOrFileName - name of item found in directory (without preceeding paths) isDir - tells wether item is directory exit - return TRUE unless you wish to abort the processing See procedure DoForAllFilesInDirectory *) PROCEDURE CurWorkDirectory(VAR path: ARRAY OF CHAR); (* Returns the path of the current working directory. This routine is available on all platforms. Note, path contains at the end a platform specific path separator. *) PROCEDURE CreateDir( path, dirN: ARRAY OF CHAR; VAR done: BOOLEAN ); PROCEDURE DeleteDir( path, dirN: ARRAY OF CHAR; VAR done: BOOLEAN ); (* Creates/Deletes the directory specified by path and dirN, the success of operation is returned in done (Note, a non empty directory cannot be deleted). This routine is available on all platforms. *) PROCEDURE RenameDir( path, oldDirN, newDirN: ARRAY OF CHAR; VAR done: BOOLEAN ); (* Rename the directory specified by path and oldDirN to path and newDirN, the success of operation is returned in done. This routine is available on all platforms. *) PROCEDURE DirInfo( path, dirN: ARRAY OF CHAR; VAR dirExists, containsFiles : BOOLEAN ); (* Returns if the directory specified by path and dirN exists and if it contains any other directories or files. HINT: DirInfo works also if path contains already the name of the wanted directory at the end, given you pass for dirN the empty string. This routine is available on all platforms. *) PROCEDURE DoForAllFilesInDirectory(path: ARRAY OF CHAR; dp: DirectoryProc); (* Executes dp for all files or directories residing in the directory specified by path. The first argument is the position number of the file (starts with 1), the 2nd argument of dp is the name of the file (contains no path) or if it is a directory the name of the directory (without any preceeding volume or mother directory names), the 3rd argument indicates whether the item encountered is a directory or not, the 4th argument is interpreted by DoForAllFilesInDirectory upon returning from dp as a signal to exit the loop (the parameter is in/out and is reset before each call to FALSE). The following sample program excerpt, which lists all files contained in the directory 'HD:MyWork', exemplifies a typical usage of DoForAllFilesInDirectory: ... PROCEDURE ListDir(nr: INTEGER; dirOrFileName: ARRAY OF CHAR; isDir: BOOLEAN; VAR exit: BOOLEAN); BEGIN IF nr=1 THEN WriteString("The directory contains following files: "); END(*IF*); IF NOT isDir THEN WriteLn; WriteString(dirOrFileName) END; exit := FALSE; END ListDir; ... DoForAllFilesInDirectory("HD:MyWork:",ListDir); ... This routine is available on all platforms. *) (***********************) (*##### Files #####*) (***********************) PROCEDURE GetFileDialog(prompt, fileTypes: ARRAY OF CHAR; VAR path,fileName: ARRAY OF CHAR): BOOLEAN; (* Let the user specify a file's location and name by standard open file dialog box. Only files of particular types, listed in fileTypes (each type characterized by exactly 4 characters) will be shown and offered for selection. Up to 4 file types may be specified by separating them with '|' (e.g. "TEXT|PICT|APPL|Mine"). This routine does nothing and returns FALSE if the 'Dialog Machine' is currently running in the so-called batch mode (see DMMaster routine DialogMachineIsInBatchMode). The implementation may be platform dependent. *) PROCEDURE GetApplication (prompt: ARRAY OF CHAR; VAR path, applName: ARRAY OF CHAR): BOOLEAN; (* Let the user specify an application's location and name by standard open file dialog box (equivalent to GetFileDialog('APPL',path,fileName)). This routine does nothing and returns FALSE if the 'Dialog Machine' is currently running in the so-called batch mode (see DMMaster routine DialogMachineIsInBatchMode). The implementation may be platform dependent. *) CONST inexistent = -1; notOpen = 0; readOnly = 1; alreadyWrite = 2; PROCEDURE CurrentFileUse (path,fileName: ARRAY OF CHAR): INTEGER; (* Returns how the file denoted by path and name fileName is currently used by other programs or applications. If the operation could not be performed or the file does not exist, notDone respectively inexistent is returned. If it is currently closed, notOpen is returned. If the file is currently opened by an application which has the permission to read only from the file (no write permission), then readOnly is returned. If the file is currently opened by an application which has a writing permission, alreadyWrite is returned. For instance, routine CurrentFileUse will return alreadyWrite, in all cases when the routines GetExistingFile, CreateNewFile, or Lookup from DMFiles have been used to open the file. If DMFiles.ReadOnlyLookup has been used to open a file, CurrentFileUse returns readOnly. The result of this routine may be platform dependent. NOTE: The values returned by CurrentFileUse are globally valid for all currently running programs regardless wether it is the 'Dialog Machine' or any other program which accesses the file. In particular, this is also true for the application, which calls CurrentFileUse. If you wish specifically to learn about wether a file is used by the "Dialog Machine" itself, it is better to use routines from module DMFiles. Note that on the Macintosh normally only a single application has the permission to write to a file (unless shared access should be in use). Hence, any program should avoid to write to a file which is currently already open for writing. *) PROCEDURE GetFileTypeAndCreator (path,fn: ARRAY OF CHAR; VAR type,creator: ARRAY OF CHAR); (* Returns the file's type and creator (both strings must be exactly 4 characters long) given it exists on volume/directory path and has the name fn. This routine returns the file extension in the string 'type' if run on a non-Macintosh platform or run under Mac OSX. *) PROCEDURE SetFileTypeAndCreator (path,fn: ARRAY OF CHAR; type,creator: ARRAY OF CHAR); (* This routine does nothing if run on a non-Macintosh platform or run under Mac OSX. *) PROCEDURE HasCustomIcon (path,fn: ARRAY OF CHAR): BOOLEAN; PROCEDURE SetCustomIconFlag (path,fn: ARRAY OF CHAR; cif: BOOLEAN); (* Investigate wether the custom icon flag is set or set it to cif. This routine does nothing if run on a non-Macintosh platform or run under Mac OSX. *) PROCEDURE GetFileDates (path,fn: ARRAY OF CHAR; VAR creationDate,modificationDate: LONGINT); (* Returns the file's creation and last modificaton date given it exists on volume/directory path and has the name fn. The older the file the smaller the returned long integer values, since they correspond to the number of seconds elapsed since 1st January 1904. Convert the long integer values with routine InterpreteSeconds from module DMClock. This routine is available on all platforms but its result may be platform dependent. *) PROCEDURE SetFileDates (path,fn: ARRAY OF CHAR; creationDate,modificationDate: LONGINT); (* Sets the file's creation and last modificaton date given it exists on volume/directory path and has the name fn. This routine is available on all platforms but its result may be platform dependent. *) PROCEDURE NowSeconds (): LONGINT; (* Returns current date and time from the computer's internal clock. If needed convert the returned long integer value with routine DMClock.InterpreteSeconds. This routine is available on all platforms. *) PROCEDURE TouchFileDate (path,fn: ARRAY OF CHAR); (* Force the file's last modificaton date to be that of the current date and time from the computer's internal clock, given the file exists on volume/directory path and has the name fn. This routine is available on all platforms. *) PROCEDURE CopyResourceFork (sourcePath,sourceFn, destPath, destFn: ARRAY OF CHAR; VAR done: BOOLEAN); (* Copies the whole resource fork from file source to the file dest. WARNING: If the file dest should already have a resource fork, the resources from that file will be completely lost without any warning or a chance for user interaction. If destFn is an existing file without a resource fork, CopyResourceFork adds first a resource fork and then copies all resources from source to dest. If destFn can't be found that file will be created (creator & type for ResEdit) and the resources are added. done returns the success of the overall copying process. Note: In case of creation of a new dest, neither the creation nor modification dates of the source file are retained; use SetFileDates to force also the copying of these dates. This routine is only available on the Macintosh. It does nothing on all other platforms. *) PROCEDURE CopyDataFork (sourcePath,sourceFn, destPath, destFn: ARRAY OF CHAR; VAR done: BOOLEAN); (* Copies the whole data fork from file source to the file dest. WARNING: If file dest should already have a data fork, all data from that file will be completely lost without any warning or a chance for user interaction. If destFn is an existing file without a data fork, CopyResourceFork adds first a data fork and then copies all data from source to dest. If destFn can't be found that file will be created (creator & type of sourceFn) and the data are added. done returns the success of the overall copying process. Note: In case of creation of a new dest, neither the creation nor modification dates of the source file are retained; use SetFileDates to force also the copying of these dates. This routine is available on all platforms. *) (************************************************) (*##### Start Up and Document handling #####*) (************************************************) PROCEDURE GetNameOfRunningApplication (VAR name: ARRAY OF CHAR); (* Returns the name of the currently running application. If you need the path to the folder where it is running, use procedure CurWorkDirectory. The implementation of this routine is platform dependent. Note, on the Macintosh the running application is NOT the subprogram you may be executing, while you are making use of the dynamic linking loader provided by MacMETH or RAMSES. For the MacOS the running application is only the application the MacOS knows about. Typically this is the MacMETH or RAMSES Shell. Only if you link your 'Dialog Machine' program as a double-clickable stand-alone application, will this routine return the name of your 'Dialog Machine' program. *) TYPE InitDocuHandlingProc = PROCEDURE ( INTEGER ); DocuHandler = PROCEDURE ( INTEGER, ARRAY OF CHAR, ARRAY OF CHAR, VAR BOOLEAN ); PROCEDURE InstallInitDocuOpening (idhp: InitDocuHandlingProc); PROCEDURE InstallInitDocuPrinting (idhp: InitDocuHandlingProc); PROCEDURE InstallOpenDocuHandler (dh: DocuHandler); PROCEDURE InstallPrintDocuHandler (dh: DocuHandler); (* Above handlers support the opening respectively printing of document files bundled with a 'Dialog Machine' program at start up time or under Windows or MacOS 7 (or later) while the 'Dialog Machine' program is already running. Typically when double clicking a document belonging to a 'Dialog Machine' program, the opening handlers will be executed as installed by above procedures. Depending whether the user has requested the printing or just the opening of the documents, either the printing or the opening handlers are called accordingly. At the begin of the sequence the initialization procedure (InitDocuHandlingProc) is called by the 'Dialog Machine'; hereby the integer parameter nrDocs, i.e. the number of documents to be processed, is passed to the installed initialization procedure. Afterwards the 'Dialog Machine' loops from 1 to nrDocs by calling for each document the installed handler (DocuHandler). First an index for the document (range [1..nrDocs]) is passed, then the file name (a full path and file name, which can be directly used as an argument for DMFiles.Lookup), the type (e.g. 'TEXT' or 'TXT'), and the flag continue set to the value TRUE. In case the installed handler procedure decides to exit the loop, it may set the flag continue to FALSE, and the 'Dialog Machine' will terminate the loop. In case that the user has issued a printing request, the Dialog Machine program will be quit immediately after having printed the last document. The implementation of this routine is platform dependent. *) (***************************************) (*##### Using Non-DM Programs #####*) (***************************************) PROCEDURE SubLaunch (path, prog: ARRAY OF CHAR); (* May be used to launch any other application. This includes also applications which are not 'Dialog Machine' programs. On a Macintosh make sure if you launch a native OS X application (Carbon or Cocoa application) to specify the prog parameter properly by adding the extension '.app'. In the Finder the extension '.app' of such applications is normally not visible. The implementation is platform dependent. *) PROCEDURE Transfer (path, prog: ARRAY OF CHAR); (* May be used for transferring (quit current program and launch prog) to any other application. This includes also applications which are not 'Dialog Machine' programs. On a Macintosh make sure if you launch a native OS X application (Carbon or Cocoa application) to specify the prog parameter properly by adding the extension '.app'. In the Finder the extension '.app' of such applications is normally not visible. The implementation is platform dependent. *) PROCEDURE ExecuteForResult (command: ARRAY OF CHAR; VAR result: ARRAY OF CHAR); (* Executes a command on the host operating system. It returns the result in the string 'result'. E.g. on Unix the command "/bin/ls -l" will return in 'result' the standard output of the executed command. Use GetLastResultCode to learn about the success. In case of failure 'result' is the empty string. IMPORTANT NOTE: There is no warranty for the success of this routine; it is highly NON-PORTABLE! IMPLEMENTATION RESTRICTIONS: Works under Unix in a limited way, i.e. commands have either to be programs in the working directory or need to be passed to this routine with absolute paths. Arguments containing blanks need to be double quoted. Any other quoting fails. *) PROCEDURE IsForegroundProgram(): BOOLEAN; (* Returns whether the calling program is currently in the foreground and receives the user's attention with the highest priority. The implementation may be platform dependent. *) PROCEDURE BringProgramToForeground; (* Brings the calling program to the foreground where it receives the user's attention with the highest priority. The implementation may be platform dependent. *) PROCEDURE PutProgramIntoBackground; (* Puts the calling program into the background. There it receives the user's attention no longer with the highest priority. The implementation may be platform dependent. *) PROCEDURE QuitDialogMachineInBackground; (* Similar to DMMaster.AbortDialogMachine but manages to quit the running 'Dialog Machine' program while it is in the background. The implementation may be platform dependent. *) (*************************************************) (*##### Inter Application Communication #####*) (*************************************************) (* Functions available only on Macintosh under System 7.0 or later *) TYPE MessageResponder = PROCEDURE (ARRAY OF CHAR, ARRAY OF CHAR, INTEGER); PROCEDURE SetMessageResponder( mr: MessageResponder); PROCEDURE GetMessageResponder(VAR mr: MessageResponder); (* Simple basic mechanism to respond to messages from other programs under MacOS System 7 (or later). Given the 'Dialog Machine' receives a message from an other application where the message class is 'DMEv' ('Dialog Machine' Event) or 'MnCh' (Menu Choice), the 'Dialog Machine' will respond to this message in the manner tabulated below. Otherwise the the 'Dialog Machine' ignores the event and passes it on to the Apple Event Manager. Event class Action taken i.e. value of by DM field message in EventRecord ------------------------------------------------------------------ 'MnCh' While responding to an event of this class the 'Dialog Machine' interprets the eventID (EventRecord.where) to execute a menu command within the receiving DM program. The eventID is interpreted as follows: high word contains the menuID (All following menus numbered consecutively starting at the Apple menu with number 128), the low word denotes the menu item or command number (starting at the topmost command with the number 1). Note that hierarchical submenus matter. E.g. if the first menu right to the Apple menu with ID 129 has a hierarchical menu, the second menu next to the first will have ID 131 and not 130, since the hierarchical menu gets ID 130. Using ResEdit to learn about the menu IDs may be helpful if the DM program uses predefined menus (resource type MENU). Commands are numbered from 1. Note that separators count fully as if they would be a menu command and that the status of a menu command does not matter. If a menu command is currently disabled, a 'MnCh' event for that command will simply have no effect. 'DMEv' While responding to an event of this class the 'Dialog Machine' calls the currently installed responder by passing it the eventClass (EventRecord.message) as the first, the eventID (EventRecord.where) as the second and the EventRecord.modifiers as the third argument. any other value Event is ignored by the receiving DM program The implementation of this routine is highly platform dependent. *) PROCEDURE SignalMessageToApplication(creatorOfAppl, eventClass, eventID: ARRAY OF CHAR; msgVal: INTEGER; VAR resultCode: INTEGER); (* Simple basic mechanism to send a message to another program under MacOS System 7 (or later, i.e. including OS X). Signals a message to the application running on the local machine, i.e. not through the network, which is identified via the creatorOfAppl, e.g. 'MSWD' for Microsoft Word or 'MEDT' for MEdit editor. All other input parameters must be interpreted by the receiving application and are used in the following way when constructing the event record before sending it: parameter is assigned E.g. Possible meaning to EventRecord and action field taken by receiving application ------------------------------------------------------------------ eventClass message 'MnCh' use eventID as if the user has chosen a menu command eventID where 'quit' causes another program to be quit msgVal modifiers 3 An additional integer to be sent to the receiver (possibly ignored) Note that calling SignalMessageToApplication with the eventClass = 'MnCh' leads to the following interpretation of the parameters: eventID denotes the menu and command IDs. E.g. the menuID of the Apple menu is 129, thus pass '129' as the actual parameter value for argument eventID. You may find out about menu IDs by using ResEdit and opening the receiving applications resources of type 'MENU'. msgVal denotes the menu item, e.g. 1. Note that separators or submenu items count like normal items and that the top item in a menu is item 1. Example: SignalMessageToApplication('RAMS','MnCh', '129', 1, res); This will cause the RAMSES Shell (has the creator 'RAMS') to execute the 1st menu command in the menu with ID = 129, i.e. the about command 'About RAMSES Shell...' in the Apple menu. Both actual arguments eventClass and eventID should always contain exactly 4 characters. Otherwise blanks will be appended or only the first 4 characters will be recognized. The only reporting on success which is available is the resultCode ( no error = 0; for other codes see Inside Macintosh Vol. VI p. 5-31, values returned by PostHighLevelEvent). The postingOptions is always only = receiverIDisSignature (see also Inside Macintosh Vol. VI p. 5-30), hence no receipt can be requested. Note that Apple core events are implemented in any 'Dialog Machine' program by default. Most applications are capable to respond to these events in the wanted manner. According to Inside Macintosh VI 6-106 Apple core events are specified as follows: parameter is assigned E.g. Possible meaning to EventRecord and action field taken by receiving application ------------------------------------------------------------------ eventClass message 'aevt' is Apple core event eventID where 'oapp' open application = kAEOpenApplication eventID where 'odoc' open document = kAEOpenDocuments eventID where 'pdoc' print document = kAEPrintDocuments eventID where 'quit' quit application = kAEQuitApplication msgVal modifiers 0 ignored or pointer to document list IMPORTANT IMPLEMENTATION INFORMATION: ------------------------------------ On the Macintosh platform the data are internally stored in the following data structure, the so-called EventRecord before a message is sent to another application: TYPE EventRecord = RECORD what: Integer; {event code} message: LongInt; {event message} when: LongInt; {ticks since startup} where: Point; {mouse location} modifiers: Integer; {modifier flags} END; Point = RECORD v,h: INTEGER; END; For event class 'MnCh' the actual menu choice needs to be stored in field where: The menuID is stored in where.v, the number of the menu item (command) in where.h. This is exactly the format in which a Macintosh applications expect to find the selection of any ordinary menu choice, i.e. one made by the user. If a 'Dialog Machine' program receives such an EventRecord via an Apple Event, the effect is the same as if you would call DMMenus.ExecuteCommand(Menu(menuID), Command(itemNo)). It is for your convenience only, that you may call SignalMessageToApplication by passing the menuID and the menu item number as two separate arguments. As a consequence you can't send any modifiers. Note also, the event class 'MnCh' is not generally recognized by Macintosh applications. Only all 'Dialog Machine' programs recognize this event class. The use of the fields what and when are reserved for internal use. The implementation of this routine is highly platform dependent. *) (**************************************) (*##### User event emulation #####*) (**************************************) (* Use these procedures to emulate a 'Dialog Machine' user event received by the running 'Dialog Machine' program *) PROCEDURE EmulateKeyPress(ch: CHAR; modifier: BITSET); (* Emulates the user event keyboard pressed (see module DMKeyChars for a description of modifiers or see Inside Macintosh Toolbox Event manager). The implementation of this routine is platform dependent. *) PROCEDURE EmulateMenuSelection(aliasChar: CHAR); (* Emulates the user event menu selection via a keyboard equivalent. Implementation restriction: Only menus which have an alias char installed can be selected by this mechanism. The implementation of this routine is platform dependent. *) PROCEDURE EmulateMouseDown(x,y: INTEGER; modif: BITSET); (* Emulates the user event mouse click at background coordinates x,y and with modifiers modif (see module DMKeyChars for a description of modifiers or see Inside Macintosh Toolbox Event manager). *) (*************************************) (*##### Machine environment #####*) (*************************************) (* The following routines have no effect on platforms, which don't support these functions for an ordinary user. For instance under Unix you require super user privileges to reboot (RestartMachine) or to shut the machine down (TurnMachineOff). *) PROCEDURE TurnMachineOff; (* terminates any running program and turns the power off *) PROCEDURE RestartMachine; (* terminates any running program and reboots *) (**************************************) (*##### Modula-2 environment #####*) (**************************************) (* ----------------------------------------------------------------- The following routines are of relevance on platforms where a dynamic linking-loader is available. Cyrrently this is the case only for MacMETH on the Macintosh. On other platforms, program levels remain always the same and the use of the following routines makes little sense. ----------------------------------------------------------------- *) TYPE ProgStatus = (regular, moduleNotFound, fileNotFound, illegalKey, readError, badSyntax, noMemory, alreadyLoaded, killed, tooManyPrograms, continue, noApplication); (* Note: in current implementation matches also type DMLinkLoader.ProgStatus from MacMETH*) PROCEDURE SetNewPaths; (* Reads a new path definition from the text file with the name profileFName (is normally 'User.Profile') and updates all 'Dialog Machine' file acessing routines (DMFiles, DMSubLaunch, compiler, linker, editor) such that those paths become accessible. *) PROCEDURE CallDMSubProg (prog: ARRAY OF CHAR; leaveLoaded: BOOLEAN; VAR st: ProgStatus); (* Calls (i.e. sublaunches) a Modula-2 (sub)program by using the dynamic linking loader; i.e. only those modules are loaded which are not already in memory. The program level increases automatically, so that the whole module environment can be released upon returning from this procedure and the program level is set back to what it was before the call. In case that leaveLoaded = TRUE the memory block holding the program will not be actually released but can be reused for any subsequent calls to this procedure without having to get the program from disk again. Note that in the latter case the initializing bodies of the modules are still rexecuted as if the (sub)program would have been loaded anew. (NOTE: Implementation restriction: The names of the module and the file in which its code is stored must exactly match, even the extension 'OBM' is disallowed. Otherwise there will an error occur, i.e. the status alreadyLoaded is returned when returning from the second call to this procedure). (Sub)Programs are located following a search strategy which uses a path definition which must be given in the text file with the name profileFName (User.Profile). The latter file must reside in the same folder as the starting application (usually the shell or any other linked stand-alone application made with the 'Dialog Machine'). Path definitions must follow this syntax given in EBNF (start symbol is PathDefinition): PathDefinition = 'PATH' path { ',' path }. path = [VolName] { ':' FolderName | ':' } ':'. VolName = String. FolderName = String. String = char { char }. (Remark: all characters (including ' ') are allowed except ':', however it is recommended to avoid also the use of ',' and '.' in folder names due to some not well understood Macintosh operating system idiosynchrasies sometimes causing program crashes at start-up, sometimes not). Ex.: PATH HD:M2:Work:, :DMLib:, :RAMSESLib:, :Work:MyProject:, Another Disk:M2:Work:Another Project:, ::Utilities: Remark to the semantics of relative paths defintions: A path definition starting with ':' signifies a relative path, i.e. a path which starts at the folder in which the file with name profileFName (User.Profile) resides. If one uses absolute paths, they must not start with ':' and then always indicate a full path starting with the volume name. In the example given the last path using the folder Utilities is preceeded by the construct '::' is located relative to the start-up folder in which the file with name profileFName (User.Profile) resides on a level above (father/mother level). Path definitions can be changed anytime during program execution but must then be reentered into the system by calling routine DMSubLaunch.SetNewPaths. *) PROCEDURE CallM2SubProg (prog: ARRAY OF CHAR; leaveLoaded: BOOLEAN; VAR st: ProgStatus); (* Same as CallDMSubProg but is called with a slightly different level management, i.e. the program is called on the level just above the current subprogram level. Hence this procedure is should only be called from the System.TopDMLevel(). It is the subprogram mechanism used by the underlying MacMETH system and is reserved to special purposes. Typically this procedure is never used unless a MacMETH compiler, editor or linker shall be called. *) PROCEDURE IncludeLibModules (prog: ARRAY OF CHAR; VAR st: ProgStatus); (* Same as CallM2SubProg but the program level is not incremented and remains the same. As a consequence you should not call with this technique program modules (you would not return from it anymore) but only library modules since you return from this procedure only if it just executes the bodies of library modules. Neither is it possible to set the flag leaveLoaded, since it is always interpreted as beeing the same as the including program. Finally it is neither possible to release the used memory unless the whole currnet program level is left. *) PROCEDURE UnLoadM2Progs; (* Releases all memory occupied by Modula-2 (sub)programs previously called with leaveLoaded = TRUE. *) PROCEDURE EmulateMacMETHCopyProtection; (* Emulates the MacMETH copy protection, so that the compiler can be freely executed, e.g. via CallM2SubProg, from anywhere. Note that without calling EmulateMacMETHCopyProtection the MacMETH compilers will refuse to work properly. *) PROCEDURE SetCompilerFileTypes(creator, sbmType, obmType, rfmType: ARRAY OF CHAR); PROCEDURE GetCompilerFileTypes(VAR creator, sbmType, obmType, rfmType: ARRAY OF CHAR); (* Allows to control the creator and the corresponding Macintosh file type used by the MacMETH compiler. During compilation it may create symbol files (SBM file), object code files (OBM file), and debugger information holding reference files (RFM file). Note that the file type used depends solely on the file's name, i.e. each file ending with the extension '.SBM' is treated as a symbol file etc. Initial defaults are SetCompilerFileTypes('RAMS','MSYM','MOBJ','MREF'); Note: In accordance with Macintosh file system rules, all strings must be exactly 4 characters long. Note: the defaults are restored upon termination of the environment of this module. *) (**********************************) (*##### Program Abortion #####*) (**********************************) PROCEDURE AbortM2Prog (st: ProgStatus); (* Aborts the currently running program level without executing any remaining portions of its code except for the installed termination procedures (see DMSystem.InstallTermProc). The program status on which to terminate is given by st. On the Unix platform this routine corresponds to typing Control^C. The implementation of this routine is platform dependent. *) END DMOpSys.
|
||
|
|
|