Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / workbench / c / AddDatatypes.c
blobea4f5516096b1747127d671407bf0e20a1075a4e
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
10 /******************************************************************************
12 NAME
14 AddDatatypes (files) [QUIET] [REFRESH] [LIST]
16 SYNOPSIS
18 FILES/M, QUIET/S, REFRESH/S, LIST/S
20 LOCATION
24 FUNCTION
26 AddDatatypes allows you to activate a set of specific datatypes.
27 This might be necessary if new datatypes were installed on your
28 system or were not activated on startup.
30 INPUTS
32 FILES -- The name of the file(s) of the corresponding datatype.
33 QUIET -- Won't output any messages
34 REFRESH -- Refreshes the Datatype list?
35 LIST -- This will display a list of current datatypes loaded in
36 memory
38 RESULT
40 Standard DOS error codes.
42 NOTES
44 EXAMPLE
46 AddDataTypes gif.datatype REFRESH
48 BUGS
50 SEE ALSO
52 INTERNALS
54 HISTORY
56 ******************************************************************************/
58 #include <aros/macros.h>
59 #include <aros/bigendianio.h>
60 #include <exec/types.h>
61 #include <exec/memory.h>
62 #include <exec/execbase.h>
63 #include <dos/dos.h>
64 #include <dos/dosasl.h>
65 #include <dos/dosextens.h>
66 #include <libraries/iffparse.h>
67 #include <utility/name.h>
68 #include <utility/hooks.h>
69 #include <workbench/startup.h>
71 #include <proto/exec.h>
72 #include <proto/dos.h>
73 #include <proto/utility.h>
74 #include <proto/iffparse.h>
75 #include <proto/alib.h>
76 #include <proto/arossupport.h>
78 #include <string.h>
80 #include "../libs/datatypes/datatypes_intern.h"
81 #undef DOSBase
82 #undef UtilityBase
83 #undef IFFParseBase
84 #undef LocaleBase
85 #undef DTList
87 /******************************** STRUCTURES *********************************/
89 /* same as datatypes/datatypes.h/struct DataTypeHeader, but always big endian
90 and 32 bit pointers (which in the file are actually offsets) */
92 struct FileDataTypeHeader
94 ULONG fdth_NameOffset; /* Name of the data type */
95 ULONG fdth_BaseNameOffset; /* Base name of the data type */
96 ULONG fdth_PatternOffset; /* File name match pattern */
97 ULONG fdth_MaskOffset; /* Comparision mask (binary) */
98 ULONG fdth_GroupID; /* DataType Group */
99 ULONG fdth_ID; /* DataType ID (same as IFF FORM type) */
100 WORD fdth_MaskLen; /* Length of the comparision mask */
101 WORD fdth_Pad; /* Unused at present (must be 0) */
102 UWORD fdth_Flags; /* Flags -- see below */
103 UWORD fdth_Priority;
106 #define O(x) offsetof(struct FileDataTypeHeader,x)
108 static const IPTR FileDataTypeHeaderDesc[] =
110 sizeof(struct FileDataTypeHeader),
111 SDM_ULONG(O(fdth_NameOffset)),
112 SDM_ULONG(O(fdth_BaseNameOffset)),
113 SDM_ULONG(O(fdth_PatternOffset)),
114 SDM_ULONG(O(fdth_MaskOffset)),
115 SDM_ULONG(O(fdth_GroupID)),
116 SDM_ULONG(O(fdth_ID)),
117 SDM_WORD(O(fdth_MaskLen)),
118 SDM_WORD(O(fdth_Pad)),
119 SDM_UWORD(O(fdth_Flags)),
120 SDM_UWORD(O(fdth_Priority)),
121 SDM_END
124 /******************************** PROTOTYPES *********************************/
126 struct StackVars; /* forward declaration */
128 BOOL DateScan(struct StackVars *sv);
129 void ScanDirectory(struct StackVars *sv, STRPTR pattern);
130 struct DataTypesList *CreateDTList(struct StackVars *sv);
131 struct CompoundDatatype *CreateBasicType(struct StackVars *sv,
132 struct List *list,
133 struct List *globallist, STRPTR name,
134 UWORD Flags, ULONG ID, ULONG GroupID);
135 void LoadDatatype(struct StackVars *sv, STRPTR name);
136 struct CompoundDatatype *CreateDatatype(struct StackVars *sv,
137 struct IFFHandle *iff);
138 struct CompoundDatatype *AddDatatype(struct StackVars *sv,
139 struct CompoundDatatype *cdt);
140 void DeleteDatatype(struct StackVars *sv, struct CompoundDatatype *cdt);
141 void AlphaInsert(struct StackVars *sv, struct List *list, struct Node *node);
142 void PrioInsert(struct StackVars *sv, struct List *list,
143 struct CompoundDatatype *cdt);
144 struct Node *__FindNameNoCase(struct StackVars *sv, struct List *list,
145 STRPTR name);
147 AROS_UFP4(LONG, AROS_SLIB_ENTRY(ReadFunc, AddDatatypes, 0),
148 AROS_UFPA(BPTR , fh , D1),
149 AROS_UFPA(void * , buf , D2),
150 AROS_UFPA(LONG , size , D3),
151 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
152 AROS_UFP4(LONG, AROS_SLIB_ENTRY(SeekFunc, AddDatatypes, 0),
153 AROS_UFPA(BPTR , fh , D1),
154 AROS_UFPA(LONG , pos , D2),
155 AROS_UFPA(LONG , mode , D3),
156 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
157 AROS_UFP3(UBYTE *, AROS_SLIB_ENTRY(AllocFunc, AddDatatypes, 0),
158 AROS_UFPA(ULONG, size, D0),
159 AROS_UFPA(ULONG, req, D1),
160 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
161 AROS_UFP3(void, AROS_SLIB_ENTRY(FreeFunc, AddDatatypes, 0),
162 AROS_UFPA(APTR , memory, A1),
163 AROS_UFPA(ULONG, size , D0),
164 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
166 /********************************* CONSTANTS *********************************/
168 const TEXT Version[] = "$VER: AddDatatypes 42.1 (8.12.2007)\n";
170 #define EXCL_LEN 18
171 UBYTE ExcludePattern[] = "#?.(info|backdrop)";
173 UBYTE Template[] = "FILES/M,QUIET/S,REFRESH/S,LIST/S";
175 struct ArgArray
177 UBYTE **aa_Files;
178 IPTR aa_Quiet;
179 IPTR aa_Refresh;
180 IPTR aa_List;
183 #define ID_DTCD MAKE_ID('D','T','C','D')
184 #define ID_DTTL MAKE_ID('D','T','T','L')
186 #define NUM_PROP 2
188 LONG PropArray[2*NUM_PROP]=
190 ID_DTYP, ID_DTHD,
191 ID_DTYP, ID_DTCD
194 #define NUM_COLL 1
196 const LONG const CollArray[2*NUM_COLL]=
198 ID_DTYP, ID_DTTL
202 const LONG_FUNC const FunctionArray[]=
203 { /* Note! */
204 (LONG_FUNC)AROS_SLIB_ENTRY(ReadFunc, AddDatatypes, 0),
205 (LONG_FUNC)AROS_SLIB_ENTRY(AllocFunc, AddDatatypes, 0),
206 (LONG_FUNC)AROS_SLIB_ENTRY(FreeFunc, AddDatatypes, 0),
207 (LONG_FUNC)AROS_SLIB_ENTRY(SeekFunc, AddDatatypes, 0), /* For ELF */
211 struct StackVars
213 struct DataTypesList *DTList;
214 UBYTE ExclPat[2*EXCL_LEN+2+1];
215 struct ArgArray AA;
216 UBYTE *HookBuffer;
217 ULONG HookBufSize;
218 ULONG HookPosition;
221 #undef SysBase
222 #define DTList sv->DTList
223 #define ExclPat sv->ExclPat
224 #define AA sv->AA
225 #define HookBuffer sv->HookBuffer
226 #define HookBufSize sv->HookBufSize
227 #define HookPosition sv->HookPosition
229 /****** AddDatatypes/main *****************************************************
231 * NAME
232 * main - well... main
234 * SYNOPSIS
236 * FUNCTION
238 * INPUTS
240 * RETURNS
242 * EXAMPLE
244 * SEE ALSO
246 ******************************************************************************
249 int UtilityBase_version = 37;
250 int LocaleBase_version = 37;
251 int IFFParseBase_version = 37;
253 int __nocommandline = 1;
255 int main(void)
257 extern struct WBStartup *WBenchMsg;
258 struct StackVars vars;
259 struct StackVars *sv;
260 int result = RETURN_FAIL;
262 memset(&vars, 0, sizeof(struct StackVars));
263 sv = &vars;
265 if((DTList = CreateDTList(sv)))
267 ParsePatternNoCase(ExcludePattern, ExclPat, sizeof(ExclPat));
269 ObtainSemaphore(&DTList->dtl_Lock);
271 if(WBenchMsg)
273 UWORD num;
274 struct WBArg *wa = &WBenchMsg->sm_ArgList[1];
276 for(num = 1; num<WBenchMsg->sm_NumArgs; wa++)
278 BPTR olddir = CurrentDir(wa->wa_Lock);
279 LoadDatatype(sv, wa->wa_Name);
280 CurrentDir(olddir);
283 result = RETURN_OK;
285 else
287 struct RDArgs *RDArgs;
289 if(!(RDArgs = ReadArgs(Template, (SIPTR*)&AA, NULL)))
291 PrintFault(IoErr(), NULL);
293 else
295 if(AA.aa_Refresh)
297 if(DateScan(sv))
299 ScanDirectory(sv, "DEVS:DataTypes");
302 else
304 UBYTE **files = AA.aa_Files;
306 if(files)
308 while(*files)
310 ScanDirectory(sv, *files);
311 files++;
316 if(AA.aa_List)
318 struct DataTypesList *dtl = NULL;
319 struct NamedObject *no = NULL;
320 if((no = FindNamedObject(NULL, DATATYPESLIST, NULL)))
322 dtl = (struct DataTypesList*)no->no_Object;
323 ReleaseNamedObject(no);
324 if(dtl != NULL)
326 struct Node *node=dtl->dtl_SortedList.lh_Head;
327 while(node->ln_Succ != NULL)
329 // sorted list points to DT.dtn_Node2 ....
330 struct CompoundDatatype *cdt;
331 struct DataTypeHeader *dth;
332 STRPTR argarray[2];
334 if(CheckSignal(SIGBREAKF_CTRL_C))
336 Flush(Output());
337 PrintFault(ERROR_BREAK,0);
338 break;
340 cdt=(struct CompoundDatatype *)(node-1);
341 dth=cdt->DT.dtn_Header;
343 argarray[0] = dth->dth_BaseName;
344 argarray[1] = dth->dth_Name;
346 VPrintf("%s, \"%s\"\n", (IPTR *)argarray);
347 node = node->ln_Succ;
354 result = RETURN_OK;
355 FreeArgs(RDArgs);
359 ReleaseSemaphore(&DTList->dtl_Lock);
362 return result;
367 /****** AddDatatypes/DateScan *************************************************
369 * NAME
370 * DateScan - See if datatypes descriptors need updating
372 * SYNOPSIS
374 * FUNCTION
376 * INPUTS
378 * RETURNS
380 * EXAMPLE
382 * SEE ALSO
384 ******************************************************************************
388 BOOL DateScan(struct StackVars *sv)
390 BOOL result = TRUE;
391 BPTR lock;
392 struct FileInfoBlock *fib;
394 if((lock = Lock("DEVS:Datatypes", ACCESS_READ)))
396 if((fib = AllocDosObject(DOS_FIB, NULL)))
398 if(Examine(lock, fib))
400 if(!CompareDates(&fib->fib_Date, &DTList->dtl_DateStamp))
402 result = FALSE;
404 else
406 DTList->dtl_DateStamp = fib->fib_Date;
410 FreeDosObject(DOS_FIB,fib);
413 UnLock(lock);
416 return result;
421 /****** AddDatatypes/ScanDirectory ********************************************
423 * NAME
424 * ScanDirectory - Scan a directory recursively for DT descriptors
426 * SYNOPSIS
428 * FUNCTION
430 * INPUTS
432 * RETURNS
434 * EXAMPLE
436 * SEE ALSO
438 ******************************************************************************
442 void ScanDirectory(struct StackVars *sv, STRPTR pattern)
444 struct AnchorPath *AnchorPath;
445 LONG RetVal;
446 BPTR OldDir;
448 if((AnchorPath = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath),
449 MEMF_CLEAR)))
451 AnchorPath->ap_BreakBits = SIGBREAKF_CTRL_C;
453 RetVal = MatchFirst(pattern, AnchorPath);
455 while(!RetVal)
457 if(CheckSignal(SIGBREAKF_CTRL_C))
459 if(!AA.aa_Quiet)
461 PrintFault(ERROR_BREAK, NULL);
464 break;
467 if(AnchorPath->ap_Info.fib_DirEntryType > 0L)
469 if(!(AnchorPath->ap_Flags & APF_DIDDIR))
471 AnchorPath->ap_Flags |= APF_DODIR;
474 AnchorPath->ap_Flags &= ~APF_DIDDIR;
476 else
478 if(!MatchPatternNoCase(ExclPat,
479 AnchorPath->ap_Info.fib_FileName))
481 OldDir = CurrentDir(AnchorPath->ap_Current->an_Lock);
483 LoadDatatype(sv, AnchorPath->ap_Info.fib_FileName);
485 CurrentDir(OldDir);
489 RetVal = MatchNext(AnchorPath);
492 if(RetVal != ERROR_NO_MORE_ENTRIES)
494 if(!AA.aa_Quiet)
496 PrintFault(RetVal, NULL);
500 MatchEnd(AnchorPath);
502 FreeVec((APTR)AnchorPath);
507 /****** AddDatatypes/CreateDTList *********************************************
509 * NAME
510 * CreateDTList - Create and initialize the DataTypesList
512 * SYNOPSIS
514 * FUNCTION
516 * INPUTS
518 * RETURNS
520 * EXAMPLE
522 * SEE ALSO
524 ******************************************************************************
528 struct DataTypesList *CreateDTList(struct StackVars *sv)
530 struct DataTypesList *dtl = NULL;
531 struct NamedObject *no = NULL;
532 struct Library *DTBase;
534 /* We do this in order to force datatypes.library to get
535 loaded and initialized. During this process it will
536 create and install datatypes list object in memory. */
537 DTBase = OpenLibrary("datatypes.library", 0);
538 if (DTBase)
539 CloseLibrary(DTBase);
541 if((no = FindNamedObject(NULL, DATATYPESLIST, NULL)))
543 dtl = (struct DataTypesList*)no->no_Object;
546 if(dtl)
548 if(!__FindNameNoCase(sv, &dtl->dtl_BinaryList, "binary"))
550 CreateBasicType
552 sv, &dtl->dtl_BinaryList, &dtl->dtl_SortedList,
553 "binary", DTF_BINARY, ID_BINARY, GID_SYSTEM
557 if(!__FindNameNoCase(sv, &dtl->dtl_ASCIIList, "ascii"))
559 CreateBasicType
561 sv, &dtl->dtl_ASCIIList, &dtl->dtl_SortedList,
562 "ascii", DTF_ASCII, ID_ASCII, GID_TEXT
566 if(!__FindNameNoCase(sv, &dtl->dtl_IFFList, "iff"))
568 CreateBasicType
570 sv, &dtl->dtl_IFFList, &dtl->dtl_SortedList,
571 "iff", DTF_IFF, ID_IFF, GID_SYSTEM
575 if(!__FindNameNoCase(sv, &dtl->dtl_MiscList, "directory"))
577 CreateBasicType
579 sv, &dtl->dtl_MiscList, &dtl->dtl_SortedList,
580 "directory", DTF_MISC, ID_DIRECTORY, GID_SYSTEM
585 if(no)
587 ReleaseNamedObject(no);
591 return dtl;
596 /****** AddDatatypes/CreateBasicType ******************************************
598 * NAME
599 * CreateBasicType - Initialize one of the basic types
601 * SYNOPSIS
603 * FUNCTION
605 * INPUTS
607 * RETURNS
609 * EXAMPLE
611 * SEE ALSO
613 ******************************************************************************
617 struct CompoundDatatype *CreateBasicType(struct StackVars *sv,
618 struct List *list,
619 struct List *globallist, STRPTR name,
620 UWORD Flags, ULONG ID, ULONG GroupID)
622 struct CompoundDatatype *cdt;
623 ULONG AllocLen = sizeof(struct CompoundDatatype) + strlen(name) + 1;
625 if((cdt = AllocVec(AllocLen, MEMF_PUBLIC | MEMF_CLEAR)))
627 cdt->DT.dtn_Header = &cdt->DTH;
629 strcpy((UBYTE*)(cdt + 1), name);
631 cdt->DTH.dth_Name=
632 cdt->DTH.dth_BaseName=
633 cdt->DT.dtn_Node1.ln_Name=
634 cdt->DT.dtn_Node2.ln_Name=(UBYTE*)(cdt + 1);
636 cdt->DTH.dth_GroupID = GroupID;
637 cdt->DTH.dth_ID = ID;
639 cdt->DTH.dth_Flags = Flags;
641 NewList(&cdt->DT.dtn_ToolList);
643 cdt->DT.dtn_Length = AllocLen;
645 AddTail(list, &cdt->DT.dtn_Node1);
647 AlphaInsert(sv, globallist, &cdt->DT.dtn_Node2);
650 return cdt;
655 /****** AddDatatypes/LoadDatatype *********************************************
657 * NAME
658 * LoadDatatype - Load and install a single datatype descriptor
660 * SYNOPSIS
662 * FUNCTION
664 * INPUTS
666 * RETURNS
668 * EXAMPLE
670 * SEE ALSO
672 ******************************************************************************
676 void LoadDatatype(struct StackVars *sv, STRPTR name)
678 struct IFFHandle *iff;
680 if((iff = AllocIFF()))
682 if((iff->iff_Stream = (IPTR)Open(name, MODE_OLDFILE))) /* Why IPTR? */
684 InitIFFasDOS(iff);
686 if(!OpenIFF(iff, IFFF_READ))
688 if(!PropChunks(iff, PropArray, NUM_PROP))
690 if(!CollectionChunks(iff, CollArray, NUM_COLL))
692 if(!StopOnExit(iff, ID_DTYP, ID_FORM))
694 LONG error;
696 while((error = ParseIFF(iff, IFFPARSE_SCAN)) == IFFERR_EOC)
698 CreateDatatype(sv, iff);
699 /* FIXME: The while ParseIFF loop here crashes the 2nd time inside the loop, therefore the break below as temp fix */
700 break;
706 CloseIFF(iff);
709 Close((BPTR)iff->iff_Stream);
712 FreeIFF(iff);
714 else
716 SetIoErr(ERROR_NO_FREE_STORE);
721 /****** AddDatatypes/MemStreamHook *******************************************
723 * NAME
724 * MemStreamHook - needed by ReadStruct
726 * SYNOPSIS
728 * FUNCTION
730 * INPUTS
732 * RETURNS
734 * EXAMPLE
736 * SEE ALSO
738 ******************************************************************************
742 LONG MemStreamHook(struct Hook * hook, UBYTE **memptr, Msg msg)
744 LONG rc;
746 switch (msg->MethodID)
748 case BEIO_READ:
749 rc = **memptr;
750 (*memptr)++;
751 break;
753 default:
754 rc = -1;
755 break;
758 return rc;
761 /****** AddDatatypes/CreateDatatype *******************************************
763 * NAME
764 * CreateDatatype - create a datatype from IFF chunks
766 * SYNOPSIS
768 * FUNCTION
770 * INPUTS
772 * RETURNS
774 * EXAMPLE
776 * SEE ALSO
778 ******************************************************************************
782 struct CompoundDatatype *CreateDatatype(struct StackVars *sv,
783 struct IFFHandle *iff)
785 struct CompoundDatatype *cdt = NULL;
786 struct StoredProperty *prop;
787 ULONG AllocLen;
788 UBYTE *func;
789 LONG DefaultStack = AROS_STACKSIZE, i;
790 BPTR SegList;
792 if((prop = FindProp(iff, ID_DTYP, ID_DTHD)))
794 AllocLen = sizeof(struct CompoundDatatype) -
795 32 + /* was sizeof(struct DataTypeHeader), but we must use struct size as it would be on Amiga */
796 prop->sp_Size;
798 if(!(cdt = AllocVec(AllocLen, MEMF_PUBLIC | MEMF_CLEAR)))
800 SetIoErr(ERROR_NO_FREE_STORE);
802 else
804 struct FileDataTypeHeader *fdh;
805 UBYTE *memptr = (UBYTE *)prop->sp_Data;
806 struct Hook hook;
808 hook.h_Entry = (HOOKFUNC)HookEntry;
809 hook.h_SubEntry = (HOOKFUNC)MemStreamHook;
811 if (ReadStruct(&hook, (APTR *) &fdh, &memptr, FileDataTypeHeaderDesc))
813 IPTR extraoffset = sizeof(struct DataTypeHeader) - 32;
815 cdt->DT.dtn_Header= &cdt->DTH;
817 cdt->DTH.dth_Name = (STRPTR)(fdh->fdth_NameOffset + extraoffset + (IPTR)&cdt->DTH);
818 cdt->DTH.dth_BaseName = (STRPTR)(fdh->fdth_BaseNameOffset + extraoffset + (IPTR)&cdt->DTH);
819 cdt->DTH.dth_Pattern = (STRPTR)(fdh->fdth_PatternOffset + extraoffset + (IPTR)&cdt->DTH);
820 cdt->DTH.dth_Mask = (WORD *)(fdh->fdth_MaskOffset + extraoffset + (IPTR)&cdt->DTH);
821 cdt->DTH.dth_GroupID = fdh->fdth_GroupID;
822 cdt->DTH.dth_ID = fdh->fdth_ID;
823 cdt->DTH.dth_MaskLen = fdh->fdth_MaskLen;
824 cdt->DTH.dth_Pad = fdh->fdth_Pad;
825 cdt->DTH.dth_Flags = fdh->fdth_Flags;
826 cdt->DTH.dth_Priority = fdh->fdth_Priority;
828 CopyMem(prop->sp_Data + 32, cdt + 1, prop->sp_Size - 32);
830 for(i = 0; i < cdt->DTH.dth_MaskLen; i++)
832 cdt->DTH.dth_Mask[i] = AROS_BE2WORD(cdt->DTH.dth_Mask[i]);
833 #if 0
834 kprintf("mask[%d] = %04x (%c %c)\n", i,
835 cdt->DTH.dth_Mask[i],
836 cdt->DTH.dth_Mask[i] & 255,
837 (cdt->DTH.dth_Mask[i] >> 8) & 255);
838 #endif
841 #if 0
842 kprintf("groupid = %c%c%c%c\n", cdt->DTH.dth_GroupID >> 24,
843 cdt->DTH.dth_GroupID >> 16,
844 cdt->DTH.dth_GroupID >> 8,
845 cdt->DTH.dth_GroupID);
846 kprintf("id = %c%c%c%c\n", cdt->DTH.dth_ID >> 24,
847 cdt->DTH.dth_ID >> 16,
848 cdt->DTH.dth_ID >> 8,
849 cdt->DTH.dth_ID);
850 kprintf("flags = %x\n", cdt->DTH.dth_Flags);
851 kprintf("pri = %d\n", cdt->DTH.dth_Priority);
852 kprintf("name = %s\n", cdt->DTH.dth_Name);
853 kprintf("basename = %s\n", cdt->DTH.dth_BaseName);
854 kprintf("pattern = %s\n", cdt->DTH.dth_Pattern);
855 kprintf("masklen = %d\n", cdt->DTH.dth_MaskLen);
856 #endif
858 NewList(&cdt->DT.dtn_ToolList);
860 cdt->DT.dtn_Length = AllocLen;
862 if((prop = FindProp(iff, ID_DTYP, ID_DTCD)))
864 if((func = AllocVec(prop->sp_Size, MEMF_PUBLIC | MEMF_CLEAR)))
866 cdt->DTCDChunk = func;
867 cdt->DTCDSize = prop->sp_Size;
869 CopyMem(prop->sp_Data,func,prop->sp_Size);
871 HookBuffer = cdt->DTCDChunk;
872 HookBufSize = cdt->DTCDSize;
873 HookPosition = 0;
875 /* We use a cast to BPTR, since sv may not
876 * be ULONG aligned. Since only our ReadFunc
877 * is going to be looking at it, this is ok.
879 if((SegList = InternalLoadSeg((BPTR)(sv), BNULL,
880 (LONG_FUNC *)FunctionArray,
881 &DefaultStack)))
883 cdt->SegList = SegList;
884 cdt->Function = BADDR(SegList) + sizeof(BPTR);
887 } /* if((func = AllocVec(prop->sp_Size, MEMF_PUBLIC | MEMF_CLEAR))) */
889 } /* if((prop = FindProp(iff, ID_DTYP, ID_DTCD))) */
891 cdt = AddDatatype(sv, cdt);
893 FreeStruct(fdh, FileDataTypeHeaderDesc);
895 } /* if (ReadStruct(&hook, &fdh, &memptr, FileDataTypeHeaderDesc)) */
897 } /* cdt AllocVec okay */
899 } /* if((prop = FindProp(iff, ID_DTYP, ID_DTHD))) */
901 return cdt;
906 /****** AddDatatypes/AddDatatype **********************************************
908 * NAME
909 * AddDatatype - add a datatype to the system
911 * SYNOPSIS
913 * FUNCTION
915 * This subroutine tries to add a datatype to the system datatypes
916 * list. If the datatype already exists, it will be replaced or
917 * updated. In case of an error, the CompoundDatatype will be deleted
918 * and a NULL pointer is returned.
920 * The CompoundDatatype pointer you passed in will be invalid after
921 * calling this function. Use the returned handle instead.
922 * DO NOT USE THE OLD POINTER IN ANY MORE!
924 * INPUTS
926 * RETURNS
928 * A pointer to a CompoundDatatype in the system datatypes list
929 * or a NULL pointer for failure
931 * EXAMPLE
933 * SEE ALSO
935 ******************************************************************************
939 struct CompoundDatatype *AddDatatype(struct StackVars *sv,
940 struct CompoundDatatype *cdt)
942 struct List *typelist;
943 BOOL Success = FALSE;
944 ULONG AllocSize;
945 ULONG result;
946 struct CompoundDatatype *oldcdt;
948 switch(cdt->DTH.dth_Flags & DTF_TYPE_MASK)
950 case DTF_BINARY: typelist= &DTList->dtl_BinaryList; break;
951 case DTF_ASCII: typelist= &DTList->dtl_ASCIIList; break;
952 case DTF_IFF: typelist= &DTList->dtl_IFFList; break;
953 case DTF_MISC: typelist= &DTList->dtl_MiscList; break;
954 default: typelist= NULL;
957 if(typelist)
959 cdt->DT.dtn_Node1.ln_Name = cdt->DT.dtn_Node2.ln_Name = cdt->DTH.dth_Name;
961 Success = TRUE;
963 if((!Stricmp(cdt->DTH.dth_Pattern, "#?")) ||
964 (!strlen(cdt->DTH.dth_Pattern)) )
966 cdt->FlagLong |= CFLGF_PATTERN_UNUSED;
968 else
970 cdt->FlagLong &= ~(CFLGF_PATTERN_UNUSED);
972 AllocSize = 2*strlen(cdt->DTH.dth_Pattern) + 2;
974 if(!(cdt->ParsePatMem = AllocVec(AllocSize,
975 MEMF_PUBLIC | MEMF_CLEAR)))
977 Success = FALSE;
979 else
981 cdt->ParsePatSize = AllocSize;
983 result = ParsePatternNoCase(cdt->DTH.dth_Pattern,
984 cdt->ParsePatMem, AllocSize);
986 if(result == 1)
988 cdt->FlagLong |= CFLGF_IS_WILD;
990 else
992 FreeVec(cdt->ParsePatMem);
993 cdt->ParsePatMem = NULL;
994 cdt->ParsePatSize = 0;
996 if(result == 0)
998 cdt->FlagLong &= ~(CFLGF_IS_WILD);
1000 else
1002 Success = FALSE;
1008 if (Success)
1010 if((oldcdt = (struct CompoundDatatype*)__FindNameNoCase(sv,
1011 typelist,
1012 cdt->DT.dtn_Node1.ln_Name)))
1014 if (oldcdt->OpenCount)
1016 Success = FALSE;
1018 else
1020 if((Stricmp(oldcdt->DTH.dth_Name, cdt->DTH.dth_Name)) ||
1021 (Stricmp(oldcdt->DTH.dth_BaseName, cdt->DTH.dth_BaseName)) ||
1022 (Stricmp(oldcdt->DTH.dth_Pattern, cdt->DTH.dth_Pattern)) ||
1023 (oldcdt->DTH.dth_Flags != cdt->DTH.dth_Flags) ||
1024 (oldcdt->DTH.dth_Priority != cdt->DTH.dth_Priority) ||
1025 (oldcdt->DTH.dth_MaskLen != cdt->DTH.dth_MaskLen))
1027 DeleteDatatype(sv, oldcdt);
1028 oldcdt = NULL;
1030 else
1032 oldcdt->DTH.dth_GroupID = cdt->DTH.dth_GroupID;
1033 oldcdt->DTH.dth_ID = cdt->DTH.dth_ID;
1034 CopyMem(cdt->DTH.dth_Mask,cdt->DTH.dth_Mask,
1035 (ULONG)(sizeof(WORD)*cdt->DTH.dth_MaskLen));
1040 if(Success)
1042 if(oldcdt)
1044 DeleteDatatype(sv, cdt);
1045 cdt = oldcdt;
1047 else
1049 if(cdt->DT.dtn_FunctionName)
1051 LONG DefaultStack = 4096;
1052 BPTR file;
1053 ULONG AllocLen;
1054 BPTR SegList;
1056 if((file = Open(cdt->DT.dtn_FunctionName, MODE_OLDFILE)))
1058 if(Seek(file, 0, OFFSET_END) >= 0)
1060 if((AllocLen = Seek(file, 0,
1061 OFFSET_BEGINNING)) > 0)
1063 if((cdt->DTCDChunk = AllocVec(AllocLen,
1064 MEMF_PUBLIC | MEMF_CLEAR)))
1066 cdt->DTCDSize = AllocLen;
1068 if(Read(file, cdt->DTCDChunk, AllocLen) == AllocLen)
1070 HookBuffer = cdt->DTCDChunk;
1071 HookBufSize = cdt->DTCDSize;
1072 HookPosition = 0;
1074 /* We use a cast to BPTR, since sv may not
1075 * be ULONG aligned. Since only our ReadFunc
1076 * is going to be looking at it, this is ok.
1078 if((SegList = InternalLoadSeg((BPTR)(sv), BNULL, (LONG_FUNC *)FunctionArray, &DefaultStack)))
1080 cdt->SegList = SegList;
1081 cdt->Function = BADDR(SegList) + sizeof(BPTR); // FIXME: is this portable?
1084 else
1086 FreeVec(cdt->DTCDChunk);
1087 cdt->DTCDChunk = NULL;
1088 cdt->DTCDSize = 0;
1094 cdt->DT.dtn_FunctionName=NULL;
1097 if(cdt->DTH.dth_MaskLen > DTList->dtl_LongestMask)
1099 DTList->dtl_LongestMask = cdt->DTH.dth_MaskLen;
1102 PrioInsert(sv, typelist, cdt);
1104 AlphaInsert(sv, &DTList->dtl_SortedList, &cdt->DT.dtn_Node2);
1110 if(!Success)
1112 DeleteDatatype(sv, cdt);
1113 cdt = NULL;
1116 return cdt;
1121 /****** AddDatatypes/DeleteDatatype *******************************************
1123 * NAME
1124 * DeleteDatatype - unlink and deallocate a CompoundDatatype structure
1126 * SYNOPSIS
1128 * FUNCTION
1130 * INPUTS
1132 * RETURNS
1134 * EXAMPLE
1136 * SEE ALSO
1138 ******************************************************************************
1142 void DeleteDatatype(struct StackVars *sv, struct CompoundDatatype *cdt)
1144 if(cdt)
1146 if(cdt->ParsePatMem)
1148 FreeVec(cdt->ParsePatMem);
1149 cdt->ParsePatMem = NULL;
1150 cdt->ParsePatSize = 0;
1153 if(cdt->DTCDChunk)
1155 FreeVec(cdt->DTCDChunk);
1156 cdt->DTCDChunk = NULL;
1157 cdt->DTCDSize = 0;
1160 if(cdt->SegList)
1162 UnLoadSeg(cdt->SegList);
1163 cdt->SegList = BNULL;
1164 cdt->Function = NULL;
1167 if(cdt->DT.dtn_Node1.ln_Succ && cdt->DT.dtn_Node1.ln_Pred)
1169 Remove(&cdt->DT.dtn_Node1);
1170 Remove(&cdt->DT.dtn_Node2);
1171 cdt->DT.dtn_Node1.ln_Succ = cdt->DT.dtn_Node1.ln_Pred =
1172 cdt->DT.dtn_Node2.ln_Succ = cdt->DT.dtn_Node2.ln_Pred = NULL;
1175 FreeVec(cdt);
1181 /****** AddDatatypes/AlphaInsert **********************************************
1183 * NAME
1184 * AlphaInsert - enqueue a node alphabetically into a list
1186 * SYNOPSIS
1188 * FUNCTION
1190 * INPUTS
1192 * RETURNS
1194 * EXAMPLE
1196 * SEE ALSO
1198 ******************************************************************************
1202 void AlphaInsert(struct StackVars *sv, struct List *list, struct Node *node)
1204 struct Node *cur,*prev=NULL;
1206 for(cur = list->lh_Head; cur->ln_Succ; prev = cur, cur = cur->ln_Succ)
1208 if(Stricmp(cur->ln_Name, node->ln_Name) > 0)
1209 break;
1212 Insert(list, node, prev);
1217 /****** AddDatatypes/PrioInsert **********************************************
1219 * NAME
1220 * PrioInsert - enqueue a CompoundDatatype correctly in the type list
1222 * SYNOPSIS
1224 * FUNCTION
1226 * INPUTS
1228 * RETURNS
1230 * EXAMPLE
1232 * SEE ALSO
1234 ******************************************************************************
1238 void PrioInsert(struct StackVars *sv, struct List *list,
1239 struct CompoundDatatype *cdt)
1241 struct CompoundDatatype *cur, *prev = NULL;
1242 WORD diff;
1244 for(cur = (struct CompoundDatatype*)list->lh_Head;
1245 cur->DT.dtn_Node1.ln_Succ;
1246 prev = cur, cur = (struct CompoundDatatype*)cur->DT.dtn_Node1.ln_Succ)
1248 diff = (cdt->Function ? 1 : 0) - (cur->Function ? 1 : 0);
1250 if(diff > 0)
1251 break;
1253 if(!diff)
1255 UWORD MinMask = (cdt->DTH.dth_MaskLen < cur->DTH.dth_MaskLen) ?
1256 cdt->DTH.dth_MaskLen : cur->DTH.dth_MaskLen;
1257 WORD *cdtmask = cdt->DTH.dth_Mask;
1258 WORD *curmask=cur->DTH.dth_Mask;
1260 while(!diff && MinMask--)
1261 diff= *(curmask++) - *(cdtmask++);
1263 if(diff > 0)
1264 break;
1266 if(!diff)
1268 diff = cdt->DTH.dth_MaskLen - cur->DTH.dth_MaskLen;
1270 if(diff > 0)
1271 break;
1273 if(!diff)
1275 diff = (((cdt->FlagLong & CFLGF_PATTERN_UNUSED) || cdt->DTH.dth_Pattern==NULL) ? 0 : 1) -
1276 (((cur->FlagLong & CFLGF_PATTERN_UNUSED) || cur->DTH.dth_Pattern==NULL) ? 0 : 1);
1278 if(diff > 0)
1279 break;
1281 if(!diff)
1283 diff = cdt->DTH.dth_Priority - cur->DTH.dth_Priority;
1285 if(diff > 0)
1286 break;
1293 Insert(list, &cdt->DT.dtn_Node1, (struct Node *)prev);
1298 /****** AddDatatypes/__FindNameNoCase *****************************************
1300 * NAME
1301 * __FindNameNoCase - find a node in a list (case insensitive)
1303 * SYNOPSIS
1305 * FUNCTION
1307 * INPUTS
1309 * RETURNS
1311 * EXAMPLE
1313 * SEE ALSO
1315 ******************************************************************************
1319 struct Node *__FindNameNoCase(struct StackVars *sv, struct List *list,
1320 STRPTR name)
1322 struct Node *node;
1323 struct Node *result = NULL;
1325 for(node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
1327 if(!Stricmp(node->ln_Name, name))
1329 result = node;
1330 break;
1334 return result;
1339 /****** AddDatatypes/ReadFunc *************************************************
1341 * NAME
1342 * ReadFunc - data read hook for InternalLoadSeg
1344 * SYNOPSIS
1346 * FUNCTION
1348 * INPUTS
1350 * RETURNS
1352 * EXAMPLE
1354 * SEE ALSO
1356 ******************************************************************************
1360 AROS_UFH4(LONG, AROS_SLIB_ENTRY(ReadFunc, AddDatatypes, 0),
1361 AROS_UFHA(BPTR , fh , D1),
1362 AROS_UFHA(void * , buffer , D2),
1363 AROS_UFHA(LONG , length , D3),
1364 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1366 AROS_USERFUNC_INIT
1368 struct StackVars *sv = (APTR)fh;
1369 LONG maxlen = HookBufSize-HookPosition;
1370 LONG actual = length > maxlen ? maxlen : length;
1372 CopyMem(HookBuffer+HookPosition, buffer, actual);
1374 HookPosition += actual;
1376 return actual;
1378 AROS_USERFUNC_EXIT
1381 /****** AddDatatypes/SeekFunc *************************************************
1383 * NAME
1384 * SeekFunc - seek hook for InternalLoadSeg (ELF only)
1386 * SYNOPSIS
1388 * FUNCTION
1390 * INPUTS
1392 * RETURNS
1394 * EXAMPLE
1396 * SEE ALSO
1398 ******************************************************************************
1402 AROS_UFH4(LONG, AROS_SLIB_ENTRY(SeekFunc, AddDatatypes, 0),
1403 AROS_UFHA(BPTR , fh , D1),
1404 AROS_UFHA(LONG , pos , D2),
1405 AROS_UFHA(LONG , mode , D3),
1406 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1408 AROS_USERFUNC_INIT
1410 struct StackVars *sv = (APTR)fh;
1411 LONG oldpos = HookPosition;
1413 switch (mode) {
1414 case OFFSET_BEGINNING: break;
1415 case OFFSET_END: pos = HookBufSize - pos; break;
1416 case OFFSET_CURRENT: pos = HookPosition + pos; break;
1417 default: return -1;
1420 if (pos < 0 || pos >= HookBufSize)
1421 return -1;
1423 HookPosition = pos;
1425 return oldpos;
1427 AROS_USERFUNC_EXIT
1430 /****** AddDatatypes/AllocFunc ************************************************
1432 * NAME
1433 * AllocFunc - memory allocation hook for InternalLoadSeg
1435 * SYNOPSIS
1437 * FUNCTION
1439 * INPUTS
1441 * RETURNS
1443 * EXAMPLE
1445 * SEE ALSO
1447 ******************************************************************************
1451 AROS_UFH3(UBYTE *, AROS_SLIB_ENTRY(AllocFunc, AddDatatypes, 0),
1452 AROS_UFHA(ULONG, size, D0),
1453 AROS_UFHA(ULONG, flags,D1),
1454 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1456 AROS_USERFUNC_INIT
1458 return(AllocMem(size, flags));
1460 AROS_USERFUNC_EXIT
1465 /****** AddDatatypes/FreeFunc *************************************************
1467 * NAME
1468 * FreeFunc - memory freeing hook for InternalLoadSeg
1470 * SYNOPSIS
1472 * FUNCTION
1474 * INPUTS
1476 * RETURNS
1478 * EXAMPLE
1480 * SEE ALSO
1482 ******************************************************************************
1486 AROS_UFH3(void, AROS_SLIB_ENTRY(FreeFunc, AddDatatypes, 0),
1487 AROS_UFHA(APTR , memory, A1),
1488 AROS_UFHA(ULONG, size , D0),
1489 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1491 AROS_USERFUNC_INIT
1493 FreeMem(memory, size);
1495 AROS_USERFUNC_EXIT
1500 /******************************* STUB ROUTINES ********************************/
1502 struct NamedObject *allocnamedobject(struct StackVars *sv, STRPTR name,
1503 Tag FirstTag, ...)
1505 return AllocNamedObjectA(name, (struct TagItem*)&FirstTag);