#ifndef LIBRARIES_ARPBASE_H #define LIBRARIES_ARPBASE_H /********************************************************************** * * AmigaDOS Replacement Project (ARP) -- Library Include File 'C' * ********************************************************************** * * History: * * Version: arpbase.h,v 34.00 02/27/88 * * Created by: SDB * Revised: SDB -- Just bag earlier versions, since didn't have * time to maintain C header during 'the last days'. * Created this file mainly from arpbase.i. * * Revised: SDB -- Added stuff for version 32, ASyncRun() * returns and data structures. * SDB -- Added ERROR_NO_CLI * SDB -- Added final resident data structures, * final ASyncRun() data structures, and * date. Final edits for V33.4 release. ********************************************************************** * * * Copyright (c) 1987, by Scott Ballantyne * * The arp.library, and related code and files may be freely used * by supporters of ARP. Modules in the arp.library may not be * extracted for us in independent code, but you are welcome to provide * the arp.library with your work and call on it freely. * * You are equally welcome to contribute new functions, improve the * ones within, or suggest additions. * * BCPL programs are not welcome to call on the arp.library. * The welcome mat is out to all others. * *********************************************************************/ #ifndef EXEC_TYPES_H #include #endif !EXEC_TYPES_H #ifndef EXEC_LIBRARIES_H #include #endif !EXEC_LIBRARIES_H #ifndef EXEC_LISTS_H #include #endif !EXEC_LISTS_H #ifndef EXEC_SEMAPHORES_H #include #endif !EXEC_SEMAPHORES_H #ifndef LIBRARIES_DOS_H #include #endif !LIBRARIES_DOS_H /* arp.library's node structure, not too hefty even now. */ struct ArpBase { struct Library LibNode; /* Standard library node */ BPTR SegList; /* Pointer to loaded libcode */ UBYTE Flags; /* Not used, yet! */ UBYTE ESCChar; /* Character used for escaping */ LONG ArpReserved1; /* ArpLib's use only! */ struct Library *EnvBase; /* Dummy library for MANX compatibility */ struct Library *DosBase; /* Dos library pointer */ struct Library *GfxBase; /* Graphics lib pointer */ struct Library *IntuiBase; /* Intuition lib pointer */ struct MinList ResLists; /* Resource trackers */ struct ResidentPrgNode *ResidentPrgList; /* Installed programs */ struct SignalSemaphore ResPrgProtection; /* Protection for above */ }; /* Following is here *only* for information and for compatibility * with MANX, don't use in new code! */ struct EnvBase { struct Library LibNode; /* Standard library node for linkage */ BYTE *EnvSpace; /* Access only when Forbidden! */ ULONG EnvSize; /* Total allocated mem for EnvSpace */ struct ArpBase *ArpBase; /* Added in V32 for Resource Tracking */ }; /* These are used in release 33.4, but not by the library code. Instead, * individual programs check for these flags. Not ideal, but such is life. * */ #define ARPB_WILD_WORLD 0L ; Mixed BCPL/Normal wildcards. #define ARPB_WILD_BCPL 1L ; Pure BCPL wildcards. #define ARPF_WILD_WORLD (1L << 0) #define ARPF_WILD_BCPL (1L << 1) /*************** C SPECIFIC STUFF *************************************/ /* There are a few things in arp.library that are only directly acessable * from assembler. The glue routines provided by us for all 'C' compilers * use the following conventions to make these available to C programs. * The glue for other language's should use as similar a mechanism as * possible, so that no matter what language or compiler we speak, when * talk about arp, we will know what the other guy is saying. * * Here are the cases: * Atol() - if a bad digit is encountered, will store a ERRBADINT in * Errno, the return from Atol() will be the bad character * encountered. Note: Atol() will not clear Errno if return * is successful. * Trackers: All tracking calls return the Tracker pointer in A1 as a * secondary result, you can obtain this from the global * variable LastTracker immediately after the call. * Finally, GetTracker() syntax is differnt for C and assembler, for 'C' * the Syntax is GetTraker( ID ), the binding routine will store the ID * into the tracker on return. * * In cases where you have allocated a tracker before you have obtained a * resource (usually the most efficient method), and the resource has not * been obtained, you will need to clear the tracker id. The macro CLEAR_ID() * has been provided for that purpose. It expects a pointer to a DefaultTracker * sort of struct. * */ extern LONG Errno; /* Error returns not reportable by functions */ extern struct DefaultTracker *LastTracker; /* Look here after a tracking call */ #define ERRBADINT 1L /* Atol() could not convert string to number */ #define CLEAR_ID( t ) ((SHORT *) t)[-1] = NULL /* * Non controversial, normal library style stuff */ #define ArpName "arp.library" /* Name to use when opening */ #define ArpVersion 34L /* Current version of arplib */ /* * The alert object is what you use if you really must return an * alert to the user. You would normally OR this with another alert number * from the alerts.h file, generally, these should be NON deadend alerts. * * For example, if you can't open ArpLibrary: * Alert( (AG_OpenLib|AO_ArpLib), 0L); * */ #define AO_ArpLib 0x00008036L /* Alert object */ /* * Alerts that arp.library can return. */ #define AN_ArpLib 0x03600000L /* Alert number */ #define AN_ArpNoMem 0x03610000L /* No more memory */ #define AN_ArpInputMem 0x03610002L /* No memory for input buffer */ #define AN_ArpNoMakeEnv 0x83610003L /* No memory to make EnvLib */ #define AN_ArpNoDOS 0x83630001L /* Can't open DOS */ #define AN_ArpNoGfx 0x83630002L /* Can't open graphics.library */ #define AN_ArpNoIntuit 0x83630003L /* Can't open intuition */ #define AN_BadPackBlues 0x83640000L /* Bad packet returned to SendPacket() */ #define AN_Zombie 0x83600003L /* Zombie roaming around system */ #define AN_ArpScattered 0x83600002L /* Scatter loading not allowed for arp */ /* Return codes you can get from calling arp.library's Assign() function */ #define ASSIGN_OK 0L /* Everything is cool and groovey */ #define ASSIGN_NODEV 1L /* "Physical" is not valid for assignment */ #define ASSIGN_FATAL 2L /* Something really icky happened */ #define ASSIGN_CANCEL 3L /* Tried to cancel something but it won't cancel */ /* Size of buffer you need if you are going to call ReadLine() */ #define MaxInputBuf 256L /************************** File Requester ****************************/ /***************** Submit the following to FileRequest() **************/ /**********************************************************************/ struct FileRequester { BYTE *fr_Hail; /* Hailing text */ BYTE *fr_File; /* Filename array (FCHARS * N) */ BYTE *fr_Dir; /* Directory array (DSIZE + 1) */ struct Window *fr_Window; /* Window requesting files or NULL*/ UBYTE fr_FuncFlags; /* Set bitdef's below */ UBYTE fr_reserved1; /* Set to NULL */ VOID (*fr_Function)(); /* Your function, see bitdef's */ LONG fr_reserved2; /* RESERVED */ }; /* The following are the defines for fr_FuncFlags. These bits tell * FileRequest() what your fr_UserFunc is expecting, and what FileRequest() * should call it for. * * You are called like so: * fr_Function(Mask, Object) * ULONG Mask; * CPTR *Object; * * The Mask is a copy of the flag value that caused FileRequest() to call * your function. You can use this to determine what action you need to * perform, and exactly what Object is, so you know what to do and * what to return. */ #define FRB_DoWildFunc 7L /* Call me with a FIB and a name, ZERO return accepts. */ #define FRB_DoMsgFunc 6L /* You get all IDCMP messages not for FileRequest() */ #define FRB_DoColor 5L /* Set this bit for that new and different look */ #define FRB_NewIDCMP 4L /* Force a new IDCMP (only if fr_Window != NULL) */ #define FRB_NewWindFunc 3L /* You get to modify the newwindow structure. */ #define FRB_AddGadFunc 2L /* You get to add gadgets. */ #define FRB_GEventFunc 1L /* Function to call if one of your gadgets is selected. */ #define FRB_ListFunc 0L /* Not implemented yet. */ #define FRF_DoWildFunc (1L << 7) #define FRF_DoMsgFunc (1L << 6) #define FRF_DoColor (1L << 5) #define FRF_NewIDCMP (1L << 4) #define FRF_NewWindFunc (1L << 3) #define FRF_AddGadFunc (1L << 2) #define FRF_GEventFunc (1L << 1) #define FRF_ListFunc (1L << 0) #define FCHARS 32L /* Filename size */ #define DSIZE 33L /* Directory name size */ #define FR_FIRST_GADGET 0x7680L /* User gadgetID's must be less than this value */ /*************************************************************************/ /********************** PATTERN MATCHING *********************************/ /*************************************************************************/ /* Structure expected by FindFirst(), FindNext() */ /* * You need to 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 FindFirst() and then afterwards, FindNext() with this structure. * You should check the return value each time (see below) and take the * appropriate action, ultimately calling FreeAnchorChain() 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. * * You will also have to check the DirEntryType variable in the ap_Info * structure to determine what exactly you have received. */ struct AnchorPath { struct Anchor *ap_Base; /* Pointer to first anchor */ struct Anchor *ap_Last; /* Pointer to last anchor */ LONG ap_BreakBits; /* Bits to break on */ LONG ap_FoundBreak; /* Bits we broke on. Also returns ERROR_BREAK */ ULONG ap_Length; /* Actual size of ap_Buf, set to 0 if no ap_Buf */ struct FileInfoBlock ap_Info; BYTE ap_Buf[1]; /* Allocate a buffer here, if desired */ }; /* * structure used by the pattern matching functions, no need to obtain, diddle * or allocate this yourself. */ struct Anchor { struct Anchor *an_Next; struct Anchor *an_Pred; struct FileLock *an_Lock; struct FileInfoBlock *an_Info; LONG an_Status; /* Type of this anchor node */ union { WORD an_Text; /* Actual instance of a BSTRing */ BYTE an_Actual[2]; /* more memory allocated as required */ } an_BSTR; }; /* This structure takes a pointer, and returns FALSE if wildcard was not * found by FindFirst() */ #define IsWild( ptr ) ( *((LONG *)(ptr)) ) /* 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, FindFirst() FindNext() * handle all these for you. */ #define P_ANY 0x80L /* Token for '*' or '#?' */ #define P_SINGLE 0x81L /* Token for '?' */ #define P_ORSTART 0x82L /* Token for '(' */ #define P_ORNEXT 0x83L /* Token for '|' */ #define P_OREND 0x84L /* Token for ')' */ #define P_TAG 0x85L /* Token for '{' */ #define P_TAGEND 0x86L /* Token for '}' */ #define P_NOTCLASS 0x87L /* Token for '^' */ #define P_CLASS 0x88L /* Token for '[]' */ #define P_REPBEG 0x89L /* Token for '[' */ #define P_REPEND 0x8AL /* Token for ']' */ /* Values for an_Status, NOTE: these are the actual bit numbers. */ #define COMPLEX_BIT 1L /* Parsing complex pattern */ #define EXAMINE_BIT 2L /* Searching directory */ /* Returns from FindFirst() FindNext() */ /* Note that you can also get return codes as defined in dos.h, * particularly you can get ERROR_NO_MORE_ENTRIES. */ #define ERROR_BUFFER_OVERFLOW 303L /* User or internal buffer overflow */ #define ERROR_BREAK 304L /* A break character was received */ /* Structure used by AddDANode(), AddDADevs(), FreeDAList(). * * This structure is used to create lists of names, which normally * are devices, assigns, volumes, files, or directories. */ struct DirectoryEntry { struct DirectoryEntry *de_Next; /* Next in list */ BYTE de_Type; /* DLX_mumble */ BYTE de_Flags; /* For future expansion, DO NOT USE! */ BYTE de_Name[1]; /* The name of the thing found */ }; /* Defines you use to get a list of the devices you want to look at. * For example, to get a list of all directories and volumes, do: * * AddDADevs( mydalist, (DLF_DIRS | DLF_VOLUMES) ) * * After this, you can examine the de_type field of the elements added to * your list (if any) to discover specifics about the objects added. * * Note that if you want only devices which are also disks, you must request * (DLF_DEVICES | DLF_DISKONLY). */ #define DLB_DEVICES 0L /* Return devices */ #define DLB_DISKONLY 1L /* Modifier for above: Return disk devices only */ #define DLB_VOLUMES 2L /* Return volumes only */ #define DLB_DIRS 3L /* Return assigned devices only */ #define DLF_DEVICES (1L << 0) #define DLF_DISKONLY (1L << 1) #define DLF_VOLUMES (1L << 2) #define DLF_DIRS (1L << 3) /* Legal de_Type values, check for these after a call to AddDADevs(), or use * on your own as the ID values in AddDANode(). */ #define DLX_FILE 0L /* AddDADevs() can't determine this */ #define DLX_DIR 8L /* AddDADevs() can't determine this */ #define DLX_DEVICE 16L /* It's a resident device */ #define DLX_VOLUME 24L /* Device is a volume */ #define DLX_UNMOUNTED 32L /* Device is not resident */ #define DLX_ASSIGN 40L /* Device is a logical assignment */ /*********************************************************************/ /********************** RESOURCE TRACKING ****************************/ /*********************************************************************/ /* Note: ResList MUST be a DosAllocMem'ed list!, this is done for * you when you call CreateTaskResList(), typically, you won't need * to access/allocate this structure. */ struct ResList { struct MinNode rl_Node; /* Used by arplib to link reslist's */ struct Task *rl_TaskID; /* Owner of this list */ struct MinList rl_FirstItem; /* List of TrackedResource's */ struct ArpResList *rl_Link; /* SyncRun's use - hide list here */ }; /* * The rl_FirstItem list (above) is a list of TrackedResource (below). * It is very important that nothing in this list depend on the task * existing at resource freeing time (i.e., RemTask(0L) type stuff, * DeletePort() and the rest). * * The tracking functions return a struct Tracker *Tracker to you, this * is a pointer to whatever follows the tr_ID variable. * The default case is reflected below, and you get it if you call * GetTracker() ( see DefaultTracker below). * * NOTE: The two user variables mentioned in an earlier version don't * exist, and never did. Sorry about that (SDB). * * However, you can still use ArpAlloc() to allocate your own tracking nodes * and they can be any size or shape you like, as long as the base structure * is preserved. They will be freed automagically just like the default trackers. */ struct TrackedResource { struct MinNode tr_Node; /* Double linked pointer */ BYTE tr_Flags; /* Don't touch */ BYTE tr_Lock; /* Don't touch, for Get/FreeAccess() */ SHORT tr_ID; /* Item's ID */ /* * The struct DefaultTracker *Tracker portion of the structure. * The stuff below this point can conceivably vary, depending * on user needs, etc. This reflects the default. */ union { CPTR tr_Resource; /* Whatever */ LONG tg_Verify; /* For use during TRAK_GENERIC */ } tr_Object; /* The thing being tracked */ union { VOID (*tg_Function)(); /* Function to call for TRAK_GENERIC */ struct Window *tr_Window2; /* For TRAK_WINDOW */ } tr_Extra; /* Only needed sometimes */ }; #define tg_Value tg_Verify /* Ancient compatibility */ /* You get a pointer to a struct of the following type when you call * GetTracker(). You can change this, and use ArpAlloc() instead of * GetTracker() to do tracking. Of course, you have to take a wee bit * more responsibility if you do, as well as if you use TRAK_GENERIC * stuff. * * TRAK_GENERIC folks need to set up a task function to be called when an * item is freed. Some care is required to set this up properly. * * Some special cases are indicated by the unions below, for TRAK_WINDOW, * if you have more than one window opened, and don't want the IDCMP closed * particularly, you need to set a ptr to the other window in dt_Window2. * See CloseWindowSafely() for more info. If only one window, set this to NULL. * */ struct DefaultTracker { union { CPTR dt_Resource; /* Whatever */ LONG tg_Verify; /* For use during TRAK_GENERIC */ } dt_Object; /* The object being tracked */ union { VOID (*tg_Function)(); /* Function to call for TRAK_GENERIC */ struct Window *dt_Window2; /* For TRAK_WINDOW */ } dt_Extra; }; /* Items the tracker knows what to do about */ #define TRAK_AAMEM 0L /* Default (ArpAlloc) element */ #define TRAK_LOCK 1L /* File lock */ #define TRAK_FILE 2L /* Opened file */ #define TRAK_WINDOW 3L /* Window -- see docs */ #define TRAK_SCREEN 4L /* Screen */ #define TRAK_LIBRARY 5L /* Opened library */ #define TRAK_DAMEM 6L /* Pointer to DosAllocMem block */ #define TRAK_MEMNODE 7L /* AllocEntry() node */ #define TRAK_SEGLIST 8L /* Program segment */ #define TRAK_RESLIST 9L /* ARP (nested) ResList */ #define TRAK_MEM 10L /* Memory ptr/length */ #define TRAK_GENERIC 11L /* Generic Element, your choice */ #define TRAK_DALIST 12L /* DAlist ( aka file request ) */ #define TRAK_ANCHOR 13L /* Anchor chain (pattern matching) */ #define TRAK_MAX 13L /* Poof, anything higher is tossed */ #define TRB_UNLINK 7L /* Free node bit */ #define TRB_RELOC 6L /* This may be relocated (not used yet) */ #define TRB_MOVED 5L /* Item moved */ #define TRF_UNLINK (1L << 7) #define TRF_RELOC (1L << 6) #define TRF_MOVED (1L << 5) /* Returns from CompareLock() */ #define LCK_EQUAL 0L /* The two locks refer to the same object */ #define LCK_VOLUME 1L /* Locks are on the same volume */ #define LCK_DIFVOL1 2L /* Locks are on different volumes */ #define LCK_DIFVOL2 3L /* Locks are on different volumes */ /****************************** ASyncRun() ***************************/ /* * Message sent back on your request by an exiting process. * You request this by putting the address of your message in pcb_LastGasp, * and initializing the ReplyPort variable of your ZombieMsg to the * port you wish the message posted to. */ struct ZombieMsg { struct Message zm_ExecMessage; ULONG zm_TaskNum; /* Task ID */ ULONG zm_ReturnCode; /* Process's return code */ ULONG zm_Result2; /* System return code */ struct DateStamp zm_ExitTime; /* Date stamp at time of exit */ ULONG zm_UserInfo; /* For whatever you wish. */ }; /* Structure required by ASyncRun() -- see docs for more info. */ struct ProcessControlBlock { ULONG pcb_StackSize; /* Stacksize for new process */ BYTE pcb_Pri; /* Priority of new task */ BYTE pcb_Control; /* Control bits, see defines below */ APTR pcb_TrapCode; /* Optional Trap Code */ ULONG pcb_Input,p_Output; /* Optional stdin, stdout */ union { ULONG pcb_SplatFile; /* File to use for Open("*") */ BYTE *pcb_ConName; /* CON: filename */ } pcb_Console; ULONG pcb_SplatFile; /* File to use for Open("*") */ CPTR pcb_LoadedCode; /* If not null, will not load/unload code */ struct ZombieMsg *pcb_LastGasp; /* ReplyMsg() to be filled in by exit */ struct MsgPort *pcb_WBProcess; /* Valid only when PRB_NOCLI */ }; /* Some programs appear to have bugs in the startup code that does not handle * well a zero length command line (lattice startup has this, but is probably * not unique). Use this macro to pass a null cmd line to a process using * either ASyncRun() or SyncRun() */ #define NOCMD "\n" /* The following control bits determine what ASyncRun() does on Abnormal Exits * and on background process termination. */ #define PRB_SAVEIO 0L /* Don't free/check file handles on exit */ #define PRB_CLOSESPLAT 1L /* Close Splat file, must request explicitly */ #define PRB_NOCLI 2L /* Don't create a CLI process */ #define PRB_INTERACTIVE 3L /* This should be interactive */ #define PRB_CODE 4L /* Dangerous yet enticing */ #define PRB_STDIO 5L /* Do the stdio thing, splat = CON:Filename */ #define PRF_SAVEIO (1L << 0) #define PRF_CLOSESPLAT (1L << 1) #define PRF_NOCLI (1L << 2) #define PRF_INTERACTIVE (1L << 3) #define PRF_CODE (1L << 4) #define PRF_STDIO (1L << 5) /* Error returns from SyncRun() and ASyncRun() */ #define PR_NOFILE -1L /* Could not LoadSeg() the file */ #define PR_NOMEM -2L /* No memory for something */ #define PR_NOCLI -3L /* Only SyncRun() will fail if call not cli */ #define PR_NOSLOT -4L /* No room in TaskArray */ #define PR_NOINPUT -5L /* Could not open input file */ #define PR_NOOUTPUT -6L /* Could not get output file */ #define PR_NOLOCK -7L /* Could not get a lock */ #define PR_ARGERR -8L /* Bad argument to ASyncRun() */ #define PR_NOBCPL -9L /* Bad program passed to ASyncRun() */ #define PR_BADLIB -10 /* Bad library version */ #define PR_NOSTDIO -11 /* Couldn't get stdio handles */ /* Programs should return this as result2 if need a cli and don't have one. */ #define ERROR_NOT_CLI 400L /* Program/function neeeds to be cli */ /******************** Resident Program Support *****************************/ /* * This is the kind of node allocated for you when yhou AddResidentPrg() a code * segment. They are stored as a single linked list with the root in * ArpBase. If you absolutely *must* wander through this list instead of * using the supplied functions, then you must first obtain the semaphore * which protects this list, and then release it afterwards. * Do not use Forbid() and Permit() to gain exclusive access! * Note that the supplied functions handle this locking protocol for you. */ struct ResidentPrgNode { struct ResidentPrgNode *rpn_Next; /* next or NULL */ LONG rpn_Usage; /* Number of current users */ ULONG rpn_CheckSum; /* Checksum of code */ BPTR rpn_Segment; /* Actual segment */ BYTE rpn_Name[1]; /* Allocated as needed */ }; /* If your program starts with this structure, ASyncRun() and SyncRun() will * override a users stack request with the value in rpt_StackSize. * Furthermore, if you are actually attached to the resident list, a memory * block of size rpt_DataSize will be allocated for you, and * a pointer to this data passed to you in register A4. You may use this * block to clone the data segment of programs, thus resulting in one * copy of text, but multiple copies of data/bss for each process * invocation. If you are resident, your program will start at * rpt_Instruction, otherwise, it will be launched from the initial branch. */ struct ResidentProgramTag { BPTR rpt_NextSeg; /* Provided by DOS at LoadSeg time. */ UWORD rpt_BRA; /* Short branch to executable */ UWORD rpt_Magic; /* Resident majik value */ ULONG rpt_StackSize; /* min stack for this process */ ULONG rpt_DataSize; /* Data size to allocate if resident */ /* rpt_Instruction; /* Start here if resident */ }; /* * The form of the ARP allocated node in your tasks memlist when launched * as a resident program. Note that the data portion of the node will only * exist if you have specified a nonzero value for rpt_DataSize. Note also * that this structure is READ ONLY, modify values in this at your own * risk. The stack stuff is for tracking, if you need actual addresses * or stack size, check the normal places for it in your process/task struct. */ struct ProcessMemory { struct Node pm_Node; UWORD pm_Num; /* This is 1 if no data, two if data */ CPTR pm_Stack; ULONG pm_StackSize; CPTR pm_Data; /* Only here if pm_Num == 2 */ ULONG pm_DataSize; }; /* To find the above on your memlist, search for the following name. * We guarantee this will be the only arp.library allocated node on * your memlist with this name, i.e. FindName(task->tcb_MemEntry, PMEM_NAME); */ #define PMEM_NAME "ARP_MEM" #define RESIDENT_MAGIC 0x4AFC /* same as RTC_MATCHWORD (trapf) */ /* The initial branch destination and rpt_Instruction do not have to be the same. * This allows different actions to be taken if you are diskloaded or * resident. DataSize memory will be allocated only if you are resident, * but StackSize will override all user stack requests. */ /*********************** String/Data structures *************************/ struct DateTime { struct DateStamp dat_Stamp; /* DOS Datestamp */ UBYTE dat_Format; /* controls appearance ot dat_StrDate */ UBYTE dat_Flags; /* See BITDEF's below */ BYTE *dat_StrDay; /* day of the week string */ BYTE *dat_StrDate; /* date string */ BYTE *dat_StrTime; /* time string */ }; /* Size of buffer you need for each DateTime strings: */ #define LEN_DATSTRING 10L /* For dat_Flags */ #define DTB_SUBST 0L /* Substitute "Today" "Tomorrow" where appropriate */ #define DTB_FUTURE 1L /* Day of the week is in future */ #define DTF_SUBST (1L << 0) #define DTF_FUTURE (1L << 1) /* For dat_Format */ #define FORMAT_DOS 0L /* dd-mmm-yy AmigaDOS's own, unique style */ #define FORMAT_INT 1L /* yy-mm-dd International format */ #define FORMAT_USA 2L /* mm-dd-yy The good'ol'USA. */ #define FORMAT_CDN 3L /* dd-mm-yy Our brothers and sisters to the north */ #define FORMAT_MAX FORMAT_CDN /* Larger than this? Defaults to AmigaDOS */ #endif !LIBRARIES_ARPBASE_H