Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / libs / identify / idfunction.c
blob5a02ba54270eaa089b1f5a9ab5ecb3f82956bde7
1 /*
2 * Copyright (c) 2010-2011 Matthias Rustler
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 * IN THE SOFTWARE.
22 * $Id$
25 #include <proto/utility.h>
26 #include <proto/dos.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
32 #include "identify_intern.h"
33 #include "identify.h"
35 //#define DEBUG 1
36 #include <aros/debug.h>
39 static struct LibNode *searchLibrary(struct List *libList, CONST_STRPTR libname);
40 static BOOL addFuncNode(struct List *funcList, CONST_STRPTR line, ULONG offset, struct IdentifyBaseIntern *libBase);
41 static struct LibNode *loadFD(struct List *libList, CONST_STRPTR libname, struct IdentifyBaseIntern *libBase);
42 static CONST_STRPTR searchFunction(struct LibNode *libNode, ULONG offset);
45 /*****************************************************************************
47 NAME */
48 #include <proto/identify.h>
50 AROS_LH3(LONG, IdFunction,
52 /* SYNOPSIS */
53 AROS_LHA(STRPTR , libname, A0),
54 AROS_LHA(LONG , offset , D0),
55 AROS_LHA(struct TagItem *, taglist, A1),
57 /* LOCATION */
58 struct IdentifyBaseIntern *, IdentifyBase, 8, Identify)
60 /* FUNCTION
61 Decodes the offset of the provided library name into function name.
63 This function requires the .fd files in a drawer with 'FD:' assigned
64 to it. All files must have the standard file name format, e.g.
65 'exec_lib.fd'.
67 The appropriate .fd file will be scanned. The result will be
68 cached until the identify.library is removed from system.
70 INPUTS
71 LibName -- (STRPTR) name of the function's library, device
72 or resource. All letters behind the point (and
73 the point itself) are optional. The name is
74 case sensitive.
76 Examples: 'exec.library', 'dos', 'cia.resource'.
78 Offset -- (LONG) offset of the function. It must be a
79 multiple of 6. You do not need to provide the
80 minus sign.
82 Examples: -456, 60
84 TagList -- (struct TagItem *) tags that describe further
85 options.
87 RESULT
88 Error -- (LONG) error code, or 0 if everything went fine.
90 TAGS
91 IDTAG_FuncNameStr -- (STRPTR) Buffer where the function name
92 will be copied into.
94 IDTAG_StrLength -- (UWORD) Maximum length of the string buffer,
95 including termination. Defaults to 50.
97 NOTES
99 EXAMPLE
101 BUGS
102 Every line in the .fd file must have a maximum of 254 characters.
103 Otherwise the internal offset table may be corrupted (but the
104 system won't be harmed). Anyhow, this should be no problem.
106 SEE ALSO
108 INTERNALS
110 HISTORY
113 *****************************************************************************/
115 AROS_LIBFUNC_INIT
117 struct TagItem *tag;
118 struct TagItem *tags;
119 STRPTR funcNameStr = NULL;
120 ULONG strLength = 0;
121 struct LibNode *libNode;
122 LONG retVal = IDERR_OKAY;
124 for (tags = taglist; (tag = NextTagItem(&tags)); )
126 switch (tag->ti_Tag)
128 case IDTAG_FuncNameStr:
129 funcNameStr = (STRPTR)tag->ti_Data;
130 break;
132 case IDTAG_StrLength:
133 strLength = tag->ti_Data;
134 break;
138 if (funcNameStr == NULL || strLength == 0)
139 return IDERR_NOLENGTH;
141 offset = abs(offset);
142 if (offset % 6)
143 return IDERR_OFFSET;
145 ObtainSemaphore(&IdentifyBase->sem);
147 libNode = searchLibrary(&IdentifyBase->libList, libname);
148 if (!libNode)
150 libNode = loadFD(&IdentifyBase->libList, libname, IdentifyBase);
153 if (libNode)
155 strlcpy(funcNameStr, searchFunction(libNode, offset), strLength);
156 if (funcNameStr == NULL)
158 retVal = IDERR_OFFSET;
161 else
163 retVal = IDERR_NOFD;
166 ReleaseSemaphore(&IdentifyBase->sem);
168 return retVal;
170 AROS_LIBFUNC_EXIT
171 } /* IdFunction */
176 static struct LibNode *searchLibrary(struct List *libList, CONST_STRPTR libname)
178 struct LibNode *libNode;
179 ULONG len;
180 STRPTR dot = strchr(libname, '.');
182 if (dot)
184 len = (IPTR)dot - (IPTR)libname;
186 else
188 len = strlen(libname);
191 D(bug("[idfunction/searchLibrary] libList %p libname %s len %u\n", libList, libname, len));
193 ForeachNode(libList, libNode)
195 if (strncmp(libname, libNode->nd.ln_Name, len) == 0)
197 D(bug("[idfunction/searchLibrary] found %p\n", libNode));
198 return libNode;
201 D(bug("[idfunction/searchLibrary] found nothing\n"));
202 return NULL;
205 static BOOL addFuncNode(struct List *funcList, CONST_STRPTR line, ULONG offset, struct IdentifyBaseIntern *libBase)
207 D(bug("[idfunction/addFuncNode] funcList %p line %s offset %u\n", funcList, line, offset));
209 struct FuncNode *newNode = AllocVecPooled(libBase->poolMem, sizeof (struct FuncNode));
210 if (newNode)
212 memset(newNode, 0, sizeof (struct FuncNode));
213 int len;
215 STRPTR bracket = strchr(line, '(');
216 if (bracket)
218 len = (IPTR)bracket - (IPTR)line;
220 else
222 len = strlen(line);
225 STRPTR name = AllocVecPooled(libBase->poolMem, len + 1);
226 if (name)
228 newNode->nd.ln_Name = name;
229 strlcpy(newNode->nd.ln_Name, line, len + 1);
230 newNode->offset = offset;
231 AddTail(funcList, (struct Node *)newNode);
232 D(bug("[idfunction/addFuncNode] funcnode %p name %s offset %u created\n", newNode, newNode->nd.ln_Name, newNode->offset));
233 return TRUE;
235 else
237 FreeVecPooled(libBase->poolMem, newNode);
240 D(bug("[idfunction/addFuncNode] failed to create funcnode\n"));
241 return FALSE;
244 static struct LibNode *loadFD(struct List *libList, CONST_STRPTR libname, struct IdentifyBaseIntern *libBase)
246 struct LibNode *retVal = NULL;
247 struct LibNode *newNode = NULL;
248 STRPTR fileName = NULL;
249 STRPTR libNameStripped = NULL;
250 BPTR fileHandle = BNULL;
251 TEXT buffer[256];
252 ULONG offset = 0;
253 ULONG len;
254 STRPTR dot = strchr(libname, '.');
256 D(bug("[idfunction/loadFD] libList %p libname %s\n", libList, libname));
258 if (dot)
260 len = (IPTR)dot - (IPTR)libname;
262 else
264 len = strlen(libname);
267 libNameStripped = AllocVecPooled(libBase->poolMem, len + 1);
268 if (libNameStripped == NULL)
270 D(bug("[idfunction/loadFD] out of mem for libNameStripped\n"));
271 goto bailout;
273 strlcpy(libNameStripped, libname, len + 1);
275 fileName = AllocVecPooled(libBase->poolMem, len + 30);
276 if (fileName == NULL)
278 D(bug("[idfunction/loadFD] out of mem for filename\n"));
279 goto bailout;
281 sprintf(fileName, "Development:fd/%s_lib.fd", libNameStripped);
283 D(bug("[idfunction/loadFD] libnamestripped %s filename %s\n", libNameStripped, fileName));
285 fileHandle = Open(fileName, MODE_OLDFILE);
286 if (fileHandle == BNULL)
288 D(bug("[idfunction/loadFD] failed to open file\n"));
289 goto bailout;
292 newNode = AllocVecPooled(libBase->poolMem, sizeof (struct LibNode));
293 if (newNode == NULL)
295 D(bug("[idfunction/loadFD] out of mem for LibNode\n"));
296 goto bailout;
299 newNode->nd.ln_Name = libNameStripped;
301 NEWLIST(&newNode->funcList);
303 while (FGets(fileHandle, buffer, sizeof (buffer)))
305 D(bug("[idfunction/loadFD] line %s\n", buffer));
307 if (buffer[0] == '*')
309 D(bug("[idfunction/loadFD] comment\n"));
311 else if (buffer[0] == '#')
313 if (strncmp(buffer, "##bias", 6) == 0)
315 D(bug("[idfunction/loadFD] ##bias\n"));
316 LONG value;
317 StrToLong(buffer + 6, &value);
318 offset = value;
320 else if (strncmp(buffer, "##end", 5) == 0)
322 D(bug("[idfunction/loadFD] ##end\n"));
323 break;
325 else
327 D(bug("[idfunction/loadFD] unknown command\n"));
330 else
332 addFuncNode(&newNode->funcList, buffer, offset, libBase);
333 offset += 6;
336 AddTail(libList, (struct Node *)newNode);
337 retVal = newNode;
339 bailout:
340 if (fileHandle) Close(fileHandle);
341 FreeVecPooled(libBase->poolMem, fileName);
342 return retVal;
345 static CONST_STRPTR searchFunction(struct LibNode *libNode, ULONG offset)
347 struct FuncNode *node;
349 D(bug("[idfunction/searchFunction] libNode %p offset %u\n", libNode, offset));
351 ForeachNode(&libNode->funcList, node)
353 if (node->offset == offset)
355 D(bug("[idfunction/searchFunction] found node %p name %s\n", node, node->nd.ln_Name));
356 return node->nd.ln_Name;
359 return ""; // FIXME: should we check that offset doesn't exceed highest LVO?