1/*
2** Copyright (c) 2001-2007 Expat maintainers.
3**
4** Permission is hereby granted, free of charge, to any person obtaining
5** a copy of this software and associated documentation files (the
6** "Software"), to deal in the Software without restriction, including
7** without limitation the rights to use, copy, modify, merge, publish,
8** distribute, sublicense, and/or sell copies of the Software, and to
9** permit persons to whom the Software is furnished to do so, subject to
10** the following conditions:
11**
12** The above copyright notice and this permission notice shall be included
13** in all copies or substantial portions of the Software.
14**
15** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*/
23
24#include <dos/dos.h>
25#include <proto/exec.h>
26
27#define LIBNAME		"expat.library"
28#define LIBPRI		0
29#define VERSION		4
30#define REVISION	2
31#define VSTRING		"expat.library 4.2 (2.6.2007)"  /* dd.mm.yyyy */
32
33
34static const char* __attribute__((used)) verstag = "\0$VER: " VSTRING;
35
36
37struct ExpatBase {
38	struct Library libNode;
39	uint16 pad;
40	BPTR SegList;
41};
42
43
44struct ExpatBase * libInit(struct ExpatBase *libBase, BPTR seglist, struct ExecIFace *ISys);
45uint32 libObtain (struct LibraryManagerInterface *Self);
46uint32 libRelease (struct LibraryManagerInterface *Self);
47struct ExpatBase *libOpen (struct LibraryManagerInterface *Self, uint32 version);
48BPTR libClose (struct LibraryManagerInterface *Self);
49BPTR libExpunge (struct LibraryManagerInterface *Self);
50
51
52static APTR lib_manager_vectors[] = {
53	libObtain,
54	libRelease,
55	NULL,
56	NULL,
57	libOpen,
58	libClose,
59	libExpunge,
60	NULL,
61	(APTR)-1,
62};
63
64
65static struct TagItem lib_managerTags[] = {
66	{ MIT_Name, (uint32)"__library" },
67	{ MIT_VectorTable, (uint32)lib_manager_vectors },
68	{ MIT_Version, 1 },
69	{ TAG_END, 0 }
70};
71
72
73extern void *main_vectors[];
74
75static struct TagItem lib_mainTags[] = {
76	{ MIT_Name, (uint32)"main" },
77	{ MIT_VectorTable, (uint32)main_vectors },
78	{ MIT_Version, 1 },
79	{ TAG_END, 0 }
80};
81
82
83static APTR libInterfaces[] = {
84	lib_managerTags,
85	lib_mainTags,
86	NULL
87};
88
89
90static struct TagItem libCreateTags[] = {
91	{ CLT_DataSize, sizeof(struct ExpatBase) },
92	{ CLT_InitFunc, (uint32)libInit },
93	{ CLT_Interfaces, (uint32)libInterfaces },
94	{ TAG_END, 0 }
95};
96
97
98static struct Resident __attribute__((used)) lib_res = {
99	RTC_MATCHWORD,	// rt_MatchWord
100	&lib_res,		// rt_MatchTag
101	&lib_res+1,		// rt_EndSkip
102	RTF_NATIVE | RTF_AUTOINIT,	// rt_Flags
103	VERSION,		// rt_Version
104	NT_LIBRARY,		// rt_Type
105	LIBPRI,			// rt_Pri
106	LIBNAME,		// rt_Name
107	VSTRING,		// rt_IdString
108	libCreateTags	// rt_Init
109};
110
111
112struct Library *DOSLib = 0;
113struct Library *UtilityBase = 0;
114
115struct ExecIFace *IExec = 0;
116struct DOSIFace *IDOS = 0;
117struct UtilityIFace *IUtility = 0;
118
119
120void _start()
121{
122}
123
124
125struct ExpatBase *libInit(struct ExpatBase *libBase, BPTR seglist, struct ExecIFace *ISys)
126{
127	libBase->libNode.lib_Node.ln_Type = NT_LIBRARY;
128	libBase->libNode.lib_Node.ln_Pri = LIBPRI;
129	libBase->libNode.lib_Node.ln_Name = LIBNAME;
130	libBase->libNode.lib_Flags = LIBF_SUMUSED|LIBF_CHANGED;
131	libBase->libNode.lib_Version = VERSION;
132	libBase->libNode.lib_Revision = REVISION;
133	libBase->libNode.lib_IdString = VSTRING;
134	libBase->SegList = seglist;
135
136	IExec = ISys;
137
138	DOSLib = OpenLibrary("dos.library", 51);
139	if ( DOSLib != 0 )  {
140		IDOS = (struct DOSIFace *)GetInterface(DOSLib, "main", 1, NULL);
141		if ( IDOS != 0 )  {
142			UtilityBase = OpenLibrary("utility.library", 51);
143			if ( UtilityBase != 0 )  {
144				IUtility = (struct UtilityIFace*)GetInterface(UtilityBase, "main", 1, NULL);
145				if ( IUtility != 0 )  {
146					return libBase;
147				}
148
149				CloseLibrary(UtilityBase);
150			}
151
152			DropInterface((struct Interface *)IDOS);
153		}
154
155		CloseLibrary(DOSLib);
156	}
157
158	return NULL;
159}
160
161
162uint32 libObtain( struct LibraryManagerInterface *Self )
163{
164	++Self->Data.RefCount;
165	return Self->Data.RefCount;
166}
167
168
169uint32 libRelease( struct LibraryManagerInterface *Self )
170{
171	--Self->Data.RefCount;
172	return Self->Data.RefCount;
173}
174
175
176struct ExpatBase *libOpen( struct LibraryManagerInterface *Self, uint32 version )
177{
178	struct ExpatBase *libBase;
179
180	libBase = (struct ExpatBase *)Self->Data.LibBase;
181
182	++libBase->libNode.lib_OpenCnt;
183	libBase->libNode.lib_Flags &= ~LIBF_DELEXP;
184
185	return libBase;
186}
187
188
189BPTR libClose( struct LibraryManagerInterface *Self )
190{
191	struct ExpatBase *libBase;
192
193	libBase = (struct ExpatBase *)Self->Data.LibBase;
194
195	--libBase->libNode.lib_OpenCnt;
196	if ( libBase->libNode.lib_OpenCnt ) {
197		return 0;
198	}
199
200	if ( libBase->libNode.lib_Flags & LIBF_DELEXP ) {
201		return (BPTR)Self->LibExpunge();
202	}
203	else {
204		return 0;
205	}
206}
207
208
209BPTR libExpunge( struct LibraryManagerInterface *Self )
210{
211	struct ExpatBase *libBase;
212	BPTR result = 0;
213
214	libBase = (struct ExpatBase *)Self->Data.LibBase;
215
216	if (libBase->libNode.lib_OpenCnt == 0) {
217		Remove(&libBase->libNode.lib_Node);
218
219		result = libBase->SegList;
220
221		DropInterface((struct Interface *)IUtility);
222		CloseLibrary(UtilityBase);
223		DropInterface((struct Interface *)IDOS);
224		CloseLibrary(DOSLib);
225
226		DeleteLibrary(&libBase->libNode);
227	}
228	else {
229		libBase->libNode.lib_Flags |= LIBF_DELEXP;
230	}
231
232	return result;
233}
234