'***************************************************************************** '* * '* AC/BASIC Compiler * '* =================== * '* Command Line Acquisition Program * '* * '* This program calls an assembly language routine to examine the runtime * '* communications block and extract useful information about the environment * '* used to launch the program. Using this information, normal AC/BASIC code * '* can be used to extract command line arguments from CLI, glean information * '* from the WorkBench message, etc. * '* * '* Note: To completely understand how this routine (and it's 68000 program) * '* function, an understanding of the ROM Kernel is fundamental. See * '* the ROM Kernel Manual: Libraries and Devices publication for more * '* information about Workbench. Refer to the Exec manual for details * '* about messages and message passing. Refer to AmigaDOS technical * '* documents for details about the Command Line Interface (CLI) * '* * '***************************************************************************** '* '* Modification History: '* '* 28 March 1988 Original version for AC/BASIC v1.3 release CCG '* '--- Declare an array to hold the assembly language subroutine DIM GetArgData%(19) '-- Useful information to decipher the offset data for Workbench messages '-- These equates come from the file "STARTUP", part of the include files '-- provided with most assemblers. The node structures have been expanded '-- and the offsets listed to the left (in parentheses) to show how the '-- offsets required were computed. '(0) WBSTARTUP EQU 0 '(0) SMMESSAGE EQU WBSTARTUP+0 * a standard message structure '(14) SMPROCESS EQU SMMESSAGE+MNSIZE * the process descriptor ' (14) MN EQU LNSIZE ' (0) LN EQU 0 ' (0) LNSUCC EQU LN+0 ' (4) LNPRED EQU LNSUCC+4 ' (8) LNTYPE EQU LNPRED+4 ' (9) LNPRI EQU LNTYPE+1 ' (10) LNNAME EQU LNPRI+1 ' (14) LNSIZE EQU LNNAME+4 '(14) MNREPLYPORT EQU MN+0 * message reply port '(18) MNLENGTH EQU MNREPLYPORT+4 * message len in bytes '(20) MNSIZE EQU MNLENGTH+2 '(24) SMSEGMENT EQU SMPROCESS+4 * a descriptor for your code '(28) SMNUMARGS EQU SMSEGMENT+4 * # of elements in ArgList '(32) SMTOOLWINDOW EQU SMNUMARGS+4 * description of window '(36) SMARGLIST EQU SMTOOLWINDOW+4 * the arguments themselves '(40) SMSIZEOF EQU SMARGLIST+4 ' '-- and here are the actual offsets into the structures derived from above sm.NumArgs% = 28 sm.ArgList% = 36 '-- Load the routine to check out the launch environment '-- As discussed in Appendix D of the AC/BASIC manual, a simple method to '-- load and run assembly language routines is to put the binary representation '-- into an array and execute the array. In this particular case, the source '-- was assembled and the hex representation was literally lifted out of the '-- assembly listing and packed into data statements. FOR x% = 0 TO 18 READ GetArgData%( x% ) NEXT x% '-- Get pointer to routine and init various stuff GetArgs& = VARPTR( GetArgData%( 0 )) CmdText& = 0 CmdLen& = 0 Launch& = 0 '-- Make pointers to the storage locations of the actual variables we '-- want to use on return. This allows the assembly language routine '-- to modify the callers local storage. CmdTextPtr& = VARPTR( CmdText& ) CmdLenPtr& = VARPTR( CmdLen& ) LaunchPtr& = VARPTR( Launch& ) '--- Call the assembly language routine CALL GetArgs&( CmdTextPtr&, CmdLenPtr&, LaunchPtr& ) IF Launch& <> 0 THEN PRINT "Program lauched from Workbench" PRINT "Workbench message is ";Launch& '--- The WB message is in Launch&. Use it and the equates given '--- earlier to chase down the sm_ArgList in the WB message. You '--- can also use similar techniques to track down other information '--- about the WB launch. Refer to Chapter 18 of "ROM Kernel Manual: '--- Libraries and Devices" for additional information about Workbench. numArgs& = PEEKL( Launch& + sm.NumArgs% ) PRINT "Number of arguments is ";numArgs& '--- Get ArgList base into ArgListPtr&. The arglist structure is: ' ' WBARG EQU 0 ' WALOCK EQU WBARG+0 * a lock descriptor ' WANAME EQU WALOCK+4 * a string relative to that lock ' WASIZEOF EQU WANAME+4 ' ' Note no 'next node' field...the arguments are contiguous relative to ' the arglist base pointer. ArgListPtr& = PEEKL(Launch& + sm.ArgList% ) FOR x% = 1 TO numArgs& ArgName& = PEEKL(ArgListPtr& + 4) a$ = "" '-- Got a valid string pointer, build and print a BASIC string WHILE PEEK(ArgName&) <> 0 a$ = a$ + CHR$(PEEK(ArgName& )) ArgName& = ArgName& + 1 WEND PRINT "Argument #";x%;" name is ";a$ ArgListPtr& = ArgListPtr& + 8 '-- Offset to next arglist node NEXT x% ELSE '--- We were launched from CLI. Build and print the command line image IF CmdLen& <= 1 THEN PRINT "Nothing given on command line." ELSE FOR x% = 1 TO CmdLen& -1 '-- Subtracting one avoids the line feed a$ = a$ + CHR$( PEEK( CmdText& + x% - 1 )) NEXT x% PRINT "The command line is ";a$ PRINT "The command line length is";CmdLen& END IF END IF INPUT "All done";x$ '---- Data statements which represent the assembled code. '---- See file "Args.asm" for the assembly language source. DATA &H47EF, &H0010, &H7000, &H2263 DATA &H22A8, &HFFBC, &H2263, &H6600 DATA &H000E, &H22A8, &HFFB0, &H2263 DATA &H22A8, &HFFB4, &H4E75, &H2280 DATA &H2263, &H2280, &H4E75 '---------------------------------------------------------------------------- END