Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!cbmvax!carolyn From: carolyn@cbmvax.cbm.UUCP (Carolyn Scheppner) Newsgroups: comp.sys.amiga Subject: Re: Pattern Matching & documentation, & flame to C-A Message-ID: <1136@cbmvax.cbmvax.cbm.UUCP> Date: Wed, 17-Dec-86 21:49:49 EST Article-I.D.: cbmvax.1136 Posted: Wed Dec 17 21:49:49 1986 Date-Received: Thu, 18-Dec-86 21:43:39 EST References: <8612152348.AA29410@cory.Berkeley.EDU> <1135@cbmvax.cbmvax.cbm.UUCP> Reply-To: carolyn@cbmvax.UUCP (Carolyn Scheppner) Organization: Commodore Technology, West Chester, PA Lines: 336 This is for everyone but Matt Dillon who has been rather rude lately. I've spent the past three days typing this in between phone calls and after hours. I even had to type the first hundred lines in twice because our VAX went down before I had saved the file. The following is a summary of an article that Tim King wrote for the CBM UK developer's newsletter. He sheds some light on the inner workings of AmigaDOS. carolyn -------------------------------------------------------------------------- Some AmigaDOS Info from Tim King ================================ GLOBAL VECTOR ============= To cut down on link times, BCPL allows modules to link at run-time. Different modules communicate using a common data area known as the "global vector". The global vector is a large table containing global variables and addresses of global routines that all modules know about. Note that the global vector table is for the internal convenience of AmigaDOS. It is likely to vary from version to version, and application programs are not supposed to use it. Most references to "global vector" refer to one master table used by the whole of AmigaDOS. However some processes such as the file-handler are tied together using their own private global vector. WORDS and BPTRs =============== The only data type supported by BCPL is the machine-word. In 68000 BCPL implementations this is a 32-bit quantity (LONG or ULONG). AmigaDOS makes use of normal machine addresses (APTRs) internally. For example, entries in the global vector corresponding to global routines are usually APTRs. However, since BCPL does everything in terms of long-words, its own pointers are expressed as pointers to long-words called BPTRs. (BPTR = APTR/4) Note that anything accessed via a BPTR must be long-word aligned. (in other words, have an address evenly divisible by 4) STRINGS and BSTRs ================= A C string is a pointer to a string of characters terminated by a null. A BCPL string (BSTR) is a BPTR to a structure containing the lenghth of the string in the first byte, with the actual string characters following. Be warned that references to BSTRs normally mean a BPTR to a BSTR structure, but sometimes refer to the BSTR itself. SEGMENT LISTS ============= Another BCPL structure used extensively by AmigaDOS is a "Segment List". This is a simple forward linked list: -------------------- -------------------- -------------------- | Length of seg | | Length of seg | | Length of seg | | BPTR to next seg |--->| BPTR to next seg |--/ /-->| Null (no more) | | Data | | Data | | Data | -------------------- -------------------- -------------------- An example of this type of list is the segment list created by the scatter loader. THE AMIGADOS KERNEL =================== AmigaDOS consists of a small "kernel" written in assembler, plus various "processes" such as file-handlers and CLIs, mostly written in BCPL, plus various "devices" such as DF0: and CON:, also written mostly is BCPL but interfacing to "device drivers" written in assembler. AmigaDOS uses exec as its kernel, and makes use of Exec "devices" such as trackdisk.device as its device drivers. THE AMIGADOS LIBRARY ==================== The AmigaDOS "library" is organized so that it can be accessed as either an Exec library (dos.library) or as a Tripos-style resident library. As an Exec library, DOS is somewhat peculiar. It does not support Expunge() and its jump table does not consist of jump instructions. Instead, the table consists of a series of six-byte entries (same length as jump instruction) organized as follows: MOVEQ #entry_number_in_global_vector, D0 BRA action MOVEQ #another_entry_number_in_global_vector, D0 BRA action etc. The "action" routine, which is in the library positive offset area, grabs 1500 bytes below your current stack pointer for use as a BCPL stack and sets up A1 as a BCPL stack pointer. BCPL stacks are used from the bottom upwards. No bounds check is done on this so you better have 1500 bytes available on your stack when you call AmigaDOS. It then zeros a0, and sets up registers A2 = global vector, A5 = DOS kernel action routine from ROM, and A6 = DOS kernel cleanup routine from ROM, from locations which are also in the library positive offsets, and puts the appropriate action address from the global vector table into A4. The ROM is now invoked by JSR (A5), and deals with the call. This often involves constructing the appropriate "packet" for the DOS call in question, sending it to the right process, and waiting for a reply indicating successful completion or an error. Note that D1, D2, D3, and D4 are used to pass values to AmigaDOS. Results are returned form the ROM action routine in D1, then transferred to D0 for return to the calling program. PROCESSES ========= A Process is the basic structure used to control multi-tasking in AmigaDOS. It is built on the Exec concept of a Task, and consists of an Exec task control block, a message port, and some things needed by AmigaDOS. A process can be distinguished from a task by the task control block's node type which will be either NT_PROCESS or NT_TASK. The process message port is used by AmigaDOS for its own "packet" based communication between processes. The other things following the message port include the current directory lock for the process and the current input and output "streams" (handles for the current input and output files). Anything which calls AmigaDOS directly or indirectly (for example by opening a disk-resident Amiga library or font) must be a Process rather than a simple Task. Most of the Amiga's tasks are processes. Workbench, CLI, the file system, and the handlers for AmigaDOS devices (CON, PRT, etc.) are processes. The only simple tasks are things such as Exec devices (printer.device, input.device, etc). AmigaDOS refers to each process by its Process ID, which is an APTR to the message port in the Process structure. This is the pointer returned by CreateProc(). To find the Process structure subtract the size of a Task structure from this APTR. PACKETS ======= The "packet" is the basic unit of message-passing in AmigaDOS and it is built on the Exec concept of a "message". The part of the message structure defined as pointer to a name is used instead to point to a Tripos structure called a "packet", as follows: APTR back to message structure APTR to reply port LONG packet type LONG result1 LONG result2 LONG argument1 LONG argument2 etc. AmigaDOS gets things done by sending "packets" like this to the message-ports of appropriate processes such as file-handlers. Note that you can also get things done by sending packets to processes, instead of calling AmigaDOS library routines. This is handy if you want to operate asynchronously. COROUTINE ========= Co-routine is a term from Tripos useful in understanding AmigaDOS. The term means a routine which is executed as part of a particular process, but using its own private stack instead of the process's standard stack. When a co-routine is about to be invoked, memory is allocated for its stack by the process, the stack pointer is saved then altered to point at this new stack, and the new stack is initialized to contain its own size, plus a return address to the main process. Then the co-routine is invoked. When the co-routine exits, control returns to the main process code, which restores its stack pointer to the old value and de-allocates the co-routine's stack memory. This technique is used by a CLI process to execute commands. The fact that the process pushes the size of the stack to the new stack is significant here, as it means that you can check if you've been given enough stack space, and refuse to run if you haven't. CLI === A CLI is a Process with some special attributes including: a CLI number (1 to 20) standard input and output streams (usually a CON: device) a path list to use when searching for command files a prompt string definition default stack size for co-routines The CLI provides a user interface, executes commands typed in at the keyboard or read in from a file and provides IO redirection. Some special setup is needed to start a CLI (initializing input and output streams etc.), and another process is needed to do this. It is important not to confuse the process which creates a CLI (such as the CLI tool you click on from Workbench) with the actual CLI process once running. The standard code for handling the CLI environment is in KickStart. COMMANDS ======== A "command" is code which is executed from a CLI process when it is invoked by name, usually loaded from a disk file with the same name as the command. AmigaDOS looks for commands in the current or specified directory, or in the C: directory. Under 1.2, it is possible to specify further directory paths to be searched for commands by using the PATH command. Commands are executed as part of the CLI process from which they are invoked. Stack space for the command's use is allocated and control is passed to the code at the start of the first segment of the command's code. On entry to the command's code, the registers contain: A0 a pointer to the command line for execution D0 the length of the command line Other registers contain defined, but not documented, values. These are irrelevant to command written in C or assembler. However, commands written in BCPL will expect to be entered with these registers properly initialized: A1 BCPL stack pointer A2 global vector etc., very much as set up by the DOS "action" routine explained above. This explains why it is not possible, for example, to load NewCli or DiskEd with Wack and execute them with GO, since these registers will not contain the appropriate values. Commands run as co-routines under the CLI will generally start with some form of standard startup code (eg LStartup.obj or AStartup.obj) which amongst other things deal with obtaining the current CLI input and output streams, and using them to set up their own IO vectors such as C "stdin" and "stdout". There is a significant difference here between programs started from CLI and those started from Workbench. A program started from Workbench is a separate process, rather than a co-routine of CLI, and has no default input or output stream. Some startups (such as LStartup) provide these streams by opening a CON: window on the Workbench. Commands are not required to preserve any registers, and the main process can not rely on any being preserved when the co-routine exits. REDIRECTION =========== When a CLI process obtains a command line for execution, it checks for redirection specifications in the form of AmigaDOS file or device names preceded by < (input redirection) or > (output redir.). The CLI will attempt to perform the requested redirection, so that the current input and output streams are those asked for, before control is passed to the command's code. The command will only respond to the redirection if it uses the default input/output streams (stdin/stdout in C) for its IO. DEVICES, DEVICES, and DEVICES ============================= Like "library", the word "device" is somewhat overworked on the Amiga, being used to refer to 3 different things: 1. Exec device (as in OpenDevice(), trackdisk.device) 2. AmigaDOS device, which is an interface between AmigaDOS and an Exec device (as in SER:, DF0:, PRT:) 3. Logical AmigaDOS device name a. an AmigaDOS device as in #2 b. the volume name of a disk (such as Extras:) c. a directory with a sytem or user ASSIGNed logical device name (such as C:, SYS:, THISISMEFOLKS:) HANDLER PROCESSES ================= AmigaDOS devices (as in #2 above) have associated processes for performing the actions required of them. These can be compared with the associated tasks used by some Exec devices such as the console.device, and are known as handler processes. The AmigaDOS function DeviceProc() allows you to obtain the Process ID for the handler process of a named AmigaDOS device. example: df0handlerID = DeviceProc("DF0:"); Handler processes generally have the same name as their device but without the colon. However, this is not always the case. The floppy disk handlers (for DF0:, DF1:, ...) are each called "File System". The handler for a CON: window is called CON. Each open CON: or RAW: window will have its own handler, so it is commaon to have many processes with these names present. One cannot use DeviceProc() to find the handler process for a CON: or a RAW: because there may be more than one handler for the specified device. Handler processes speend much of their time in wait states, waiting to receive AmigaDOS packets at their message ports asking them to perform some action, such as reading or writing data or closing a file. They then perform the required action, then reply the packet to the sender. --------------------------------------------------------------- -- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Carolyn Scheppner -- CBM >>Amiga Technical Support<< UUCP ...{allegra,caip,ihnp4,seismo}!cbmvax!carolyn PHONE 215-431-9180 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=