(**************************************************************************)
(*                                                                        *)
(* Definition Module DosD by Marcel Timmermans.                           *)
(* Date     : 21 Feb 1994                                                 *)
(* Language : Modula-2                                                    *)
(*                                                                        *)
(**************************************************************************)

(*$ Implementation- *)
DEFINITION MODULE DosD; 

FROM SYSTEM IMPORT ADDRESS,BYTE,LONGSET,WORD,CAST;

FROM ExecD IMPORT
 Library,LibraryPtr,MemReqSet,Message,MessagePtr,MinList,MinNode
 ,MsgPort,MsgPortPtr,Node,SignalSemaphore,Task,TaskPtr;

FROM Timer IMPORT
 TimeRequestPtr;

FROM UtilityD IMPORT
 HookPtr,tagUser,TagItemPtr;

IMPORT Reg;

TYPE 
  StrPtr=ADDRESS;
  BPTR=BPOINTER TO LONGINT;
  BSTR=BPOINTER TO ARRAY[0..255] OF CHAR;
  AChainPtr=POINTER TO AChain;
  AnchorPathPtr=POINTER TO AnchorPath;
  AssignListPtr=POINTER TO AssignList;
  CliProcListPtr=POINTER TO CliProcList;
  CommandLineInterfaceAPtr=POINTER TO CommandLineInterface;
  CommandLineInterfacePtr=BPOINTER TO CommandLineInterface;
  CSourcePtr=POINTER TO CSource;
  DatePtr=POINTER TO Date;
  DateTimePtr=POINTER TO DateTime;
  DeviceListPtr=BPOINTER TO DeviceList;
  DeviceNodePtr=POINTER TO DeviceNode;
  DevProcPtr = POINTER TO DevProc;
  DosEnvecPtr=BPOINTER TO DosEnvec;
  DosInfoPtr=BPOINTER TO DosInfo;
  DosLibraryPtr=POINTER TO DosLibrary;
  DosListPtr=POINTER TO DosList;
  DosPacketPtr=POINTER TO DosPacket;
  ErrorStringPtr=POINTER TO ErrorString;
  ExAllControlPtr=POINTER TO ExAllControl;
  ExAllDataPtr=POINTER TO ExAllData;
  FileHandlePtr=BPOINTER TO FileHandle;
  FileInfoBlockPtr=POINTER TO FileInfoBlock;
  FileLockPtr=BPOINTER TO FileLock;
  FileSysStartupMsgPtr=BPOINTER TO FileSysStartupMsg;
  InfoDataPtr=POINTER TO InfoData;
  LocalVarPtr=POINTER TO LocalVar;
  NotifyMsgPtr=POINTER TO NotifyMessage;
  NotifyRequestPtr=POINTER TO NotifyRequest;
  PathLockPtr=BPOINTER TO PathLock;
  ProcessPtr=POINTER TO Process;
  RDArgsPtr=POINTER TO RDArgs;
  RecordLockPtr=POINTER TO RecordLock;
  SegmentPtr=POINTER TO Segment;
  RootNodePtr=POINTER TO RootNode;
  StandardPacketPtr=POINTER TO StandardPacket;
  TaskArrayAPtr=POINTER TO TaskArray;
  TaskArrayPtr=BPOINTER TO TaskArray;
  ProcessId=MsgPortPtr;

