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
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=