Small cleanup of extensions code
[AROS.git] / workbench / c / AddDatatypes.c
bloba0c501b6310bcc0991d66cabb3d3043937078d29
1 /*
2 Copyright © 1995-2007, 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
22 Sys:C
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>
79 #include <stdio.h>
81 #include "../libs/datatypes/datatypes_intern.h"
82 #undef DOSBase
83 #undef UtilityBase
84 #undef IFFParseBase
85 #undef LocaleBase
86 #undef DTList
88 /******************************** STRUCTURES *********************************/
90 /* same as datatypes/datatypes.h/struct DataTypeHeader, but always big endian
91 and 32 bit pointers (which in the file are actually offsets) */
93 struct FileDataTypeHeader
95 ULONG fdth_NameOffset; /* Name of the data type */
96 ULONG fdth_BaseNameOffset; /* Base name of the data type */
97 ULONG fdth_PatternOffset; /* File name match pattern */
98 ULONG fdth_MaskOffset; /* Comparision mask (binary) */
99 ULONG fdth_GroupID; /* DataType Group */
100 ULONG fdth_ID; /* DataType ID (same as IFF FORM type) */
101 WORD fdth_MaskLen; /* Length of the comparision mask */
102 WORD fdth_Pad; /* Unused at present (must be 0) */
103 UWORD fdth_Flags; /* Flags -- see below */
104 UWORD fdth_Priority;
107 #define O(x) offsetof(struct FileDataTypeHeader,x)
109 static const IPTR FileDataTypeHeaderDesc[] =
111 sizeof(struct FileDataTypeHeader),
112 SDM_ULONG(O(fdth_NameOffset)),
113 SDM_ULONG(O(fdth_BaseNameOffset)),
114 SDM_ULONG(O(fdth_PatternOffset)),
115 SDM_ULONG(O(fdth_MaskOffset)),
116 SDM_ULONG(O(fdth_GroupID)),
117 SDM_ULONG(O(fdth_ID)),
118 SDM_WORD(O(fdth_MaskLen)),
119 SDM_WORD(O(fdth_Pad)),
120 SDM_UWORD(O(fdth_Flags)),
121 SDM_UWORD(O(fdth_Priority)),
122 SDM_END
125 /******************************** PROTOTYPES *********************************/
127 struct StackVars; /* forward declaration */
129 BOOL DateScan(struct StackVars *sv);
130 void ScanDirectory(struct StackVars *sv, STRPTR pattern);
131 struct DataTypesList *CreateDTList(struct StackVars *sv);
132 struct CompoundDatatype *CreateBasicType(struct StackVars *sv,
133 struct List *list,
134 struct List *globallist, STRPTR name,
135 UWORD Flags, ULONG ID, ULONG GroupID);
136 void LoadDatatype(struct StackVars *sv, STRPTR name);
137 struct CompoundDatatype *CreateDatatype(struct StackVars *sv,
138 struct IFFHandle *iff);
139 struct CompoundDatatype *AddDatatype(struct StackVars *sv,
140 struct CompoundDatatype *cdt);
141 void DeleteDatatype(struct StackVars *sv, struct CompoundDatatype *cdt);
142 void AlphaInsert(struct StackVars *sv, struct List *list, struct Node *node);
143 void PrioInsert(struct StackVars *sv, struct List *list,
144 struct CompoundDatatype *cdt);
145 struct Node *__FindNameNoCase(struct StackVars *sv, struct List *list,
146 STRPTR name);
147 LONG ReadFunc(struct StackVars *sv, UBYTE *buffer, ULONG length);
148 UBYTE *AllocFunc(ULONG size, ULONG flags);
149 void FreeFunc(UBYTE *memory, ULONG size);
152 /********************************* CONSTANTS *********************************/
154 const TEXT Version[] = "$VER: AddDatatypes 42.1 (8.12.2007)\n";
156 #define EXCL_LEN 18
157 UBYTE ExcludePattern[] = "#?.(info|backdrop)";
159 UBYTE Template[] = "FILES/M,QUIET/S,REFRESH/S,LIST/S";
161 struct ArgArray
163 UBYTE **aa_Files;
164 IPTR aa_Quiet;
165 IPTR aa_Refresh;
166 IPTR aa_List;
169 #define ID_DTCD MAKE_ID('D','T','C','D')
170 #define ID_DTTL MAKE_ID('D','T','T','L')
172 #define NUM_PROP 2
174 LONG PropArray[2*NUM_PROP]=
176 ID_DTYP, ID_DTHD,
177 ID_DTYP, ID_DTCD
180 #define NUM_COLL 1
182 LONG CollArray[2*NUM_COLL]=
184 ID_DTYP, ID_DTTL
188 LONG_FUNC FunctionArray[]=
189 { /* Note! */
190 (LONG_FUNC)&ReadFunc,
191 (LONG_FUNC)&AllocFunc,
192 (LONG_FUNC)&FreeFunc
196 struct StackVars
198 struct DataTypesList *DTList;
199 UBYTE ExclPat[2*EXCL_LEN+2+1];
200 struct ArgArray AA;
201 UBYTE *HookBuffer;
202 ULONG HookBufSize;
203 ULONG HookPosition;
206 #undef SysBase
207 #define DTList sv->DTList
208 #define ExclPat sv->ExclPat
209 #define AA sv->AA
210 #define HookBuffer sv->HookBuffer
211 #define HookBufSize sv->HookBufSize
212 #define HookPosition sv->HookPosition
214 /****** AddDatatypes/main *****************************************************
216 * NAME
217 * main - well... main
219 * SYNOPSIS
221 * FUNCTION
223 * INPUTS
225 * RETURNS
227 * EXAMPLE
229 * SEE ALSO
231 ******************************************************************************
234 int UtilityBase_version = 37;
235 int LocaleBase_version = 37;
236 int IFFParseBase_version = 37;
238 int __nocommandline = 1;
240 int main(void)
242 extern struct WBStartup *WBenchMsg;
243 struct StackVars vars;
244 struct StackVars *sv;
245 int result = RETURN_FAIL;
247 memset(&vars, 0, sizeof(struct StackVars));
248 sv = &vars;
250 if((DTList = CreateDTList(sv)))
252 ParsePatternNoCase(ExcludePattern, ExclPat, sizeof(ExclPat));
254 ObtainSemaphore(&DTList->dtl_Lock);
256 if(WBenchMsg)
258 UWORD num;
259 struct WBArg *wa = &WBenchMsg->sm_ArgList[1];
261 for(num = 1; num<WBenchMsg->sm_NumArgs; wa++)
263 BPTR olddir = CurrentDir(wa->wa_Lock);
264 LoadDatatype(sv, wa->wa_Name);
265 CurrentDir(olddir);
268 result = RETURN_OK;
270 else
272 struct RDArgs *RDArgs;
274 if(!(RDArgs = ReadArgs(Template, (SIPTR*)&AA, NULL)))
276 PrintFault(IoErr(), NULL);
278 else
280 if(AA.aa_Refresh)
282 if(DateScan(sv))
284 ScanDirectory(sv, "DEVS:DataTypes");
287 else
289 UBYTE **files = AA.aa_Files;
291 if(files)
293 while(*files)
295 ScanDirectory(sv, *files);
296 files++;
301 if(AA.aa_List)
303 struct DataTypesList *dtl = NULL;
304 struct NamedObject *no = NULL;
305 if((no = FindNamedObject(NULL, DATATYPESLIST, NULL)))
307 dtl = (struct DataTypesList*)no->no_Object;
308 ReleaseNamedObject(no);
309 if(dtl != NULL)
311 struct Node *node=dtl->dtl_SortedList.lh_Head;
312 while(node->ln_Succ != NULL)
314 // sorted list points to DT.dtn_Node2 ....
315 struct CompoundDatatype *cdt;
316 struct DataTypeHeader *dth;
317 STRPTR argarray[2];
319 if(CheckSignal(SIGBREAKF_CTRL_C))
321 Flush(Output());
322 PrintFault(ERROR_BREAK,0);
323 break;
325 cdt=(struct CompoundDatatype *)(node-1);
326 dth=cdt->DT.dtn_Header;
328 argarray[0] = dth->dth_BaseName;
329 argarray[1] = dth->dth_Name;
331 VPrintf("%s, \"%s\"\n", (IPTR *)argarray);
332 node = node->ln_Succ;
339 result = RETURN_OK;
340 FreeArgs(RDArgs);
344 ReleaseSemaphore(&DTList->dtl_Lock);
347 return result;
352 /****** AddDatatypes/DateScan *************************************************
354 * NAME
355 * DateScan - See if datatypes descriptors need updating
357 * SYNOPSIS
359 * FUNCTION
361 * INPUTS
363 * RETURNS
365 * EXAMPLE
367 * SEE ALSO
369 ******************************************************************************
373 BOOL DateScan(struct StackVars *sv)
375 BOOL result = TRUE;
376 BPTR lock;
377 struct FileInfoBlock *fib;
379 if((lock = Lock("DEVS:Datatypes", ACCESS_READ)))
381 if((fib = AllocDosObject(DOS_FIB, NULL)))
383 if(Examine(lock, fib))
385 if(!CompareDates(&fib->fib_Date, &DTList->dtl_DateStamp))
387 result = FALSE;
389 else
391 DTList->dtl_DateStamp = fib->fib_Date;
395 FreeDosObject(DOS_FIB,fib);
398 UnLock(lock);
401 return result;
406 /****** AddDatatypes/ScanDirectory ********************************************
408 * NAME
409 * ScanDirectory - Scan a directory recursively for DT descriptors
411 * SYNOPSIS
413 * FUNCTION
415 * INPUTS
417 * RETURNS
419 * EXAMPLE
421 * SEE ALSO
423 ******************************************************************************
427 void ScanDirectory(struct StackVars *sv, STRPTR pattern)
429 struct AnchorPath *AnchorPath;
430 LONG RetVal;
431 BPTR OldDir;
433 if((AnchorPath = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath),
434 MEMF_CLEAR)))
436 AnchorPath->ap_BreakBits = SIGBREAKF_CTRL_C;
438 RetVal = MatchFirst(pattern, AnchorPath);
440 while(!RetVal)
442 if(CheckSignal(SIGBREAKF_CTRL_C))
444 if(!AA.aa_Quiet)
446 PrintFault(ERROR_BREAK, NULL);
449 break;
452 if(AnchorPath->ap_Info.fib_DirEntryType > 0L)
454 if(!(AnchorPath->ap_Flags & APF_DIDDIR))
456 AnchorPath->ap_Flags |= APF_DODIR;
459 AnchorPath->ap_Flags &= ~APF_DIDDIR;
461 else
463 if(!MatchPatternNoCase(ExclPat,
464 AnchorPath->ap_Info.fib_FileName))
466 OldDir = CurrentDir(AnchorPath->ap_Current->an_Lock);
468 LoadDatatype(sv, AnchorPath->ap_Info.fib_FileName);
470 CurrentDir(OldDir);
474 RetVal = MatchNext(AnchorPath);
477 if(RetVal != ERROR_NO_MORE_ENTRIES)
479 if(!AA.aa_Quiet)
481 PrintFault(RetVal, NULL);
485 MatchEnd(AnchorPath);
487 FreeVec((APTR)AnchorPath);
492 /****** AddDatatypes/CreateDTList *********************************************
494 * NAME
495 * CreateDTList - Create and initialize the DataTypesList
497 * SYNOPSIS
499 * FUNCTION
501 * INPUTS
503 * RETURNS
505 * EXAMPLE
507 * SEE ALSO
509 ******************************************************************************
513 struct DataTypesList *CreateDTList(struct StackVars *sv)
515 struct DataTypesList *dtl = NULL;
516 struct NamedObject *no = NULL;
517 struct Library *DTBase;
519 /* We do this in order to force datatypes.library to get
520 loaded and initialized. During this process it will
521 create and install datatypes list object in memory. */
522 DTBase = OpenLibrary("datatypes.library", 0);
523 if (DTBase)
524 CloseLibrary(DTBase);
526 if((no = FindNamedObject(NULL, DATATYPESLIST, NULL)))
528 dtl = (struct DataTypesList*)no->no_Object;
531 if(dtl)
533 if(!__FindNameNoCase(sv, &dtl->dtl_BinaryList, "binary"))
535 CreateBasicType
537 sv, &dtl->dtl_BinaryList, &dtl->dtl_SortedList,
538 "binary", DTF_BINARY, ID_BINARY, GID_SYSTEM
542 if(!__FindNameNoCase(sv, &dtl->dtl_ASCIIList, "ascii"))
544 CreateBasicType
546 sv, &dtl->dtl_ASCIIList, &dtl->dtl_SortedList,
547 "ascii", DTF_ASCII, ID_ASCII, GID_TEXT
551 if(!__FindNameNoCase(sv, &dtl->dtl_IFFList, "iff"))
553 CreateBasicType
555 sv, &dtl->dtl_IFFList, &dtl->dtl_SortedList,
556 "iff", DTF_IFF, ID_IFF, GID_SYSTEM
560 if(!__FindNameNoCase(sv, &dtl->dtl_MiscList, "directory"))
562 CreateBasicType
564 sv, &dtl->dtl_MiscList, &dtl->dtl_SortedList,
565 "directory", DTF_MISC, ID_DIRECTORY, GID_SYSTEM
570 if(no)
572 ReleaseNamedObject(no);
576 return dtl;
581 /****** AddDatatypes/CreateBasicType ******************************************
583 * NAME
584 * CreateBasicType - Initialize one of the basic types
586 * SYNOPSIS
588 * FUNCTION
590 * INPUTS
592 * RETURNS
594 * EXAMPLE
596 * SEE ALSO
598 ******************************************************************************
602 struct CompoundDatatype *CreateBasicType(struct StackVars *sv,
603 struct List *list,
604 struct List *globallist, STRPTR name,
605 UWORD Flags, ULONG ID, ULONG GroupID)
607 struct CompoundDatatype *cdt;
608 ULONG AllocLen = sizeof(struct CompoundDatatype) + strlen(name) + 1;
610 if((cdt = AllocVec(AllocLen, MEMF_PUBLIC | MEMF_CLEAR)))
612 cdt->DT.dtn_Header = &cdt->DTH;
614 strcpy((UBYTE*)(cdt + 1), name);
616 cdt->DTH.dth_Name=
617 cdt->DTH.dth_BaseName=
618 cdt->DT.dtn_Node1.ln_Name=
619 cdt->DT.dtn_Node2.ln_Name=(UBYTE*)(cdt + 1);
621 cdt->DTH.dth_GroupID = GroupID;
622 cdt->DTH.dth_ID = ID;
624 cdt->DTH.dth_Flags = Flags;
626 NewList(&cdt->DT.dtn_ToolList);
628 cdt->DT.dtn_Length = AllocLen;
630 AddTail(list, &cdt->DT.dtn_Node1);
632 AlphaInsert(sv, globallist, &cdt->DT.dtn_Node2);
635 return cdt;
640 /****** AddDatatypes/LoadDatatype *********************************************
642 * NAME
643 * LoadDatatype - Load and install a single datatype descriptor
645 * SYNOPSIS
647 * FUNCTION
649 * INPUTS
651 * RETURNS
653 * EXAMPLE
655 * SEE ALSO
657 ******************************************************************************
661 void LoadDatatype(struct StackVars *sv, STRPTR name)
663 struct IFFHandle *iff;
665 if((iff = AllocIFF()))
667 if((iff->iff_Stream = (IPTR)Open(name, MODE_OLDFILE))) /* Why IPTR? */
669 InitIFFasDOS(iff);
671 if(!OpenIFF(iff, IFFF_READ))
673 if(!PropChunks(iff, PropArray, NUM_PROP))
675 if(!CollectionChunks(iff, CollArray, NUM_COLL))
677 if(!StopOnExit(iff, ID_DTYP, ID_FORM))
679 LONG error;
681 while((error = ParseIFF(iff, IFFPARSE_SCAN)) == IFFERR_EOC)
683 CreateDatatype(sv, iff);
684 #warning The while ParseIFF loop here crashes the 2nd time inside the loop, therefore the break below as temp fix
685 break;
691 CloseIFF(iff);
694 Close((BPTR)iff->iff_Stream);
697 FreeIFF(iff);
699 else
701 SetIoErr(ERROR_NO_FREE_STORE);
706 /****** AddDatatypes/MemStreamHook *******************************************
708 * NAME
709 * MemStreamHook - needed by ReadStruct
711 * SYNOPSIS
713 * FUNCTION
715 * INPUTS
717 * RETURNS
719 * EXAMPLE
721 * SEE ALSO
723 ******************************************************************************
727 LONG MemStreamHook(struct Hook * hook, UBYTE **memptr, Msg msg)
729 LONG rc;
731 switch (msg->MethodID)
733 case BEIO_READ:
734 rc = **memptr;
735 (*memptr)++;
736 break;
738 default:
739 rc = EOF;
740 break;
743 return rc;
746 /****** AddDatatypes/CreateDatatype *******************************************
748 * NAME
749 * CreateDatatype - create a datatype from IFF chunks
751 * SYNOPSIS
753 * FUNCTION
755 * INPUTS
757 * RETURNS
759 * EXAMPLE
761 * SEE ALSO
763 ******************************************************************************
767 struct CompoundDatatype *CreateDatatype(struct StackVars *sv,
768 struct IFFHandle *iff)
770 struct CompoundDatatype *cdt = NULL;
771 struct StoredProperty *prop;
772 ULONG AllocLen;
773 UBYTE *func;
774 LONG DefaultStack = AROS_STACKSIZE, i;
775 BPTR SegList;
777 if((prop = FindProp(iff, ID_DTYP, ID_DTHD)))
779 AllocLen = sizeof(struct CompoundDatatype) -
780 32 + /* was sizeof(struct DataTypeHeader), but we must use struct size as it would be on Amiga */
781 prop->sp_Size;
783 if(!(cdt = AllocVec(AllocLen, MEMF_PUBLIC | MEMF_CLEAR)))
785 SetIoErr(ERROR_NO_FREE_STORE);
787 else
789 struct FileDataTypeHeader *fdh;
790 UBYTE *memptr = (UBYTE *)prop->sp_Data;
791 struct Hook hook;
793 hook.h_Entry = (HOOKFUNC)HookEntry;
794 hook.h_SubEntry = (HOOKFUNC)MemStreamHook;
796 if (ReadStruct(&hook, (APTR *) &fdh, &memptr, FileDataTypeHeaderDesc))
798 IPTR extraoffset = sizeof(struct DataTypeHeader) - 32;
800 cdt->DT.dtn_Header= &cdt->DTH;
802 cdt->DTH.dth_Name = (STRPTR)(fdh->fdth_NameOffset + extraoffset + (IPTR)&cdt->DTH);
803 cdt->DTH.dth_BaseName = (STRPTR)(fdh->fdth_BaseNameOffset + extraoffset + (IPTR)&cdt->DTH);
804 cdt->DTH.dth_Pattern = (STRPTR)(fdh->fdth_PatternOffset + extraoffset + (IPTR)&cdt->DTH);
805 cdt->DTH.dth_Mask = (WORD *)(fdh->fdth_MaskOffset + extraoffset + (IPTR)&cdt->DTH);
806 cdt->DTH.dth_GroupID = fdh->fdth_GroupID;
807 cdt->DTH.dth_ID = fdh->fdth_ID;
808 cdt->DTH.dth_MaskLen = fdh->fdth_MaskLen;
809 cdt->DTH.dth_Pad = fdh->fdth_Pad;
810 cdt->DTH.dth_Flags = fdh->fdth_Flags;
811 cdt->DTH.dth_Priority = fdh->fdth_Priority;
813 CopyMem(prop->sp_Data + 32, cdt + 1, prop->sp_Size - 32);
815 for(i = 0; i < cdt->DTH.dth_MaskLen; i++)
817 cdt->DTH.dth_Mask[i] = AROS_BE2WORD(cdt->DTH.dth_Mask[i]);
818 #if 0
819 kprintf("mask[%d] = %04x (%c %c)\n", i,
820 cdt->DTH.dth_Mask[i],
821 cdt->DTH.dth_Mask[i] & 255,
822 (cdt->DTH.dth_Mask[i] >> 8) & 255);
823 #endif
826 #if 0
827 kprintf("groupid = %c%c%c%c\n", cdt->DTH.dth_GroupID >> 24,
828 cdt->DTH.dth_GroupID >> 16,
829 cdt->DTH.dth_GroupID >> 8,
830 cdt->DTH.dth_GroupID);
831 kprintf("id = %c%c%c%c\n", cdt->DTH.dth_ID >> 24,
832 cdt->DTH.dth_ID >> 16,
833 cdt->DTH.dth_ID >> 8,
834 cdt->DTH.dth_ID);
835 kprintf("flags = %x\n", cdt->DTH.dth_Flags);
836 kprintf("pri = %d\n", cdt->DTH.dth_Priority);
837 kprintf("name = %s\n", cdt->DTH.dth_Name);
838 kprintf("basename = %s\n", cdt->DTH.dth_BaseName);
839 kprintf("pattern = %s\n", cdt->DTH.dth_Pattern);
840 kprintf("masklen = %d\n", cdt->DTH.dth_MaskLen);
841 #endif
843 NewList(&cdt->DT.dtn_ToolList);
845 cdt->DT.dtn_Length = AllocLen;
847 if((prop = FindProp(iff, ID_DTYP, ID_DTCD)))
849 if((func = AllocVec(prop->sp_Size, MEMF_PUBLIC | MEMF_CLEAR)))
851 cdt->DTCDChunk = func;
852 cdt->DTCDSize = prop->sp_Size;
854 CopyMem(prop->sp_Data,func,prop->sp_Size);
856 HookBuffer = cdt->DTCDChunk;
857 HookBufSize = cdt->DTCDSize;
858 HookPosition = 0;
860 if((SegList = InternalLoadSeg((BPTR)sv, NULL,
861 (LONG_FUNC)FunctionArray,
862 &DefaultStack)))
864 cdt->SegList = SegList;
865 cdt->Function = (APTR)((((ULONG)SegList) << 2) + 4);
868 } /* if((func = AllocVec(prop->sp_Size, MEMF_PUBLIC | MEMF_CLEAR))) */
870 } /* if((prop = FindProp(iff, ID_DTYP, ID_DTCD))) */
872 cdt = AddDatatype(sv, cdt);
874 FreeStruct(fdh, FileDataTypeHeaderDesc);
876 } /* if (ReadStruct(&hook, &fdh, &memptr, FileDataTypeHeaderDesc)) */
878 } /* cdt AllocVec okay */
880 } /* if((prop = FindProp(iff, ID_DTYP, ID_DTHD))) */
882 return cdt;
887 /****** AddDatatypes/AddDatatype **********************************************
889 * NAME
890 * AddDatatype - add a datatype to the system
892 * SYNOPSIS
894 * FUNCTION
896 * This subroutine tries to add a datatype to the system datatypes
897 * list. If the datatype already exists, it will be replaced or
898 * updated. In case of an error, the CompoundDatatype will be deleted
899 * and a NULL pointer is returned.
901 * The CompoundDatatype pointer you passed in will be invalid after
902 * calling this function. Use the returned handle instead.
903 * DO NOT USE THE OLD POINTER IN ANY MORE!
905 * INPUTS
907 * RETURNS
909 * A pointer to a CompoundDatatype in the system datatypes list
910 * or a NULL pointer for failure
912 * EXAMPLE
914 * SEE ALSO
916 ******************************************************************************
920 struct CompoundDatatype *AddDatatype(struct StackVars *sv,
921 struct CompoundDatatype *cdt)
923 struct List *typelist;
924 BOOL Success = FALSE;
925 ULONG AllocSize;
926 ULONG result;
927 struct CompoundDatatype *oldcdt;
929 switch(cdt->DTH.dth_Flags & DTF_TYPE_MASK)
931 case DTF_BINARY: typelist= &DTList->dtl_BinaryList; break;
932 case DTF_ASCII: typelist= &DTList->dtl_ASCIIList; break;
933 case DTF_IFF: typelist= &DTList->dtl_IFFList; break;
934 case DTF_MISC: typelist= &DTList->dtl_MiscList; break;
935 default: typelist= NULL;
938 if(typelist)
940 cdt->DT.dtn_Node1.ln_Name = cdt->DT.dtn_Node2.ln_Name = cdt->DTH.dth_Name;
942 Success = TRUE;
944 if((!Stricmp(cdt->DTH.dth_Pattern, "#?")) ||
945 (!strlen(cdt->DTH.dth_Pattern)) )
947 cdt->FlagLong |= CFLGF_PATTERN_UNUSED;
949 else
951 cdt->FlagLong &= ~(CFLGF_PATTERN_UNUSED);
953 AllocSize = 2*strlen(cdt->DTH.dth_Pattern) + 2;
955 if(!(cdt->ParsePatMem = AllocVec(AllocSize,
956 MEMF_PUBLIC | MEMF_CLEAR)))
958 Success = FALSE;
960 else
962 cdt->ParsePatSize = AllocSize;
964 result = ParsePatternNoCase(cdt->DTH.dth_Pattern,
965 cdt->ParsePatMem, AllocSize);
967 if(result == 1)
969 cdt->FlagLong |= CFLGF_IS_WILD;
971 else
973 FreeVec(cdt->ParsePatMem);
974 cdt->ParsePatMem = NULL;
975 cdt->ParsePatSize = 0;
977 if(result == 0)
979 cdt->FlagLong &= ~(CFLGF_IS_WILD);
981 else
983 Success = FALSE;
989 if (Success)
991 if((oldcdt = (struct CompoundDatatype*)__FindNameNoCase(sv,
992 typelist,
993 cdt->DT.dtn_Node1.ln_Name)))
995 if (oldcdt->OpenCount)
997 Success = FALSE;
999 else
1001 if((Stricmp(oldcdt->DTH.dth_Name, cdt->DTH.dth_Name)) ||
1002 (Stricmp(oldcdt->DTH.dth_BaseName, cdt->DTH.dth_BaseName)) ||
1003 (Stricmp(oldcdt->DTH.dth_Pattern, cdt->DTH.dth_Pattern)) ||
1004 (oldcdt->DTH.dth_Flags != cdt->DTH.dth_Flags) ||
1005 (oldcdt->DTH.dth_Priority != cdt->DTH.dth_Priority) ||
1006 (oldcdt->DTH.dth_MaskLen != cdt->DTH.dth_MaskLen))
1008 DeleteDatatype(sv, oldcdt);
1009 oldcdt = NULL;
1011 else
1013 oldcdt->DTH.dth_GroupID = cdt->DTH.dth_GroupID;
1014 oldcdt->DTH.dth_ID = cdt->DTH.dth_ID;
1015 CopyMem(cdt->DTH.dth_Mask,cdt->DTH.dth_Mask,
1016 (ULONG)(sizeof(WORD)*cdt->DTH.dth_MaskLen));
1021 if(Success)
1023 if(oldcdt)
1025 DeleteDatatype(sv, cdt);
1026 cdt = oldcdt;
1028 else
1030 if(cdt->DT.dtn_FunctionName)
1032 LONG DefaultStack = 4096;
1033 BPTR file;
1034 ULONG AllocLen;
1035 BPTR SegList;
1037 if((file = Open(cdt->DT.dtn_FunctionName, MODE_OLDFILE)))
1039 if(Seek(file, 0, OFFSET_END) >= 0)
1041 if((AllocLen = Seek(file, 0,
1042 OFFSET_BEGINNING)) > 0)
1044 if((cdt->DTCDChunk = AllocVec(AllocLen,
1045 MEMF_PUBLIC | MEMF_CLEAR)))
1047 cdt->DTCDSize = AllocLen;
1049 if(Read(file, cdt->DTCDChunk, AllocLen) == AllocLen)
1051 HookBuffer = cdt->DTCDChunk;
1052 HookBufSize = cdt->DTCDSize;
1053 HookPosition = 0;
1055 if((SegList = InternalLoadSeg((BPTR)sv, NULL, (LONG_FUNC)FunctionArray, &DefaultStack)))
1057 cdt->SegList = SegList;
1058 cdt->Function = (APTR)((((ULONG)SegList)<<2)+4);
1061 else
1063 FreeVec(cdt->DTCDChunk);
1064 cdt->DTCDChunk = NULL;
1065 cdt->DTCDSize = 0;
1071 cdt->DT.dtn_FunctionName=NULL;
1074 if(cdt->DTH.dth_MaskLen > DTList->dtl_LongestMask)
1076 DTList->dtl_LongestMask = cdt->DTH.dth_MaskLen;
1079 PrioInsert(sv, typelist, cdt);
1081 AlphaInsert(sv, &DTList->dtl_SortedList, &cdt->DT.dtn_Node2);
1087 if(!Success)
1089 DeleteDatatype(sv, cdt);
1090 cdt = NULL;
1093 return cdt;
1098 /****** AddDatatypes/DeleteDatatype *******************************************
1100 * NAME
1101 * DeleteDatatype - unlink and deallocate a CompoundDatatype structure
1103 * SYNOPSIS
1105 * FUNCTION
1107 * INPUTS
1109 * RETURNS
1111 * EXAMPLE
1113 * SEE ALSO
1115 ******************************************************************************
1119 void DeleteDatatype(struct StackVars *sv, struct CompoundDatatype *cdt)
1121 if(cdt)
1123 if(cdt->ParsePatMem)
1125 FreeVec(cdt->ParsePatMem);
1126 cdt->ParsePatMem = NULL;
1127 cdt->ParsePatSize = 0;
1130 if(cdt->DTCDChunk)
1132 FreeVec(cdt->DTCDChunk);
1133 cdt->DTCDChunk = NULL;
1134 cdt->DTCDSize = 0;
1137 if(cdt->SegList)
1139 UnLoadSeg(cdt->SegList);
1140 cdt->SegList = NULL;
1141 cdt->Function = NULL;
1144 if(cdt->DT.dtn_Node1.ln_Succ && cdt->DT.dtn_Node1.ln_Pred)
1146 Remove(&cdt->DT.dtn_Node1);
1147 Remove(&cdt->DT.dtn_Node2);
1148 cdt->DT.dtn_Node1.ln_Succ = cdt->DT.dtn_Node1.ln_Pred =
1149 cdt->DT.dtn_Node2.ln_Succ = cdt->DT.dtn_Node2.ln_Pred = NULL;
1152 FreeVec(cdt);
1158 /****** AddDatatypes/AlphaInsert **********************************************
1160 * NAME
1161 * AlphaInsert - enqueue a node alphabetically into a list
1163 * SYNOPSIS
1165 * FUNCTION
1167 * INPUTS
1169 * RETURNS
1171 * EXAMPLE
1173 * SEE ALSO
1175 ******************************************************************************
1179 void AlphaInsert(struct StackVars *sv, struct List *list, struct Node *node)
1181 struct Node *cur,*prev=NULL;
1183 for(cur = list->lh_Head; cur->ln_Succ; prev = cur, cur = cur->ln_Succ)
1185 if(Stricmp(cur->ln_Name, node->ln_Name) > 0)
1186 break;
1189 Insert(list, node, prev);
1194 /****** AddDatatypes/PrioInsert **********************************************
1196 * NAME
1197 * PrioInsert - enqueue a CompoundDatatype correctly in the type list
1199 * SYNOPSIS
1201 * FUNCTION
1203 * INPUTS
1205 * RETURNS
1207 * EXAMPLE
1209 * SEE ALSO
1211 ******************************************************************************
1215 void PrioInsert(struct StackVars *sv, struct List *list,
1216 struct CompoundDatatype *cdt)
1218 struct CompoundDatatype *cur, *prev = NULL;
1219 WORD diff;
1221 for(cur = (struct CompoundDatatype*)list->lh_Head;
1222 cur->DT.dtn_Node1.ln_Succ;
1223 prev = cur, cur = (struct CompoundDatatype*)cur->DT.dtn_Node1.ln_Succ)
1225 diff = (cdt->Function ? 1 : 0) - (cur->Function ? 1 : 0);
1227 if(diff > 0)
1228 break;
1230 if(!diff)
1232 UWORD MinMask = (cdt->DTH.dth_MaskLen < cur->DTH.dth_MaskLen) ?
1233 cdt->DTH.dth_MaskLen : cur->DTH.dth_MaskLen;
1234 WORD *cdtmask = cdt->DTH.dth_Mask;
1235 WORD *curmask=cur->DTH.dth_Mask;
1237 while(!diff && MinMask--)
1238 diff= *(curmask++) - *(cdtmask++);
1240 if(diff > 0)
1241 break;
1243 if(!diff)
1245 diff = cdt->DTH.dth_MaskLen - cur->DTH.dth_MaskLen;
1247 if(diff > 0)
1248 break;
1250 if(!diff)
1252 diff = (((cdt->FlagLong & CFLGF_PATTERN_UNUSED) || cdt->DTH.dth_Pattern==NULL) ? 0 : 1) -
1253 (((cur->FlagLong & CFLGF_PATTERN_UNUSED) || cur->DTH.dth_Pattern==NULL) ? 0 : 1);
1255 if(diff > 0)
1256 break;
1258 if(!diff)
1260 diff = cdt->DTH.dth_Priority - cur->DTH.dth_Priority;
1262 if(diff > 0)
1263 break;
1270 Insert(list, &cdt->DT.dtn_Node1, (struct Node *)prev);
1275 /****** AddDatatypes/__FindNameNoCase *****************************************
1277 * NAME
1278 * __FindNameNoCase - find a node in a list (case insensitive)
1280 * SYNOPSIS
1282 * FUNCTION
1284 * INPUTS
1286 * RETURNS
1288 * EXAMPLE
1290 * SEE ALSO
1292 ******************************************************************************
1296 struct Node *__FindNameNoCase(struct StackVars *sv, struct List *list,
1297 STRPTR name)
1299 struct Node *node;
1300 struct Node *result = NULL;
1302 for(node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
1304 if(!Stricmp(node->ln_Name, name))
1306 result = node;
1307 break;
1311 return result;
1316 /****** AddDatatypes/ReadFunc *************************************************
1318 * NAME
1319 * ReadFunc - data read hook for InternalLoadSeg
1321 * SYNOPSIS
1323 * FUNCTION
1325 * INPUTS
1327 * RETURNS
1329 * EXAMPLE
1331 * SEE ALSO
1333 ******************************************************************************
1337 LONG ReadFunc(struct StackVars *sv, UBYTE *buffer, ULONG length)
1339 LONG maxlen = HookBufSize-HookPosition;
1340 LONG actual = length > maxlen ? maxlen : length;
1342 CopyMem(HookBuffer+HookPosition, buffer, actual);
1344 HookPosition += actual;
1346 return actual;
1351 /****** AddDatatypes/AllocFunc ************************************************
1353 * NAME
1354 * AllocFunc - memory allocation hook for InternalLoadSeg
1356 * SYNOPSIS
1358 * FUNCTION
1360 * INPUTS
1362 * RETURNS
1364 * EXAMPLE
1366 * SEE ALSO
1368 ******************************************************************************
1372 UBYTE *AllocFunc(ULONG size, ULONG flags)
1374 return(AllocMem(size, flags));
1379 /****** AddDatatypes/FreeFunc *************************************************
1381 * NAME
1382 * FreeFunc - memory freeing hook for InternalLoadSeg
1384 * SYNOPSIS
1386 * FUNCTION
1388 * INPUTS
1390 * RETURNS
1392 * EXAMPLE
1394 * SEE ALSO
1396 ******************************************************************************
1400 void FreeFunc(UBYTE *memory, ULONG size)
1402 FreeMem(memory, size);
1407 /******************************* STUB ROUTINES ********************************/
1409 struct NamedObject *allocnamedobject(struct StackVars *sv, STRPTR name,
1410 Tag FirstTag, ...)
1412 return AllocNamedObjectA(name, (struct TagItem*)&FirstTag);