# build AddDataTypes separately.
[AROS.git] / workbench / c / AddDataTypes.c
blobfc580546f4486c27b92d9da40190a55daa27506e
1 /*
2 Copyright © 1995-2012, 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 DataTypes 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 #define DEBUG 0
59 #include <aros/debug.h>
61 #include <aros/macros.h>
62 #include <aros/bigendianio.h>
63 #include <exec/types.h>
64 #include <exec/memory.h>
65 #include <exec/execbase.h>
66 #include <dos/dos.h>
67 #include <dos/dosasl.h>
68 #include <dos/dosextens.h>
69 #include <libraries/iffparse.h>
70 #include <utility/name.h>
71 #include <utility/hooks.h>
72 #include <workbench/startup.h>
74 #include <proto/exec.h>
75 #include <proto/alib.h>
76 #include <proto/dos.h>
77 #include <proto/utility.h>
78 #include <proto/iffparse.h>
79 #include <proto/alib.h>
80 #include <proto/arossupport.h>
82 #include <string.h>
84 #include "../libs/datatypes/datatypes_intern.h"
85 #undef DOSBase
86 #undef UtilityBase
87 #undef IFFParseBase
88 #undef LocaleBase
89 #undef DTList
91 /******************************** STRUCTURES *********************************/
93 /* same as datatypes/datatypes.h/struct DataTypeHeader, but always big endian
94 and 32 bit pointers (which in the file are actually offsets) */
96 struct FileDataTypeHeader
98 ULONG fdth_NameOffset; /* Name of the data type */
99 ULONG fdth_BaseNameOffset; /* Base name of the data type */
100 ULONG fdth_PatternOffset; /* File name match pattern */
101 ULONG fdth_MaskOffset; /* Comparision mask (binary) */
102 ULONG fdth_GroupID; /* DataType Group */
103 ULONG fdth_ID; /* DataType ID (same as IFF FORM type) */
104 WORD fdth_MaskLen; /* Length of the comparision mask */
105 WORD fdth_Pad; /* Unused at present (must be 0) */
106 UWORD fdth_Flags; /* Flags -- see below */
107 UWORD fdth_Priority;
110 #define O(x) offsetof(struct FileDataTypeHeader,x)
112 static const IPTR FileDataTypeHeaderDesc[] =
114 sizeof(struct FileDataTypeHeader),
115 SDM_ULONG(O(fdth_NameOffset)),
116 SDM_ULONG(O(fdth_BaseNameOffset)),
117 SDM_ULONG(O(fdth_PatternOffset)),
118 SDM_ULONG(O(fdth_MaskOffset)),
119 SDM_ULONG(O(fdth_GroupID)),
120 SDM_ULONG(O(fdth_ID)),
121 SDM_WORD(O(fdth_MaskLen)),
122 SDM_WORD(O(fdth_Pad)),
123 SDM_UWORD(O(fdth_Flags)),
124 SDM_UWORD(O(fdth_Priority)),
125 SDM_END
128 /******************************** PROTOTYPES *********************************/
130 struct StackVars; /* forward declaration */
132 BOOL DateScan(struct StackVars *sv);
133 void ScanDirectory(struct StackVars *sv, STRPTR pattern);
134 struct DataTypesList *CreateDTList(struct StackVars *sv);
135 struct CompoundDataType *CreateBasicType(struct StackVars *sv,
136 struct List *list,
137 struct List *globallist, STRPTR name,
138 UWORD Flags, ULONG ID, ULONG GroupID);
139 void LoadDataType(struct StackVars *sv, STRPTR name);
140 struct CompoundDataType *CreateDataType(struct StackVars *sv,
141 struct IFFHandle *iff, STRPTR name);
142 struct CompoundDataType *AddDataType(struct StackVars *sv,
143 struct CompoundDataType *cdt);
144 void DeleteDataType(struct StackVars *sv, struct CompoundDataType *cdt);
145 void AlphaInsert(struct StackVars *sv, struct List *list, struct Node *node);
146 struct Node *__FindNameNoCase(struct StackVars *sv, struct List *list,
147 STRPTR name);
149 AROS_UFP4(LONG, AROS_SLIB_ENTRY(ReadFunc, AddDataTypes, 0),
150 AROS_UFPA(BPTR , fh , D1),
151 AROS_UFPA(void * , buf , D2),
152 AROS_UFPA(LONG , size , D3),
153 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
154 AROS_UFP4(LONG, AROS_SLIB_ENTRY(SeekFunc, AddDataTypes, 0),
155 AROS_UFPA(BPTR , fh , D1),
156 AROS_UFPA(LONG , pos , D2),
157 AROS_UFPA(LONG , mode , D3),
158 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
159 AROS_UFP3(UBYTE *, AROS_SLIB_ENTRY(AllocFunc, AddDataTypes, 0),
160 AROS_UFPA(ULONG, size, D0),
161 AROS_UFPA(ULONG, req, D1),
162 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
163 AROS_UFP3(void, AROS_SLIB_ENTRY(FreeFunc, AddDataTypes, 0),
164 AROS_UFPA(APTR , memory, A1),
165 AROS_UFPA(ULONG, size , D0),
166 AROS_UFPA(struct DosLibrary *, DOSBase, A6));
168 /********************************* CONSTANTS *********************************/
170 const TEXT Version[] = "$VER: AddDataTypes 42.1 (8.12.2007)\n";
172 #define EXCL_LEN 18
173 UBYTE ExcludePattern[] = "#?.(info|backdrop)";
175 UBYTE Template[] = "FILES/M,QUIET/S,REFRESH/S,LIST/S";
177 struct ArgArray
179 UBYTE **aa_Files;
180 IPTR aa_Quiet;
181 IPTR aa_Refresh;
182 IPTR aa_List;
185 #define ID_DTCD MAKE_ID('D','T','C','D')
186 #define ID_DTTL MAKE_ID('D','T','T','L')
188 #define NUM_PROP 2
190 LONG PropArray[2*NUM_PROP]=
192 ID_DTYP, ID_DTHD,
193 ID_DTYP, ID_DTCD
196 #define NUM_COLL 1
198 const LONG const CollArray[2*NUM_COLL]=
200 ID_DTYP, ID_DTTL
204 const LONG_FUNC const FunctionArray[]=
205 { /* Note! */
206 (LONG_FUNC)AROS_SLIB_ENTRY(ReadFunc, AddDataTypes, 0),
207 (LONG_FUNC)AROS_SLIB_ENTRY(AllocFunc, AddDataTypes, 0),
208 (LONG_FUNC)AROS_SLIB_ENTRY(FreeFunc, AddDataTypes, 0),
209 (LONG_FUNC)AROS_SLIB_ENTRY(SeekFunc, AddDataTypes, 0), /* For ELF */
213 struct StackVars
215 struct DataTypesList *DTList;
216 UBYTE ExclPat[2*EXCL_LEN+2+1];
217 struct ArgArray AA;
218 UBYTE *HookBuffer;
219 ULONG HookBufSize;
220 ULONG HookPosition;
223 #undef SysBase
224 #define DTList sv->DTList
225 #define ExclPat sv->ExclPat
226 #define AA sv->AA
227 #define HookBuffer sv->HookBuffer
228 #define HookBufSize sv->HookBufSize
229 #define HookPosition sv->HookPosition
231 /****** AddDataTypes/main *****************************************************
233 * NAME
234 * main - well... main
236 * SYNOPSIS
238 * FUNCTION
240 * INPUTS
242 * RETURNS
244 * EXAMPLE
246 * SEE ALSO
248 ******************************************************************************
251 int UtilityBase_version = 37;
252 int LocaleBase_version = 37;
253 int IFFParseBase_version = 37;
255 int __nocommandline = 1;
257 int main(void)
259 extern struct WBStartup *WBenchMsg;
260 struct StackVars vars;
261 struct StackVars *sv;
262 int result = RETURN_FAIL;
264 memset(&vars, 0, sizeof(struct StackVars));
265 sv = &vars;
267 if((DTList = CreateDTList(sv)))
269 ParsePatternNoCase(ExcludePattern, ExclPat, sizeof(ExclPat));
271 ObtainSemaphore(&DTList->dtl_Lock);
273 if(WBenchMsg)
275 UWORD num;
276 struct WBArg *wa = &WBenchMsg->sm_ArgList[1];
278 for(num = 1; num<WBenchMsg->sm_NumArgs; wa++)
280 BPTR olddir = CurrentDir(wa->wa_Lock);
281 LoadDataType(sv, wa->wa_Name);
282 CurrentDir(olddir);
285 result = RETURN_OK;
287 else
289 struct RDArgs *RDArgs;
291 if(!(RDArgs = ReadArgs(Template, (SIPTR*)&AA, NULL)))
293 PrintFault(IoErr(), NULL);
295 else
297 if(AA.aa_Refresh)
299 if(DateScan(sv))
301 ScanDirectory(sv, "DEVS:DataTypes");
304 else
306 UBYTE **files = AA.aa_Files;
308 if(files)
310 while(*files)
312 ScanDirectory(sv, *files);
313 files++;
318 if(AA.aa_List)
320 struct DataTypesList *dtl = NULL;
321 struct NamedObject *no = NULL;
322 if((no = FindNamedObject(NULL, DATATYPESLIST, NULL)))
324 dtl = (struct DataTypesList*)no->no_Object;
325 ReleaseNamedObject(no);
326 if(dtl != NULL)
328 struct Node *node=dtl->dtl_SortedList.lh_Head;
329 while(node->ln_Succ != NULL)
331 // sorted list points to DT.dtn_Node2 ....
332 struct CompoundDataType *cdt;
333 struct DataTypeHeader *dth;
335 if(CheckSignal(SIGBREAKF_CTRL_C))
337 Flush(Output());
338 PrintFault(ERROR_BREAK,0);
339 break;
341 cdt=(struct CompoundDataType *)(node-1);
342 dth=cdt->DT.dtn_Header;
345 Printf("%s, \"%s\"\n", dth->dth_BaseName, dth->dth_Name);
346 node = node->ln_Succ;
353 result = RETURN_OK;
354 FreeArgs(RDArgs);
358 ReleaseSemaphore(&DTList->dtl_Lock);
361 return result;
366 /****** AddDataTypes/DateScan *************************************************
368 * NAME
369 * DateScan - See if DataTypes descriptors need updating
371 * SYNOPSIS
373 * FUNCTION
375 * INPUTS
377 * RETURNS
379 * EXAMPLE
381 * SEE ALSO
383 ******************************************************************************
387 BOOL DateScan(struct StackVars *sv)
389 BOOL result = TRUE;
390 BPTR lock;
391 struct FileInfoBlock *fib;
393 if((lock = Lock("DEVS:DataTypes", ACCESS_READ)))
395 if((fib = AllocDosObject(DOS_FIB, NULL)))
397 if(Examine(lock, fib))
399 if(!CompareDates(&fib->fib_Date, &DTList->dtl_DateStamp))
401 result = FALSE;
403 else
405 DTList->dtl_DateStamp = fib->fib_Date;
409 FreeDosObject(DOS_FIB,fib);
412 UnLock(lock);
415 return result;
420 /****** AddDataTypes/ScanDirectory ********************************************
422 * NAME
423 * ScanDirectory - Scan a directory recursively for DT descriptors
425 * SYNOPSIS
427 * FUNCTION
429 * INPUTS
431 * RETURNS
433 * EXAMPLE
435 * SEE ALSO
437 ******************************************************************************
441 void ScanDirectory(struct StackVars *sv, STRPTR pattern)
443 struct AnchorPath *AnchorPath;
444 LONG RetVal;
445 BPTR OldDir;
447 if((AnchorPath = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath),
448 MEMF_CLEAR)))
450 AnchorPath->ap_BreakBits = SIGBREAKF_CTRL_C;
452 RetVal = MatchFirst(pattern, AnchorPath);
454 while(!RetVal)
456 if(CheckSignal(SIGBREAKF_CTRL_C))
458 if(!AA.aa_Quiet)
460 PrintFault(ERROR_BREAK, NULL);
463 break;
466 if(AnchorPath->ap_Info.fib_DirEntryType > 0L)
468 if(!(AnchorPath->ap_Flags & APF_DIDDIR))
470 AnchorPath->ap_Flags |= APF_DODIR;
473 AnchorPath->ap_Flags &= ~APF_DIDDIR;
475 else
477 if(!MatchPatternNoCase(ExclPat,
478 AnchorPath->ap_Info.fib_FileName))
480 OldDir = CurrentDir(AnchorPath->ap_Current->an_Lock);
482 LoadDataType(sv, AnchorPath->ap_Info.fib_FileName);
484 CurrentDir(OldDir);
488 RetVal = MatchNext(AnchorPath);
491 if(RetVal != ERROR_NO_MORE_ENTRIES)
493 if(!AA.aa_Quiet)
495 PrintFault(RetVal, NULL);
499 MatchEnd(AnchorPath);
501 FreeVec((APTR)AnchorPath);
506 /****** AddDataTypes/CreateDTList *********************************************
508 * NAME
509 * CreateDTList - Create and initialize the DataTypesList
511 * SYNOPSIS
513 * FUNCTION
515 * INPUTS
517 * RETURNS
519 * EXAMPLE
521 * SEE ALSO
523 ******************************************************************************
527 struct DataTypesList *CreateDTList(struct StackVars *sv)
529 struct DataTypesList *dtl = NULL;
530 struct NamedObject *no = NULL;
531 struct Library *DTBase;
533 /* We do this in order to force datatypes.library to get
534 loaded and initialized. During this process it will
535 create and install DataTypes list object in memory. */
536 DTBase = OpenLibrary("datatypes.library", 0);
537 if (DTBase)
538 CloseLibrary(DTBase);
540 if((no = FindNamedObject(NULL, DATATYPESLIST, NULL)))
542 dtl = (struct DataTypesList*)no->no_Object;
545 if(dtl)
547 if(!__FindNameNoCase(sv, &dtl->dtl_BinaryList, "binary"))
549 CreateBasicType
551 sv, &dtl->dtl_BinaryList, &dtl->dtl_SortedList,
552 "binary", DTF_BINARY, ID_BINARY, GID_SYSTEM
556 if(!__FindNameNoCase(sv, &dtl->dtl_ASCIIList, "ascii"))
558 CreateBasicType
560 sv, &dtl->dtl_ASCIIList, &dtl->dtl_SortedList,
561 "ascii", DTF_ASCII, ID_ASCII, GID_TEXT
565 if(!__FindNameNoCase(sv, &dtl->dtl_IFFList, "iff"))
567 CreateBasicType
569 sv, &dtl->dtl_IFFList, &dtl->dtl_SortedList,
570 "iff", DTF_IFF, ID_IFF, GID_SYSTEM
574 if(!__FindNameNoCase(sv, &dtl->dtl_MiscList, "directory"))
576 CreateBasicType
578 sv, &dtl->dtl_MiscList, &dtl->dtl_SortedList,
579 "directory", DTF_MISC, ID_DIRECTORY, GID_SYSTEM
584 if(no)
586 ReleaseNamedObject(no);
590 return dtl;
595 /****** AddDataTypes/CreateBasicType ******************************************
597 * NAME
598 * CreateBasicType - Initialize one of the basic types
600 * SYNOPSIS
602 * FUNCTION
604 * INPUTS
606 * RETURNS
608 * EXAMPLE
610 * SEE ALSO
612 ******************************************************************************
616 struct CompoundDataType *CreateBasicType(struct StackVars *sv,
617 struct List *list,
618 struct List *globallist, STRPTR name,
619 UWORD Flags, ULONG ID, ULONG GroupID)
621 struct CompoundDataType *cdt;
622 ULONG AllocLen = sizeof(struct CompoundDataType) + strlen(name) + 1;
624 if((cdt = AllocVec(AllocLen, MEMF_PUBLIC | MEMF_CLEAR)))
626 cdt->DT.dtn_Header = &cdt->DTH;
628 strcpy((UBYTE*)(cdt + 1), name);
630 cdt->DTH.dth_Name=
631 cdt->DTH.dth_BaseName=
632 cdt->DT.dtn_Node1.ln_Name=
633 cdt->DT.dtn_Node2.ln_Name=(UBYTE*)(cdt + 1);
635 cdt->DTH.dth_GroupID = GroupID;
636 cdt->DTH.dth_ID = ID;
638 cdt->DTH.dth_Flags = Flags;
640 NewList(&cdt->DT.dtn_ToolList);
642 cdt->DT.dtn_Length = AllocLen;
644 cdt->DT.dtn_Node1.ln_Pri = -128;
645 Enqueue(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, name);
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, STRPTR name)
785 struct CompoundDataType *cdt = NULL;
786 struct StoredProperty *prop;
787 #if __mc68000
788 LONG DefaultStack = AROS_STACKSIZE;
789 UBYTE *func;
790 #endif
791 ULONG AllocLen, i;
792 BPTR SegList;
794 if((prop = FindProp(iff, ID_DTYP, ID_DTHD)))
796 AllocLen = sizeof(struct CompoundDataType) -
797 32 + /* was sizeof(struct DataTypeHeader), but we must use struct size as it would be on Amiga */
798 prop->sp_Size;
800 if(!(cdt = AllocVec(AllocLen, MEMF_PUBLIC | MEMF_CLEAR)))
802 SetIoErr(ERROR_NO_FREE_STORE);
804 else
806 struct FileDataTypeHeader *fdh = NULL;
807 UBYTE *memptr = (UBYTE *)prop->sp_Data;
808 struct Hook hook;
810 hook.h_Entry = (HOOKFUNC)HookEntry;
811 hook.h_SubEntry = (HOOKFUNC)MemStreamHook;
813 if (ReadStruct(&hook, (APTR *) &fdh, &memptr, FileDataTypeHeaderDesc))
815 IPTR extraoffset = sizeof(struct DataTypeHeader) - 32;
817 cdt->DT.dtn_Header= &cdt->DTH;
819 cdt->DTH.dth_Name = (STRPTR)(fdh->fdth_NameOffset + extraoffset + (IPTR)&cdt->DTH);
820 cdt->DTH.dth_BaseName = (STRPTR)(fdh->fdth_BaseNameOffset + extraoffset + (IPTR)&cdt->DTH);
821 cdt->DTH.dth_Pattern = (STRPTR)(fdh->fdth_PatternOffset + extraoffset + (IPTR)&cdt->DTH);
822 cdt->DTH.dth_Mask = (WORD *)(fdh->fdth_MaskOffset + extraoffset + (IPTR)&cdt->DTH);
823 cdt->DTH.dth_GroupID = fdh->fdth_GroupID;
824 cdt->DTH.dth_ID = fdh->fdth_ID;
825 cdt->DTH.dth_MaskLen = fdh->fdth_MaskLen;
826 cdt->DTH.dth_Pad = fdh->fdth_Pad;
827 cdt->DTH.dth_Flags = fdh->fdth_Flags;
828 cdt->DTH.dth_Priority = fdh->fdth_Priority;
830 CopyMem(prop->sp_Data + 32, cdt + 1, prop->sp_Size - 32);
832 for(i = 0; i < cdt->DTH.dth_MaskLen; i++)
834 cdt->DTH.dth_Mask[i] = AROS_BE2WORD(cdt->DTH.dth_Mask[i]);
835 D(bug("[AddDataTypes] mask[%d] = %04x (%c %c)\n", i,
836 cdt->DTH.dth_Mask[i],
837 cdt->DTH.dth_Mask[i] & 255,
838 (cdt->DTH.dth_Mask[i] >> 8) & 255);)
842 bug("[AddDataTypes] 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 bug("[AddDataTypes] 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 bug("[AddDataTypes] flags = %x\n", cdt->DTH.dth_Flags);
851 bug("[AddDataTypes] pri = %d\n", cdt->DTH.dth_Priority);
852 bug("[AddDataTypes] name = %s\n", cdt->DTH.dth_Name);
853 bug("[AddDataTypes] basename = %s\n", cdt->DTH.dth_BaseName);
854 bug("[AddDataTypes] pattern = %s\n", cdt->DTH.dth_Pattern);
855 bug("[AddDataTypes] masklen = %d\n", cdt->DTH.dth_MaskLen);
858 NewList(&cdt->DT.dtn_ToolList);
860 cdt->DT.dtn_Length = AllocLen;
862 #if __mc68000
863 if((prop = FindProp(iff, ID_DTYP, ID_DTCD)))
865 if((func = AllocVec(prop->sp_Size, MEMF_PUBLIC | MEMF_CLEAR)))
867 cdt->DTCDChunk = func;
868 cdt->DTCDSize = prop->sp_Size;
870 CopyMem(prop->sp_Data,func,prop->sp_Size);
872 HookBuffer = cdt->DTCDChunk;
873 HookBufSize = cdt->DTCDSize;
874 HookPosition = 0;
876 /* We use a cast to BPTR, since sv may not
877 * be ULONG aligned. Since only our ReadFunc
878 * is going to be looking at it, this is ok.
880 if((SegList = InternalLoadSeg((BPTR)(sv), BNULL,
881 (LONG_FUNC *)FunctionArray,
882 &DefaultStack)))
884 cdt->SegList = SegList;
885 cdt->Function = BADDR(SegList) + sizeof(BPTR);
888 } /* if((func = AllocVec(prop->sp_Size, MEMF_PUBLIC | MEMF_CLEAR))) */
890 } /* if((prop = FindProp(iff, ID_DTYP, ID_DTCD))) */
891 #else
892 TEXT CDname[256];
894 __sprintf(CDname,"%s.%s", name, TARGETCPU);
895 D(bug("[AddDataTypes] Checking for '%s'\n", CDname);)
897 if((SegList = LoadSeg(CDname)))
899 D(bug("[AddDataTypes] Found!\n");)
900 cdt->SegList = SegList;
901 cdt->Function = BADDR(SegList) + sizeof(BPTR);
902 D(bug("[AddDataTypes] Entry @ 0x%p\n", cdt->Function);)
904 #endif
905 cdt = AddDataType(sv, cdt);
907 FreeStruct(fdh, FileDataTypeHeaderDesc);
909 } /* if (ReadStruct(&hook, &fdh, &memptr, FileDataTypeHeaderDesc)) */
911 } /* cdt AllocVec okay */
913 } /* if((prop = FindProp(iff, ID_DTYP, ID_DTHD))) */
915 return cdt;
920 /****** AddDataTypes/AddDataType **********************************************
922 * NAME
923 * AddDataType - add a DataType to the system
925 * SYNOPSIS
927 * FUNCTION
929 * This subroutine tries to add a DataType to the system DataTypes
930 * list. If the DataType already exists, it will be replaced or
931 * updated. In case of an error, the CompoundDataType will be deleted
932 * and a NULL pointer is returned.
934 * The CompoundDataType pointer you passed in will be invalid after
935 * calling this function. Use the returned handle instead.
936 * DO NOT USE THE OLD POINTER IN ANY MORE!
938 * INPUTS
940 * RETURNS
942 * A pointer to a CompoundDataType in the system DataTypes list
943 * or a NULL pointer for failure
945 * EXAMPLE
947 * SEE ALSO
949 ******************************************************************************
953 struct CompoundDataType *AddDataType(struct StackVars *sv,
954 struct CompoundDataType *cdt)
956 struct List *typelist;
957 BOOL Success = FALSE;
958 ULONG AllocSize;
959 ULONG result;
960 struct CompoundDataType *oldcdt;
962 switch(cdt->DTH.dth_Flags & DTF_TYPE_MASK)
964 case DTF_BINARY: typelist= &DTList->dtl_BinaryList; break;
965 case DTF_ASCII: typelist= &DTList->dtl_ASCIIList; break;
966 case DTF_IFF: typelist= &DTList->dtl_IFFList; break;
967 case DTF_MISC: typelist= &DTList->dtl_MiscList; break;
968 default: typelist= NULL;
971 if(typelist)
973 cdt->DT.dtn_Node1.ln_Name = cdt->DT.dtn_Node2.ln_Name = cdt->DTH.dth_Name;
975 Success = TRUE;
977 if((!Stricmp(cdt->DTH.dth_Pattern, "#?")) ||
978 (!strlen(cdt->DTH.dth_Pattern)) )
980 cdt->FlagLong |= CFLGF_PATTERN_UNUSED;
982 else
984 cdt->FlagLong &= ~(CFLGF_PATTERN_UNUSED);
986 AllocSize = 2*strlen(cdt->DTH.dth_Pattern) + 2;
988 if(!(cdt->ParsePatMem = AllocVec(AllocSize,
989 MEMF_PUBLIC | MEMF_CLEAR)))
991 Success = FALSE;
993 else
995 cdt->ParsePatSize = AllocSize;
997 result = ParsePatternNoCase(cdt->DTH.dth_Pattern,
998 cdt->ParsePatMem, AllocSize);
1000 if(result == 1)
1002 cdt->FlagLong |= CFLGF_IS_WILD;
1004 else
1006 FreeVec(cdt->ParsePatMem);
1007 cdt->ParsePatMem = NULL;
1008 cdt->ParsePatSize = 0;
1010 if(result == 0)
1012 cdt->FlagLong &= ~(CFLGF_IS_WILD);
1014 else
1016 Success = FALSE;
1022 if (Success)
1024 if((oldcdt = (struct CompoundDataType*)__FindNameNoCase(sv,
1025 typelist,
1026 cdt->DT.dtn_Node1.ln_Name)))
1028 if (oldcdt->OpenCount)
1030 Success = FALSE;
1032 else
1034 if((Stricmp(oldcdt->DTH.dth_Name, cdt->DTH.dth_Name)) ||
1035 (Stricmp(oldcdt->DTH.dth_BaseName, cdt->DTH.dth_BaseName)) ||
1036 (Stricmp(oldcdt->DTH.dth_Pattern, cdt->DTH.dth_Pattern)) ||
1037 (oldcdt->DTH.dth_Flags != cdt->DTH.dth_Flags) ||
1038 (oldcdt->DTH.dth_Priority != cdt->DTH.dth_Priority) ||
1039 (oldcdt->DTH.dth_MaskLen != cdt->DTH.dth_MaskLen))
1041 DeleteDataType(sv, oldcdt);
1042 oldcdt = NULL;
1044 else
1046 oldcdt->DTH.dth_GroupID = cdt->DTH.dth_GroupID;
1047 oldcdt->DTH.dth_ID = cdt->DTH.dth_ID;
1048 CopyMem(cdt->DTH.dth_Mask,cdt->DTH.dth_Mask,
1049 (ULONG)(sizeof(WORD)*cdt->DTH.dth_MaskLen));
1054 if(Success)
1056 if(oldcdt)
1058 DeleteDataType(sv, cdt);
1059 cdt = oldcdt;
1061 else
1063 if(cdt->DT.dtn_FunctionName)
1065 LONG DefaultStack = 4096;
1066 BPTR file;
1067 ULONG AllocLen;
1068 BPTR SegList;
1070 if((file = Open(cdt->DT.dtn_FunctionName, MODE_OLDFILE)))
1072 if(Seek(file, 0, OFFSET_END) >= 0)
1074 if((AllocLen = Seek(file, 0,
1075 OFFSET_BEGINNING)) > 0)
1077 if((cdt->DTCDChunk = AllocVec(AllocLen,
1078 MEMF_PUBLIC | MEMF_CLEAR)))
1080 cdt->DTCDSize = AllocLen;
1082 if(Read(file, cdt->DTCDChunk, AllocLen) == AllocLen)
1084 HookBuffer = cdt->DTCDChunk;
1085 HookBufSize = cdt->DTCDSize;
1086 HookPosition = 0;
1088 /* We use a cast to BPTR, since sv may not
1089 * be ULONG aligned. Since only our ReadFunc
1090 * is going to be looking at it, this is ok.
1092 if((SegList = InternalLoadSeg((BPTR)(sv), BNULL, (LONG_FUNC *)FunctionArray, &DefaultStack)))
1094 cdt->SegList = SegList;
1095 cdt->Function = BADDR(SegList) + sizeof(BPTR); // FIXME: is this portable?
1098 else
1100 FreeVec(cdt->DTCDChunk);
1101 cdt->DTCDChunk = NULL;
1102 cdt->DTCDSize = 0;
1108 cdt->DT.dtn_FunctionName=NULL;
1111 if(cdt->DTH.dth_MaskLen > DTList->dtl_LongestMask)
1113 DTList->dtl_LongestMask = cdt->DTH.dth_MaskLen;
1116 cdt->DT.dtn_Node1.ln_Pri = cdt->DTH.dth_Priority;
1117 Enqueue(typelist, &cdt->DT.dtn_Node1);
1119 AlphaInsert(sv, &DTList->dtl_SortedList, &cdt->DT.dtn_Node2);
1125 if(!Success)
1127 DeleteDataType(sv, cdt);
1128 cdt = NULL;
1131 return cdt;
1136 /****** AddDataTypes/DeleteDataType *******************************************
1138 * NAME
1139 * DeleteDataType - unlink and deallocate a CompoundDataType structure
1141 * SYNOPSIS
1143 * FUNCTION
1145 * INPUTS
1147 * RETURNS
1149 * EXAMPLE
1151 * SEE ALSO
1153 ******************************************************************************
1157 void DeleteDataType(struct StackVars *sv, struct CompoundDataType *cdt)
1159 if(cdt)
1161 if(cdt->ParsePatMem)
1163 FreeVec(cdt->ParsePatMem);
1164 cdt->ParsePatMem = NULL;
1165 cdt->ParsePatSize = 0;
1168 if(cdt->DTCDChunk)
1170 FreeVec(cdt->DTCDChunk);
1171 cdt->DTCDChunk = NULL;
1172 cdt->DTCDSize = 0;
1175 if(cdt->SegList)
1177 UnLoadSeg(cdt->SegList);
1178 cdt->SegList = BNULL;
1179 cdt->Function = NULL;
1182 if(cdt->DT.dtn_Node1.ln_Succ && cdt->DT.dtn_Node1.ln_Pred)
1184 Remove(&cdt->DT.dtn_Node1);
1185 Remove(&cdt->DT.dtn_Node2);
1186 cdt->DT.dtn_Node1.ln_Succ = cdt->DT.dtn_Node1.ln_Pred =
1187 cdt->DT.dtn_Node2.ln_Succ = cdt->DT.dtn_Node2.ln_Pred = NULL;
1190 FreeVec(cdt);
1196 /****** AddDataTypes/AlphaInsert **********************************************
1198 * NAME
1199 * AlphaInsert - enqueue a node alphabetically into a list
1201 * SYNOPSIS
1203 * FUNCTION
1205 * INPUTS
1207 * RETURNS
1209 * EXAMPLE
1211 * SEE ALSO
1213 ******************************************************************************
1217 void AlphaInsert(struct StackVars *sv, struct List *list, struct Node *node)
1219 struct Node *cur,*prev=NULL;
1221 for(cur = list->lh_Head; cur->ln_Succ; prev = cur, cur = cur->ln_Succ)
1223 if(Stricmp(cur->ln_Name, node->ln_Name) > 0)
1224 break;
1227 Insert(list, node, prev);
1232 /****** AddDataTypes/__FindNameNoCase *****************************************
1234 * NAME
1235 * __FindNameNoCase - find a node in a list (case insensitive)
1237 * SYNOPSIS
1239 * FUNCTION
1241 * INPUTS
1243 * RETURNS
1245 * EXAMPLE
1247 * SEE ALSO
1249 ******************************************************************************
1253 struct Node *__FindNameNoCase(struct StackVars *sv, struct List *list,
1254 STRPTR name)
1256 struct Node *node;
1257 struct Node *result = NULL;
1259 for(node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
1261 if(!Stricmp(node->ln_Name, name))
1263 result = node;
1264 break;
1268 return result;
1273 /****** AddDataTypes/ReadFunc *************************************************
1275 * NAME
1276 * ReadFunc - data read hook for InternalLoadSeg
1278 * SYNOPSIS
1280 * FUNCTION
1282 * INPUTS
1284 * RETURNS
1286 * EXAMPLE
1288 * SEE ALSO
1290 ******************************************************************************
1294 AROS_UFH4(LONG, AROS_SLIB_ENTRY(ReadFunc, AddDataTypes, 0),
1295 AROS_UFHA(BPTR , fh , D1),
1296 AROS_UFHA(void * , buffer , D2),
1297 AROS_UFHA(LONG , length , D3),
1298 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1300 AROS_USERFUNC_INIT
1302 struct StackVars *sv = (APTR)fh;
1303 LONG maxlen = HookBufSize-HookPosition;
1304 LONG actual = length > maxlen ? maxlen : length;
1306 CopyMem(HookBuffer+HookPosition, buffer, actual);
1308 HookPosition += actual;
1310 return actual;
1312 AROS_USERFUNC_EXIT
1315 /****** AddDataTypes/SeekFunc *************************************************
1317 * NAME
1318 * SeekFunc - seek hook for InternalLoadSeg (ELF only)
1320 * SYNOPSIS
1322 * FUNCTION
1324 * INPUTS
1326 * RETURNS
1328 * EXAMPLE
1330 * SEE ALSO
1332 ******************************************************************************
1336 AROS_UFH4(LONG, AROS_SLIB_ENTRY(SeekFunc, AddDataTypes, 0),
1337 AROS_UFHA(BPTR , fh , D1),
1338 AROS_UFHA(LONG , pos , D2),
1339 AROS_UFHA(LONG , mode , D3),
1340 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1342 AROS_USERFUNC_INIT
1344 struct StackVars *sv = (APTR)fh;
1345 LONG oldpos = HookPosition;
1347 switch (mode) {
1348 case OFFSET_BEGINNING: break;
1349 case OFFSET_END: pos = HookBufSize - pos; break;
1350 case OFFSET_CURRENT: pos = HookPosition + pos; break;
1351 default: return -1;
1354 if (pos < 0 || pos >= HookBufSize)
1355 return -1;
1357 HookPosition = pos;
1359 return oldpos;
1361 AROS_USERFUNC_EXIT
1364 /****** AddDataTypes/AllocFunc ************************************************
1366 * NAME
1367 * AllocFunc - memory allocation hook for InternalLoadSeg
1369 * SYNOPSIS
1371 * FUNCTION
1373 * INPUTS
1375 * RETURNS
1377 * EXAMPLE
1379 * SEE ALSO
1381 ******************************************************************************
1385 AROS_UFH3(UBYTE *, AROS_SLIB_ENTRY(AllocFunc, AddDataTypes, 0),
1386 AROS_UFHA(ULONG, size, D0),
1387 AROS_UFHA(ULONG, flags,D1),
1388 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1390 AROS_USERFUNC_INIT
1392 return(AllocMem(size, flags));
1394 AROS_USERFUNC_EXIT
1399 /****** AddDataTypes/FreeFunc *************************************************
1401 * NAME
1402 * FreeFunc - memory freeing hook for InternalLoadSeg
1404 * SYNOPSIS
1406 * FUNCTION
1408 * INPUTS
1410 * RETURNS
1412 * EXAMPLE
1414 * SEE ALSO
1416 ******************************************************************************
1420 AROS_UFH3(void, AROS_SLIB_ENTRY(FreeFunc, AddDataTypes, 0),
1421 AROS_UFHA(APTR , memory, A1),
1422 AROS_UFHA(ULONG, size , D0),
1423 AROS_UFHA(struct DosLibrary *, DOSBase, A6))
1425 AROS_USERFUNC_INIT
1427 FreeMem(memory, size);
1429 AROS_USERFUNC_EXIT
1434 /******************************* STUB ROUTINES ********************************/
1436 struct NamedObject *allocnamedobject(struct StackVars *sv, STRPTR name,
1437 Tag FirstTag, ...)
1439 return AllocNamedObjectA(name, (struct TagItem*)&FirstTag);