CONST
 dosName="dos.library";

  oldFile  =1005;  (* Open existing file read/write
                    * positioned at beginning of file. *)
  newFile  =1006;  (* Open freshly created file (delete
                    * old file) read/write, exclusive lock. *)
  readWrite=1004;  (* Open old file w/shared lock,
                    * creates file if doesn't exist. *)

(* Relative position to Seek() *)
  beginning  =-1;      (* relative to Begining Of File *)
  current    = 0;      (* relative to Current file position *)
  end        = 1;      (* relative to End Of File    *)

  bitsPerByte  =8;
  bytesPerLong =4;
  bitsPerLong  =32;
  maxInt       =7FFFFFFFH;
  minInt       =80000000H;

(* Passed as type to Lock() *)
  sharedLock    =-2;    (* File is readable by others *)
  accessRead    =-2;    (* Synonym *)
  exclusiveLock =-1;    (* No other access allowed    *)
  accessWrite   =-1;    (* Synonym *)

TYPE
  Date=RECORD
    days:LONGINT;          (* Number of days since Jan. 1, 1978 *)
    minute:LONGINT;        (* Number of minutes past midnight *)
    tick:LONGINT;          (* Number of ticks past minute *)
  END;

CONST
  ticksPerSecond=50;       (* Number of ticks in one second *)


TYPE

(* FIB stands for FileInfoBlock *)

(* FIBB are bit definitions, FIBF are field definitions *)
(* Regular RWED bits are 0 == allowed. *)
(* NOTE: GRP and OTR RWED permissions are 0 == not allowed! *)
(* Group and Other permissions are not directly handled by the filesystem *)

  ProtectionMask = (
    delete,     (* prevent file from being deleted *)
    execute,    (* ignored by system, used by Shell *)
    writeProt,  (* ignored by old filesystem *)
    readProt,   (* ignored by old filesystem *)
    archive,    (* cleared whenever file is changed *)
    pure,       (* program is reentrant and rexecutable *)
    script,     (* program is a script (execute) file *)
    pm7,
    grpDelete,  (* Group: prevent file from being deleted *)
    grpExecute, (* Group: file is executable *)
    grpWrite,   (* Group: file is writable *)
    grpRead,    (* Group: file is readable *)
    otrDelete,  (* Other: prevent file from being deleted *)
    otrExecute, (* Other: file is executable *)
    otrWrite,   (* Other: file is writable *)
    otrRead,    (* Other: file is readable *)
    pm16,pm17,pm18,pm19,pm20,pm21,pm22,pm23,pm24,pm25,
    pm26,pm27,pm28,pm29,pm30,pm31);

  ProtectionMaskSet=SET OF ProtectionMask;

(* Returned by Examine() and ExNext(), must be on a 4 byte boundary *)
  FileInfoBlock=RECORD
    diskKey:LONGINT;
    dirEntryType:LONGINT;           (* Type of Directory. If < 0, then a plain file.
                                     * If > 0 a directory *)
    fileName:ARRAY[0..107] OF CHAR; (* Null terminated. Max 30 chars used for now *)
    protection:ProtectionMaskSet;   (* bit mask of protection, rwxd are 3-0.      *)
    entryType:LONGINT;
    size:LONGINT;                   (* Number of bytes in file *)
    numBlock:LONGINT;               (* Number of blocks in file *)
    date:Date;                      (* Date file last changed *)
    comment:ARRAY[0..79] OF CHAR;   (* Null terminated comment associated with file *)

   (* Note: the following fields are not supported by all filesystems.        *)
   (* They should be initialized to 0 sending an ACTION_EXAMINE packet.       *)
   (* When Examine() is called, these are set to 0 for you.           *)
   (* AllocDosObject() also initializes them to 0.                    *)
    ownerUID:INTEGER;            (* owner's UID *)
    ownerGID:INTEGER;            (* owner's GID *)

    reserved:ARRAY[0..31] OF CHAR;
  END;

CONST
(* Standard maximum length for an error string from fault.  However, most *)
(* error strings should be kept under 60 characters if possible.  Don't   *)
(* forget space for the header you pass in. *)
  faultMax=82;

TYPE
(* returned by Info(), must be on a 4 byte boundary *)
  InfoData=RECORD
    numSoftErrors : LONGINT;   (* number of soft errors on disk *)
    unitNumber    : LONGINT;   (* Which unit disk is (was) mounted on *)
    diskState     : LONGINT;   (* See defines below *)
    numBlocks     : LONGINT;   (* Number of blocks on disk *)
    numBlocksUsed : LONGINT;   (* Number of block in use *)
    bytesPerBlock : LONGINT;
    diskType      : LONGINT;   (* Disk Type code *)
    volumeNode    : DeviceListPtr; (* BCPL pointer to volume node *)
    inUse         : LONGINT;   (* Flag, zero if not in use *)
  END;

CONST

(* InfoData.diskState *)
  writeProtect = 80;    (* Disk is write protected *)
  validating   = 81;    (* Disk is currently being validated *)
  validated    = 82;    (* Disk is consistent and writeable *)

(* InfoData.diskType *)
(* Any other new filesystems should also, if possible. *)
  noDiskPresent        = -1;
  unreadableDisk       = CAST(LONGINT,'BAD\o');
  dosDisk              = CAST(LONGINT,'DOS\o');
  ffsDisk              = CAST(LONGINT,'DOS\x01');
  interDosDisk         = CAST(LONGINT,'DOS\x02');
  interFFSDisk         = CAST(LONGINT,'DOS\x03');
  fastDirDosDisk       = CAST(LONGINT,'DOS\x04');
  fastDirFFSDisk       = CAST(LONGINT,'DOS\x05');
  notReallyDos         = CAST(LONGINT,'NDOS' );
  kickStartDisk        = CAST(LONGINT,'KICK' );
  msdosDisk            = CAST(LONGINT,'MSD\o');

(* Errors from IoErr(), etc. *)
  noFreeStore                = 103;
  taskTableFull              = 105;
  badTemplate                = 114;
  badNumber                  = 115;
  requiredArgMissing         = 116;
  keyNeedsArg                = 117;
  tooManyArgs                = 118;
  unmatchedQuotes            = 119;
  lineTooLong                = 120;
  fileNotObject              = 121;
  invalidResidentLibrary     = 122;
  noDefaultDir               = 201;
  objectInUse                = 202;
  objectExists               = 203;
  dirNotFound                = 204;
  objectNotFound             = 205;
  badStreamName              = 206;
  objectTooLarge             = 207;
  actionNotKnown             = 209;
  invalidComponentName       = 210;
  invalidLock                = 211;
  objectWrongType            = 212;
  diskNotValidated           = 213;
  diskWriteProtected         = 214;
  renameAcrossDevices        = 215;
  directoryNotEmpty          = 216;
  tooManyLevels              = 217;
  deviceNotMounted           = 218;
  seekError                  = 219;
  commentTooBig              = 220;
  diskFull                   = 221;
  deleteProtected            = 222;
  writeProtected             = 223;
  readProtected              = 224;
  notADosDisk                = 225;
  noDisk                     = 226;
  noMoreEntries              = 232;
(* added for 1.4 *)
  isSoftLink                 = 233;
  objectLinked               = 234;
  badHunk                    = 235;
  notImplemented             = 236;
  recordNotLocked            = 240;
  lockCollision              = 241;
  lockTimeOut                = 242;
  unLockError                = 243;

(* These are the return codes used by convention by AmigaDOS commands *)
(* See FAILAT and IF for relvance to EXECUTE files                    *)
  ok    =  0; (* No problems, success *)
  warn  =  5; (* A warning only *)
  error = 10; (* Something wrong *)
  fail  = 20; (* Complete or severe failure*)

(* Bit numbers that signal you that a user has issued a break *)
  ctrlC = 12;
  ctrlD = 13;
  ctrlE = 14;
  ctrlF = 15;

(* Values returned by SameLock() *)
  same        = 0;
  sameHandler = 1;      (* actually same volume *)
  different   =-1;

(* types for ChangeMode() *)
  changeLock  = 0;
  changeFH    = 1;

(* Values for MakeLink() *)
  hard = 0;
  soft = 1; (* softlinks are not fully supported yet *)

(* values returned by ReadItem *)
  equal      = -2;    (* "=" Symbol *)
  itemError  = -1;    (* error *)
  nothing    =  0;    (* *N, ;, endstreamch *)
  unQuoted   =  1;    (* unquoted item *)
  quoted     =  2;    (* quoted item *)

(* types for AllocDosObject/FreeDosObject *)
  fileHandle    = 0;      (* few people should use this *)
  exAllControl  = 1;      (* Must be used to allocate this! *)
  fib           = 2;      (* useful *)
  stdpkt        = 3;      (* for doing packet-level I/O *)
  cli           = 4;      (* for shell-writers, etc *)
  rdArgs        = 5;      (* for ReadArgs if you pass it in *)

TYPE
 DateFormat=(
    formatDOS,    (* dd-mmm-yy *)
    formatINT,    (* yy-mm-dd  *)
    formatUSA,    (* mm-dd-yy  *)
    formatCDN     (* dd-mm-yy  *)
 );

CONST
 formatMAX=MAX(DateFormat);
 lenDatString=16;

TYPE
 DateTimeFlags=(subst,future,dtf2,dtf3,dtf4,dtf5,dtf6,dtf7);
 DateTimeFlagSet=SET OF DateTimeFlags;

 DateTime = RECORD
  date    : Date;             (* DOS Date *)
  format  : DateFormat;       (* controls appearance of dat_StrDate *)
  flags   : DateTimeFlagSet;  (* see BITDEF's below *)
  strDay  : StrPtr;           (* day of the week string *)
  strDate : StrPtr;           (* date string *)
  strTime : StrPtr;           (* time string *)                        
 END;


(***********************************************************************
************************ PATTERN MATCHING ******************************
************************************************************************

* structure expected by MatchFirst, MatchNext.
* Allocate this structure and initialize it as follows:
*
* Set ap_BreakBits to the signal bits (CDEF) that you want to take a
* break on, or NULL, if you don't want to convenience the user.
*
* If you want to have the FULL PATH NAME of the files you found,
* allocate a buffer at the END of this structure, and put the size of
* it into ap_Length.  If you don't want the full path name, make sure
* you set ap_Length to zero.  In this case, the name of the file, and stats
* are available in the ap_Info, as per usual.
*
* Then call MatchFirst() and then afterwards, MatchNext() with this structure.
* You should check the return value each time (see below) and take the
* appropriate action, ultimately calling MatchEnd() when there are
* no more files and you are done.  You can tell when you are done by
* checking for the normal AmigaDOS return code ERROR_NO_MORE_ENTRIES.
*
*)

TYPE
 AnchorPathFlags=( 
  doWild,     (* User option ALL *)
  itsWild,    (* Set by MatchFirst, used by MatchNext *)
              (* Application can test itsWild, too *)
  doDir,      (* Bit is SET if a DIR node should be *)
              (* entered. Application can RESET this *)
              (* bit after MatchFirst/MatchNext to AVOID *)
              (* entering a dir. *)
  didDir,     (* Bit is SET for an "expired" dir node. *)
  noMemErr,   (* Set on memory error *)
  doDot,      (* If set, allow conversion of '.' to *)
              (* CurrentDir *)
  dirChanged  (* ap_Current->an_Lock changed *)
              (* since last MatchNext call *)
);
AnchorPathFlagSet=SET OF AnchorPathFlags;

 AnchorPath=RECORD
  base,                          (* pointer to first anchor *)
  last:AChainPtr;                (* pointer to last anchor *)
  breakBits:LONGSET;             (* Bits we want to break on *)
  foundBreak:LONGSET;            (* Bits we broke on. Also returns ERROR_BREAK *)
  flags:AnchorPathFlagSet;       (* New use for extra word. *)                    
  reserved:SHORTINT;
  strLen:INTEGER;                (* This is what ap_Length used to be *)
  info:FileInfoBlock;
  (*ARRAY[0..strLen-1] OF CHAR*) (* Buffer for path name, allocated by user *)
 END;

 AChainFlags=(
  patternBit,examinedBit,completed,allBit,single,acf5,acf6,acf7
 );
 AChainFlagSet=SET OF AChainFlags;

  AChain = RECORD
        child  : AChainPtr;
        parent : AChainPtr;
        lock   : FileLockPtr;
        info   : FileInfoBlock;
        flags  : AChainFlagSet;
        (*string : SIZE ?? UBYTE an_String[1];	(* FIX!! *) *);
  END;

CONST
(*
 * Constants used by wildcard routines, these are the pre-parsed tokens
 * referred to by pattern match.  It is not necessary for you to do
 * anything about these, MatchFirst() MatchNext() handle all these for you.
 *)

  pAny           = 80H;    (* Token for '*' or '#?  *)
  pSingle        = 81H;    (* Token for '?' *)
  pOrStart       = 82H;    (* Token for '(' *)
  pOrNext        = 83H;    (* Token for '|' *)
  pOrEnd         = 84H;    (* Token for ')' *)
  pNot           = 85H;    (* Token for '~' *)
  pNotEnd        = 86H;    (* Token for *)
  pNotClass      = 87H;    (* Token for '^' *)
  pClass         = 88H;    (* Token for '[]' *)
  pRepBeg        = 89H;    (* Token for '[' *)
  pRepEnd        = 8AH;    (* Token for ']' *)
  pStop          = 8BH;    (* Token to force end of evaluation *)

(* Values for an_Status, NOTE: These are the actual bit numbers *)

  complexBit   = 1;       (* Parsing complex pattern *)
  examineBit   = 2;       (* Searching directory *)

(*
 * Returns from MatchFirst(), MatchNext()
 * You can also get dos error returns, such as ERROR_NO_MORE_ENTRIES,
 * these are in the dos.h file.
 *)

  bufferOverflow = 303;     (* User or internal buffer overflow *)
  break          = 304;     (* A break character was received *)
  notExecutable  = 305;     (* A file has E bit cleared *)


TYPE
 ProcessFlags=(
  freeSegList,freeCurrDir,freeCLI,closeInput,closeOutput,freeArgs,
  pr6,pr7,pr8,pr9,pr10,pr11,pr12,pr13,pr14,pr15,pr16
 );
 ProcessFlagSet=SET OF ProcessFlags;

(* All DOS processes have this structure *)
(* Create and Device Proc returns pointer to the MsgPort in this structure *)
(* dev_proc = (struct Process * ) (DeviceProc(..) - sizeof(struct Task)); *)

 Process=RECORD
  task:Task;                    
  msgPort:MsgPort;          (* This is BPTR address from DOS functions  *)
  pad:WORD;                 (* Remaining variables on 4 byte boundaries *)
  segList:BPTR;             (* Array of seg lists used by this process  *)
  stackSize:LONGINT;        (* Size of process stack in bytes           *)
  globVec:ADDRESS;          (* Global vector for this process (BCPL)    *)
  taskNum:LONGINT;          (* CLI task number of zero if not a CLI     *)
  stackBase:BPTR;           (* Ptr to high memory end of process stack  *)
  result2:LONGINT;          (* Value of secondary result from last call *)
  currentDir:FileLockPtr;   (* Lock associated with current directory   *)
  cis:FileHandlePtr;        (* Current CLI Input Stream                 *)
  cos:FileHandlePtr;        (* Current CLI Output Stream                *)
  consoleTask:ProcessId;    (* Console handler process for current window*)
  fileSystemTask:ProcessId; (* File handler process for current drive   *)
  cli:CommandLineInterfacePtr;(* pointer to CommandLineInterface          *)
  returnAddr:ADDRESS;       (* pointer to previous stack frame          *)
  pktWait:ADDRESS;          (* Function to be called when awaiting msg  *)
  windowPtr:ADDRESS;        (* Window for error printing                *)                       

  (* following definitions are new with 2.0 *)
  homeDir: FileLockPtr;     (* Home directory of executing program      *)
  flags:ProcessFlagSet;     (* flags telling dos about process          *)
  exitCode:PROC;            (* code to call on exit of program or NULL  *)
  exitData:ADDRESS;         (* Passed as an argument to pr_ExitCode.    *)
  arguments:StrPtr;         (* Arguments passed to the process at start *)
  localVars:MinList;        (* Local environment variables             *)
  shellPrivate:LONGCARD     (* for the use of the current shell         *);
  ces:FileHandlePtr;        (* Error stream - if NULL, use pr_COS       *)      
 END;

(* The long word address (BPTR) of this structure is returned by
 * Open() and other routines that return a file.  You need only worry
 * about this struct to do async io's via PutMsg() instead of
 * standard file system calls *)

 FileHandle=RECORD
  link:MessagePtr;    (* EXEC message              *)
  port:MsgPortPtr;    (* Reply port for the packet *)
  type:ProcessId;     (* Port to do PutMsg() to
                       * Address is negative if a plain file *)
  buf:LONGINT;
  pos:LONGINT;
  end:LONGINT;
  func1:LONGINT;
  func2:LONGINT;
  func3:LONGINT;
  arg1:LONGINT;
  arg2:LONGINT;
 END;

(* This is the extension to EXEC Messages used by DOS *)
 DosPacket=RECORD
  link:MessagePtr;    (* EXEC message              *)
  port:MsgPortPtr;    (* Reply port for the packet *)
                      (* Must be filled in each send. *)
  type:LONGINT;       (* See ACTION_... below and
                       * 'R' means Read, 'W' means Write to the
                       * file system *)                     
  res1:LONGINT;       (* For file system calls this is the result    (* status *)
                       * that would have been returned by the
                       * function, e.g. Write ('W') returns actual
                       * length written *)
  res2:LONGINT;       (* For file system calls this is what would 
                       * have been returned by IoErr() *)
  arg1:LONGINT;
  arg2:LONGINT;
  arg3:LONGINT;
  arg4:LONGINT;
  arg5:LONGINT;
  arg6:LONGINT;
  arg7:LONGINT;
 END;
 
(* A Packet does not require the Message to be before it in memory, but
 * for convenience it is useful to associate the two.
 * Also see the function init_std_pkt for initializing this structure *)

 StandardPacket=RECORD
  msg:Message;
  pkt:DosPacket;
 END;

CONST
(* Packet types *)
  nil              = 0;
  startup          = 0;
  getBlock         = 2;       (* OBSOLETE *)
  setMap           = 4;
  die              = 5;
  event            = 6;
  currentVolume    = 7;
  locateObject     = 8;
  renameDisk       = 9;
  write            = ORD('W');
  read             = ORD('R');
  freeLock         = 15;
  deleteObject     = 16;
  renameObject     = 17;
  moreCache        = 18;
  copyDir          = 19;
  waitChar         = 20;
  setProtect       = 21;
  createDir        = 22;
  examineObject    = 23;
  examineNext      = 24;
  diskInfo         = 25;
  info             = 26;
  flush            = 27;
  setComment       = 28;
  parent           = 29;
  timer            = 30;
  inhibit          = 31;
  diskType         = 32;
  diskChange       = 33;
  setDate          = 34;

  screenMode       = 994;

  readReturn       = 1001;
  writeReturn      = 1002;
  seek             = 1008;
  findUpdate       = 1004;
  findInput        = 1005;
  findOutput       = 1006;
  actionEnd        = 1007;
  setFileSize      = 1022;    (* fast file system only in 1.3 *)
  writeprotect     = 1023;    (* fast file system only in 1.3 *)

(* new 2.0 packets *)
  sameLock         = 40;
  changeSignal     = 995;
  format           = 1020;
  makeLink         = 1021;
  (**)
  (**)
  readLink         = 1024;
  fhFromLock       = 1026;
  isFileSystem     = 1027;
  changeMode       = 1028;
  (**)
  copyDirFH        = 1030;
  parentFH         = 1031;
  examineAll       = 1033;
  examineFH        = 1034;

  lockRecord       = 2008;
  freeRecord       = 2009;

  addNotify        = 4097;
  removeNotify     = 4098;

(* Added in V39: *)
  examineAllEnd    = 1035;
  setOwner         = 1036;

TYPE
(*
 * A structure for holding error messages - stored as array with error == 0
 * for the last entry.
 *)

 ErrorString=RECORD
  nums: ADDRESS;
  strings:ADDRESS;
 END;

(* DOS library node structure.
 * This is the data at positive offsets from the library node.
 * Negative offsets from the node is the jump table to DOS functions
 * node = (struct DosLibrary * ) OpenLibrary( "dos.library" .. )      *)

 DosLibrary=RECORD
  lib:Library;
  root:RootNodePtr;   (* Pointer to RootNode, described below *)
  gv:ADDRESS;         (* Pointer to BCPL global vector        *)
  a2:LONGINT;         (* Private register dump of DOS         *)
  a5:LONGINT;
  a6:LONGINT;
  errors:ErrorStringPtr;    (* pointer to array of error msgs *)
  timeReq:TimeRequestPtr;   (* private pointer to timer request *)
  utilityBase:LibraryPtr;   (* private ptr to utility library *)  
  intuitionBase:LibraryPtr; (* private ptr to intuition library *)
 END;

 RootNodeFlags=(
  rnf0,private1,rnf2,rnf3,rnf4,rnf5,rnf6,rnf7
  ,rnf8,rnf9,rnf10,rnf11,rnf12,rnf13,rnf14,rnf15
  ,rnf16,rnf17,rnf18,rnf19,rnf20,rnf21,rnf22,rnf23
  ,wildStar,rnf25,rnf26,rnf27,rnf28,rnf29,rnf30,rnf31
 );
 RootNodeFlagSet=SET OF RootNodeFlags;

 RootNode=RECORD
  taskArray:TaskArrayPtr; (* [0] is max number of CLI's
                           * [1] is APTR to process id of CLI 1
                           * [n] is APTR to process id of CLI n *)
  consoleSegment:SegmentPtr;  (* SegList for the CLI                      *)
  time:Date;                  (* Current time                             *)
  restartSeg:BPTR;            (* SegList for the disk validator process   *)
  info:DosInfoPtr;            (* Pointer to the Info structure            *)
  fileHandlerSegment:SegmentPtr;  (* segment for a file handler           *)
  cliList:MinList;            (* new list of all CLI processes *)               
                              (* the first cpl_Array is also rn_TaskArray *)
  bootProc:ProcessId;         (* private ptr to msgport of boot fs      *)
  shellSegment:SegmentPtr;    (* seglist for Shell (for NewShell)         *)
  flags:RootNodeFlagSet;     (* dos flags *)
 END;

 TaskArray=RECORD
  maxCli:LONGINT; (* max number of CLI's in this entry (n) *)
  cli:ARRAY [1..99] OF ProcessId; (* CPTR to process id of CLI *)
 END;

 CliProcList=RECORD
  node:MinNode;
  first:LONGINT;        (* number of first entry in array *)
  array:TaskArrayAPtr;
 END;

 DosInfo=RECORD
  mcName:BPTR;          (* PRIVATE: system resident module list	     *)
  devInfo:DeviceListPtr;(* Device List                               *)
  devices:BPTR;         (* Currently zero                            *)
  handlers:BPTR;        (* Currently zero                            *)
  netHand:ProcessId;    (* Network handler processid; currently zero *)
  devLock:SignalSemaphore;      (* do NOT access directly! *)
  entryLock:SignalSemaphore;    (* do NOT access directly! *)
  deleteLock:SignalSemaphore;   (* do NOT access directly! *)
 END;


(* structure for the Dos resident list.  Do NOT allocate these, use       *)
(* AddSegment(), and heed the warnings in the autodocs!                   *)

 Segment=RECORD
  next:BPTR;
  uc:LONGINT;
  seg:BPTR;
  name:ARRAY[0..3] OF CHAR; (* actually the first 4 chars of BSTR name *)
 END;

CONST

  cmdSystem   = -1;
  cmdInternal = -2;
  cmdDisabled = -999;

(* DOS Processes started from the CLI via RUN or NEWCLI have this additional
 * set to data associated with them *)

TYPE
  PathLock = RECORD
    next:PathLockPtr;
    lock:FileLockPtr;
  END;


 CommandLineInterface=RECORD
  result2:LONGINT;            (* Value of IoErr from last command        *)
  setName:BSTR;               (* Name of current directory               *)
  commandDir:PathLockPtr;     (* Head of the path locklist               *)
  returnCode:LONGINT;         (* Return code from last command           *)
  commandName:BSTR;           (* Name of current command                 *)
  failLevel:LONGINT;          (* Fail level (set by FAILAT)              *)  
  prompt:BSTR;                (* Current prompt (set by PROMPT)          *)    
  standardInput:FileHandlePtr;(* Default (terminal) CLI input            *)      
  currentInput:FileHandlePtr; (* Current CLI input                       *)    
  commandFile:BSTR;           (* Name of EXECUTE command file            *)  
  interactive:LONGINT;        (* Boolean; True if prompts required       *)    
  background:LONGINT;         (* Boolean; True if CLI created by RUN     *)      
  currentOutput:FileHandlePtr;(* Current CLI output                      *)      
  defaultStack:LONGINT;       (* Stack size to be obtained in long words *)        
  standardOutput:FileHandlePtr(* Default (terminal) CLI output           *);       
  module:BPTR;                (* SegList of currently loaded command     *)      
 END;

(* This structure can take on different values depending on whether it is
 * a device, an assigned directory, or a volume.  Below is the structure
 * reflecting volumes only.  Following that is the structure representing
 * only devices. Following that is the unioned structure representing all
 * the values
 *)

 (* Combined structure of DeviceList, Doslist and DevInfo *)

 DeviceListType=(device,directory,volume,late,nonBinding);
 DeviceList=RECORD
  next:DeviceListPtr;   (* bptr to next device list *)
  pad1,pad2,pad3:BYTE;  (* pad Bytes for padding to LONGINT *)
  type:DeviceListType;  (* See above *)
  task:ProcessId;       (* ptr to handler task *)
  lock:FileLockPtr;     (* not for volumes *)          
  CASE :DeviceListType OF
  | device:                       
   handler:BSTR;                  (* file name to load if seglist is null *)
   stackSize:LONGINT;             (* stacksize to use when starting process *)
   priority:LONGINT;              (* task priority when starting process *)
   startup:FileSysStartupMsgPtr;  (* startup msg: FileSysStartupMsg for disks *)
   segList:BPTR;                  (* already loaded code for new task *)
   globVec:BPTR;                  (* BCPL global vector to use when starting      
                                   * a process. -1 indicates a C/Assembler
                                   * program. *)
  | volume:
   volumeDate:Date;               (* creation date *)
   lockList:FileLockPtr;          (* outstanding locks *)
   diskType:LONGINT;              (* 'DOS', etc *)               
   unused:LONGINT
  | directory,late,nonBinding:
   assignName:ADDRESS;            (* name for non-or-late-binding assign *)
   list:AssignListPtr;            (* for multi-directory assigns (regular) *)
  END;
  name:BSTR;
 END;
 DosList    = DeviceList;
 DeviceNode = DeviceList;

(* structure used for multi-directory assigns. AllocVec()ed. *)

 AssignList=RECORD
  next:AssignListPtr;
  lock:FileLockPtr;
 END;

 DevProcFlags=(
  unlock,assign,dpf2,dpf3,dpf4,dpf5,dpf6,dpf7
  ,dpf8,dpf9,dpf10,dpf11,dpf12,dpf13,dpf14,dpf15
  ,dpf16,dpf17,dpf18,dpf19,dpf20,dpf21,dpf22,dpf23
  ,dpf24,dpf25,dpf26,dpf27,dpf28,dpf29,dpf30,dpf31
 );
 DevProcFlagSet=SET OF DevProcFlags;

 DevProc=RECORD
  port:MsgPortPtr;
  lock:FileLockPtr;
  flags:DevProcFlagSet;
  devNode:DosListPtr; (* DON'T TOUCH OR USE! *)
 END;

 LockDosFlags=(
  ldbRead,ldbWrite,devices,volumes,assigns,entry,ldbDelete,ldb7
  ,ldb8,ldb9,ldb10,ldb11,ldb12,ldb13,ldb14,ldb15
  ,ldb16,ldb17,ldb18,ldb19,ldb20,ldb21,ldb22,ldb23
  ,ldb24,ldb25,ldb26,ldb27,ldb28,ldb29,ldb30,ldb31
 );
 LockDosFlagSet=SET OF LockDosFlags;

CONST
(* actually all but entry (which is used for internal locking) *)
 ldAll=LockDosFlagSet{devices,volumes,assigns};

TYPE
 FileLock=RECORD
  link:FileLockPtr;       (* bcpl pointer to next lock *)
  key:LONGINT;            (* disk block number *)
  access:LONGINT;         (* exclusive or shared *)
  task:ProcessId;         (* handler task's port *)
  volume:DeviceListPtr;   (* bptr to DLT_VOLUME DosList entry *) 
 END;

CONST
(* error report types for ErrorReport() *)
  reportStream = 0;      (* a stream *)
  reportTask   = 1;      (* a process - unused *)
  reportLock   = 2;      (* a lock *)
  reportVolume = 3;      (* a volume node *)
  reportInsert = 4;      (* please insert volume *)

(* Special error codes for ErrorReport() *)
  diskError  = 296;     (* Read/write error *)
  abortBusy  = 288;     (* You MUST replace... *)

(* types for initial packets to shells from run/newcli/execute/system. *)
(* For shell-writers only *)
  runExecute         = -1;
  runSystem          = -2;
  runSystemAsynch    = -3;

(* Types for FileInfoBlock.dirEntryType. NOTE that both USERDIR and ROOT are  *)
(* directories, and that directory/file checks should use <0 and >=0.    *)
(* This is not necessarily exhaustive!  Some handlers may use other      *)
(* values as needed, though <0 and >=0 should remain as supported as     *)
(* possible.                                                             *)
  root       = 1;
  userDir    = 2;
  softLink   = 3;       (* looks like dir, but may point to a file! *)
  linkDir    = 4;       (* hard link to dir *)
  file       = -3;      (* must be negative for FIB! *)
  linkFile   = -4;      (* hard link to file *)


(* hunk types *)
  hunkUnit       = 999;
  hunkName       = 1000;
  hunkCode       = 1001;
  hunkData       = 1002;
  hunkBSS        = 1003;
  hunkReloc32    = 1004;
  hunkAbsReloc32 = hunkReloc32;
  hunkReloc16    = 1005;
  hunkRelReloc16 = hunkReloc16;
  hunkReloc8     = 1006;
  hunkRelReloc8  = hunkReloc8;
  hunkExt        = 1007;
  hunkSymbol     = 1008;
  hunkDebug      = 1009;
  hunkEnd        = 1010;
  hunkHeader     = 1011;

  hunkOverlay    = 1013;
  hunkBreak      = 1014;

  hunkDRel32     = 1015;
  hunkDRel16     = 1016;
  hunkDRel8      = 1017;

  hunkLib        = 1018;
  hunkIndex      = 1019;

(*
 * Note: V37 LoadSeg uses 1015 (HUNK_DREL32) by mistake.  This will continue
 * to be supported in future versions, since HUNK_DREL32 is illegal in load files
 * anyways.  Future versions will support both 1015 and 1020, though anything
 * that should be usable under V37 should use 1015.
 *)
  hunkReloc32Short = 1020;

(* see ext_xxx below.  New for V39 (note that LoadSeg only handles RELRELOC32).*)
  hunkRelReloc32   = 1021;
  hunkAbsReloc16   = 1022;

(*
 * Any hunks that have the HUNKB_ADVISORY bit set will be ignored if they
 * aren't understood.  When ignored, they're treated like HUNK_DEBUG hunks.
 * NOTE: this handling of HUNKB_ADVISORY started as of V39 dos.library!  If
 * lading such executables is attempted under <V39 dos, it will fail with a
 * bad hunk type.
 *)
  hunkBAdvisory    = 29;
  hunkBChip        = 30;
  hunkBFast        = 31;


(* hunk_ext sub-types *)
  extSymb        = 0;       (* symbol table *)
  extDef         = 1;       (* relocatable definition *)
  extAbs         = 2;       (* Absolute definition *)
  extRes         = 3;       (* no longer supported *)
  extRef32       = 129;     (* 32 bit reference to symbol *)
  extAbsRef32    = extRef32;
  extCommon      = 130;     (* 32 bit reference to COMMON block *)
  extAbsCommon   = extCommon;
  extRef16       = 131;     (* 16 bit reference to symbol *)
  extRelRef16    = extRef16;
  extRef8        = 132;     (*  8 bit reference to symbol *)
  extRelRef8     = extRef8;
  extDExt32      = 133;     (* 32 bit data releative reference *)
  extDExt16      = 134;     (* 16 bit data releative reference *)
  extDExt8       = 135;     (*  8 bit data releative reference *)

(* These are to support some of the '020 and up modes that are rarely used *)
  extRelRef32    = 136;     (* 32 bit PC-relative reference to symbol *)
  extRelCommon   = 137;     (* 32 bit PC-relative reference to COMMON block *)

(* for completeness... All 680x0's support this *)
  extAbsRef16    = 138;     (* 16 bit absolute reference to symbol *)

(* this only exists on '020's and above, in the (d8,An,Xn) address mode *)
  extAbsRef8     = 139;     (* 8 bit absolute reference to symbol *)


(*****************************************************************************)
(* definitions for the System() call *)

TYPE

 SysTags=(
  sysDummy:=tagUser+32,
  sysInput,               (* specifies the input filehandle  *)
  sysOutput,              (* specifies the output filehandle *)
  sysASynch,              (* run asynch, close input/output on exit(!) *)
  sysUserShell,           (* send to user shell instead of boot shell *)
  sysCustomShell          (* send to a specific shell (data is name) *)  
 );

(*****************************************************************************)
(* definitions for the CreateNewProc() call *)
(* you MUST specify one of NP_Seglist or NP_Entry.  All else is optional. *)

 NpTags=(
  npDummy:=tagUser+1000,
  npSeglist,              (* seglist of code to run for the process  *)
  npFreeSeglist,          (* free seglist on exit - only valid for   *)    
                          (* for NP_Seglist.  Default is TRUE.       *)
  npEntry,                (* entry point to run - mutually exclusive *)
                          (* with NP_Seglist! *)
  npInput,                (* filehandle - default is Open("NIL:"...) *)
  npOutput,               (* filehandle - default is Open("NIL:"...) *)
  npCloseInput,           (* close input filehandle on exit          *)  
                          (* default TRUE                            *)
  npCloseOutput,          (* close output filehandle on exit         *)    
                          (* default TRUE                            *)
  npError,                (* filehandle - default is Open("NIL:"...) *)
  npCloseError,           (* close error filehandle on exit          *)  
                          (* default TRUE                            *)
  npCurrentDir,           (* lock - default is parent's current dir  *)  
  npStackSize,            (* stacksize for process - default 4000    *)  
  npName,                 (* name for process - default "New Process"*)
  npPriority,             (* priority - default same as parent       *)
  npConsoleTask,          (* consoletask - default same as parent    *)    
  npWindowPtr,            (* window ptr - default is same as parent  *)  
  npHomeDir,              (* home directory - default curr home dir  *)
  npCopyVars,             (* boolean to copy local vars-default TRUE *)
  npCli,                  (* create cli structure - default FALSE    *)
  npPath,                 (* path - default is copy of parents path  *)
                          (* only valid if a cli process!    *)
  npCommandName,          (* commandname - valid only for CLI        *)    
  npArguments,            (* cstring of arguments - passed with str  *)  
                          (* in a0, length in d0.  (copied and freed *)
                          (* on exit.  Default is empty string.      *)
                          (* NOTE: not operational until 2.04 - see  *)
                          (* BIX/TechNotes for more info/workarounds *)
                          (* NOTE: in 2.0, it DIDN'T pass "" - the   *)
                          (* registers were random.                  *)       
(* FIX! should this be only for cli's? *)
  npNotifyOnDeath,        (* notify parent on death - default FALSE  *)
                          (* Not functional yet. *)                     
  npSynchronous,          (* don't return until process finishes -   *)
                          (* default FALSE.                          *)
                          (* Not functional yet. *)
  npExitCode,             (* code to be called on process exit       *)
  npExitData              (* optional argument for NP_EndCode rtn -  *)
                          (* default NULL                            *)
 );

(*****************************************************************************)
(* tags for AllocDosObject *)

 AdoTags=(
  adoDummy:=tagUser+2000,
  adoFhMode,                    (* for type DOS_FILEHANDLE only            *)
                                (* sets up FH for mode specified.
                                   This can make a big difference for buffered
                                   files.                                  *)

        (* The following are for DOS_CLI *)
        (* If you do not specify these, dos will use it's preferred values *)
        (* which may change from release to release.  The BPTRs to these   *)
        (* will be set up correctly for you.  Everything will be zero,     *)
        (* except cli_FailLevel (10) and cli_Background (DOSTRUE).         *)
        (* NOTE: you may also use these 4 tags with CreateNewProc.         *)
  adoDirLen,        (* size in bytes for current dir buffer    *)
  adoCommNameLen,   (* size in bytes for command name buffer   *)
  adoCommFileLen,   (* size in bytes for command file buffer   *)
  adoPromptLen      (* size in bytes for the prompt buffer     *)
 );

CONST

(*****************************************************************************)
(* tags for NewLoadSeg *)
(* no tags are defined yet for NewLoadSeg *)

(* NOTE: V37 dos.library, when doing ExAll() emulation, and V37 filesystems  *)
(* will return an error if passed ED_OWNER.  If you get ERROR_BAD_NUMBER,    *)
(* retry with ED_COMMENT to get everything but owner info.  All filesystems  *)
(* supporting ExAll() must support through ED_COMMENT, and must check Type   *)
(* and return ERROR_BAD_NUMBER if they don't support the type.                     *)

(* values that can be passed for what data you want from ExAll() *)
(* each higher value includes those below it (numerically)       *)
(* you MUST chose one of these values *)
  edName        = 1;
  edType        = 2;
  edSize        = 3;
  edProtection  = 4;
  edDate        = 5;
  edComment     = 6;
  edOwner       = 7;

TYPE

(*
 *   Structure in which exall results are returned in.  Note that only the
 *   fields asked for will exist!
 *)

 ExAllData=RECORD
  next:ExAllDataPtr;
  name:StrPtr;
  type:LONGINT;
  size:LONGCARD;
  prot:ProtectionMaskSet;
  date:Date;
  comment:StrPtr; (* strings will be after last used field *)
  ownerUID:CARDINAL; (* new for V39 *)
  ownerGID:CARDINAL;
 END;

(*
 *   Control structure passed to ExAll.  Unused fields MUST be initialized to
 *   0, expecially eac_LastKey.
 *
 *   eac_MatchFunc is a hook (see utility.library documentation for usage)
 *   It should return true if the entry is to returned, false if it is to be
 *   ignored.
 *
 *   This structure MUST be allocated by AllocDosObject()!
 *)

 ExAllControl=RECORD
  entries:LONGCARD;   (* number of entries returned in buffer      *)
  lastKey:LONGCARD;   (* Don't touch inbetween linked ExAll calls! *)
  matchString:StrPtr; (* wildcard string for pattern match or NULL *)
  matchFunc:HookPtr;  (* optional private wildcard function        *)   
 END;

(* The disk "environment" is a longword array that describes the
 * disk geometry.  It is variable sized, with the length at the beginning.
 * Here are the constants for a standard geometry.
 *)

 DosEnvec=RECORD
  tableSize:LONGCARD;           (* size of Environment vector *)
  sizeBlock:LONGCARD;           (* in longwords: standard value is 128 *)
  secOrg:LONGCARD;              (* not used; must be 0 *)
  surfaces:LONGCARD;            (* # of heads (surfaces). drive specific *)
  sectorsPerBlock:LONGCARD;     (* not used; must be 1 *)
  blocksPerTrack:LONGCARD;      (* blocks per track. drive specific *)
  reserved:LONGCARD;            (* DOS reserved blocks at start of partition. *)
  preAlloc:LONGCARD;            (* DOS reserved blocks at end of partition *)
  interleave:LONGCARD;          (* usually 0 *)  
  lowCyl:LONGCARD;              (* starting cylinder. typically 0 *)  
  highCyl:LONGCARD;             (* max cylinder. drive specific *)  
  numBuffers:LONGCARD;          (* Initial # DOS of buffers.  *)  
  bufMemType:LONGCARD;          (* type of mem to allocate for buffers *)  
  maxTransfers:LONGCARD;        (* Max number of bytes to transfer at a time *)    
  mask:LONGSET;                 (* Address Mask to block out certain memory *)  
  bootPri:LONGINT;              (* Boot priority for autoboot *)  
  dosType:LONGCARD;             (* ASCII (HEX) string showing filesystem type;
                                 * 0X444F5300 is old filesystem,
                                 * 0X444F5301 is fast file system *)
  baud:LONGCARD;                (* Baud rate for serial handler *)
  control:LONGCARD;             (* Control word for handler/filesystem *)
  bootBlocks:LONGCARD;          (* Number of blocks containing boot code *)  
 END;

CONST
(* these are the offsets into the array *)
(* DE_TABLESIZE is set to the number of longwords in the table minus 1 *)

  tableSize    = 0;       (* minimum value is 11 (includes NumBuffers) *)
  sizeBlock    = 1;       (* in longwords: standard value is 128 *)
  secOrg       = 2;       (* not used; must be 0 *)
  numHeads     = 3;       (* # of heads (surfaces). drive specific *)
  secsPerBlk   = 4;       (* not used; must be 1 *)
  blksPerTrack = 5;       (* blocks per track. drive specific *)
  reservedBlks = 6;       (* unavailable blocks at start.  usually 2 *)
  preFac       = 7;       (* not used; must be 0 *)
  interLeave   = 8;       (* usually 0 *)
  lowCyl       = 9;       (* starting cylinder. typically 0 *)
  upperCyl     = 10;      (* max cylinder.  drive specific *)
  numBuffers   = 11;      (* starting # of buffers.  typically 5 *)
  memBufType   = 12;      (* type of mem to allocate for buffers. *)
  bufMemType   = 12;      (* same as above, better name
                           * 1 is public, 3 is chip, 5 is fast *)
  maxTransfer  = 13;      (* Max number bytes to transfer at a time *)
  mask         = 14;      (* Address Mask to block out certain memory *)
  bootPri      = 15;      (* Boot priority for autoboot *)
  dosType      = 16;      (* ASCII (HEX) string showing filesystem type;
                           * 0X444F5300 is old filesystem,
                           * 0X444F5301 is fast file system *)
  baud         = 17;      (* Baud rate for serial handler *)
  control      = 18;      (* Control word for handler/filesystem *)
  bootBlocks   = 19;      (* Number of blocks containing boot code *)

TYPE
(* The file system startup message is linked into a device node's startup
** field.  It contains a pointer to the above environment, plus the
** information needed to do an exec OpenDevice().
*)

 FileSysStartupMsg=RECORD
  unit:LONGCARD;          (* exec unit number for this device *)
  device:BSTR;            (* null terminated bstring to the device name *)
  environ:DosEnvecPtr;    (* ptr to environment table (see above) *)
  flags:LONGSET;          (* flags for OpenDevice() *)                     
 END;

CONST
(* use of Class and code is discouraged for the time being - we might want to
   change things *)
(* --- NotifyMessage Class ------------------------------------------------ *)
  notifyClass = 40000000H;

(* --- NotifyMessage Codes ------------------------------------------------ *)
  notifyCode = 1234H;

TYPE
(* Sent to the application if SEND_MESSAGE is specified.                    *)

 NotifyMessage=RECORD
  execMessage:Message;
  class:LONGCARD;
  code:CARDINAL;
  nReq:NotifyRequestPtr;  (* don't modify the request! *)
  doNotTouch:LONGCARD;    (* like it says!  For use by handlers *)
  doNotTouch2:LONGCARD;   (* dito *)                               
 END;

NotifyFlags=(
  sendMessage,
  sendSignal,
  nf2,
  waitReply,
  notifyInitial,
  nf5,nf6,nf7,nf8,nf9,nf10,nf11,nf12,nf13,nf14,nf15,nf16,nf17,nf18,
  nf19,nf20,nf21,nf22,nf23,nf24,nf25,nf26,nf27,nf28,nf29,nf30,
(* do NOT set or remove NRF_MAGIC!  Only for use by handlers! *)
  magic
 );
 NotifyFlagSet=SET OF NotifyFlags;

 CONST
(* Flags reserved for private use by the handler: *)
  handlerFlags = LONGSET{16..31};

TYPE
(* Do not modify or reuse the notifyrequest while active.                   *)
(* note: the first LONG of nr_Data has the length transfered                *)

 NotifyRequest=RECORD
  name:StrPtr;
  fullName:StrPtr;    (* set by dos - don't touch *)
  userData:ADDRESS;   (* for applications use *)    
  flags:NotifyFlagSet;
  CASE :INTEGER OF
  | 0:
   port:MsgPortPtr;           (* for SEND_MESSAGE *)
  | 1:
   task:TaskPtr;              (* for SEND_SIGNAL *)
   signalNum:SHORTCARD;       (* for SEND_SIGNAL *)
   pad1,pad2,pad3:SHORTCARD; 
  END;
  reserved:ARRAY[1..4] OF LONGCARD; (* leave 0 for now *)
    (* internal use by handlers *)
  msgCount:LONGCARD;    (* # of outstanding msgs *)
  handler:MsgPortPtr;   (* handler sent to (for EndNotify) *)
 END;
 
(**********************************************************************
 *
 * The CSource data structure defines the input source for "ReadItem()"
 * as well as the ReadArgs call.  It is a publicly defined structure
 * which may be used by applications which use code that follows the
 * conventions defined for access.
 *
 * When passed to the dos.library functions, the value passed as
 * struct *CSource is defined as follows:
 *      if ( CSource == 0)      Use buffered IO "ReadChar()" as data source
 *      else                    Use CSource for input character stream
 *
 * The following two pseudo-code routines define how the CSource structure
 * is used:
 *
 * long CS_ReadChar( struct CSource *CSource )
 * {
 *      if ( CSource == 0 )     return ReadChar();
 *      if ( CSource->CurChr >= CSource->Length )       return ENDSTREAMCHAR;
 *      return CSource->Buffer[ CSource->CurChr++ ];
 * }
 *
 * BOOL CS_UnReadChar( struct CSource *CSource )
 * {
 *      if ( CSource == 0 )     return UnReadChar();
 *      if ( CSource->CurChr <= 0 )     return FALSE;
 *      CSource->CurChr--;
 *      return TRUE;
 * }
 *
 * To initialize a struct CSource, you set CSource->CS_Buffer to
 * a string which is used as the data source, and set CS_Length to
 * the number of characters in the string.  Normally CS_CurChr should
 * be initialized to ZERO, or left as it was from prior use as
 * a CSource.
 *
 **********************************************************************)

 CSource=RECORD
  buffer:StrPtr;
  length:LONGINT;
  curChr:LONGINT;
 END;

(**********************************************************************
 *
 * The RDArgs data structure is the input parameter passed to the DOS
 * ReadArgs() function call.
 *
 * The RDA_Source structure is a CSource as defined above;
 * if RDA_Source.CS_Buffer is non-null, RDA_Source is used as the input
 * character stream to parse, else the input comes from the buffered STDIN
 * calls ReadChar/UnReadChar.
 *
 * RDA_DAList is a private address which is used internally to track
 * allocations which are freed by FreeArgs().  This MUST be initialized
 * to NULL prior to the first call to ReadArgs().
 *
 * The RDA_Buffer and RDA_BufSiz fields allow the application to supply
 * a fixed-size buffer in which to store the parsed data.  This allows
 * the application to pre-allocate a buffer rather than requiring buffer
 * space to be allocated.  If either RDA_Buffer or RDA_BufSiz is NULL,
 * the application has not supplied a buffer.
 *
 * RDA_ExtHelp is a text string which will be displayed instead of the
 * template string, if the user is prompted for input.
 *
 * RDA_Flags bits control how ReadArgs() works.  The flag bits are
 * defined below.  Defaults are initialized to ZERO.
 *
 **********************************************************************)

 RDAFlags=(
  stdIn,      (* Use "STDIN" rather than "COMMAND LINE" *)
  noAlloc,    (* If set, do not allocate extra string space.*)
  noPrompt,   (* Disable reprompting for string input. *)      
  rdaf3,rdaf4,rdaf5,rdaf6,rdaf7,rdaf8,rdaf9,rdaf10,
  rdaf11,rdaf12,rdaf13,rdaf14,rdaf15,rdaf16
 );
 RDAFlagSet=SET OF RDAFlags;

 RDArgs=RECORD
  source:CSource;   (* Select input source *)
  daList:LONGINT;   (* PRIVATE. *)
  buffer:ADDRESS;   (* Optional string parsing space. *)
  bufSiz:LONGINT;   (* Size of RDA_Buffer (0..n) *)
  extHelp:StrPtr;   (* Optional extended help *)
  flags:RDAFlagSet; (* Flags for any required control *)
 END;

CONST
(**********************************************************************
 * Maximum number of template keywords which can be in a template passed
 * to ReadArgs(). IMPLEMENTOR NOTE - must be a multiple of 4.
 **********************************************************************)
  maxTemplateItems = 100;

(**********************************************************************
 * Maximum number of MULTIARG items returned by ReadArgs(), before
 * an ERROR_LINE_TOO_LONG.  These two limitations are due to stack
 * usage.  Applications should allow "a lot" of stack to use ReadArgs().
 **********************************************************************)
  maxMultiArgs = 128;

(* Modes for LockRecord/LockRecords() *)
  recExclusive       = 0;
  recExclusiveImmed  = 1;
  recShared          = 2;
  recSharedImmed     = 3;

TYPE
(* struct to be passed to LockRecords()/UnLockRecords() *)

 RecordLock=RECORD
  fh:FileHandlePtr; (* filehandle *)
  offset:LONGCARD;  (* offset in file *)
  length:LONGCARD;  (* length of file to be locked *)
  mode:LONGCARD;    (* Type of lock *)
 END;

CONST
(* types for SetVBuf *)
  bufLine = 0; (* flush on \n, etc *)
  bufFull = 1; (* never flush except when needed *)
  bufNone = 2; (* no buffering *)

(* EOF return value *)
 endStreamCh = -1;

(* the structure in the pr_LocalVars list *)
(* Do NOT allocate yourself, use SetVar()!!! This structure may grow in *)
(* future releases!  The list should be left in alphabetical order, and *)
(* may have multiple entries with the same name but different types.    *)

TYPE
 VarFlags=(
  var,          (* an variable *)
  alias,        (* an alias    *)
  vf1,vf2,vf3,vf4,vf5,vf6,
  ignore,       (* ignore this entry on GetVar, etc *)

(* definitions of flags passed to GetVar()/SetVar()/DeleteVar() *)
(* bit defs to be OR'ed with the type: *)
(* item will be treated as a single line of text unless BINARY_VAR is used *)

  globalOnly,   
  localOnly,    
  binaryVar,    (* treat variable as binary *)
  dontNullTerm, (* only with GVF_BINARY_VAR *)

(* this is only supported in >= V39 dos.  V37 dos ignores this. *)
(* this causes SetVar to affect ENVARC: as well as ENV:.      *)
  saveVar,      (* only with GVF_GLOBAL_VAR *)    
  vf13,vf14,vf15,vf16
 );
 VarFlagSet=SET OF VarFlags;

 LocalVar=RECORD
  node:Node;
  flags:VarFlagSet;
  value:StrPtr;
  len:LONGCARD;
 END;


END DosD.
