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
25 #include <proto/utility.h>
26 #include <proto/dos.h>
32 #include "identify_intern.h"
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 /*****************************************************************************
48 #include <proto/identify.h>
50 AROS_LH3(LONG
, IdFunction
,
53 AROS_LHA(STRPTR
, libname
, A0
),
54 AROS_LHA(LONG
, offset
, D0
),
55 AROS_LHA(struct TagItem
*, taglist
, A1
),
58 struct IdentifyBaseIntern
*, IdentifyBase
, 8, Identify
)
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.
67 The appropriate .fd file will be scanned. The result will be
68 cached until the identify.library is removed from system.
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
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
84 TagList -- (struct TagItem *) tags that describe further
88 Error -- (LONG) error code, or 0 if everything went fine.
91 IDTAG_FuncNameStr -- (STRPTR) Buffer where the function name
94 IDTAG_StrLength -- (UWORD) Maximum length of the string buffer,
95 including termination. Defaults to 50.
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.
113 *****************************************************************************/
118 struct TagItem
*tags
;
119 STRPTR funcNameStr
= NULL
;
121 struct LibNode
*libNode
;
122 LONG retVal
= IDERR_OKAY
;
124 for (tags
= taglist
; (tag
= NextTagItem(&tags
)); )
128 case IDTAG_FuncNameStr
:
129 funcNameStr
= (STRPTR
)tag
->ti_Data
;
132 case IDTAG_StrLength
:
133 strLength
= tag
->ti_Data
;
138 if (funcNameStr
== NULL
|| strLength
== 0)
139 return IDERR_NOLENGTH
;
141 offset
= abs(offset
);
145 ObtainSemaphore(&IdentifyBase
->sem
);
147 libNode
= searchLibrary(&IdentifyBase
->libList
, libname
);
150 libNode
= loadFD(&IdentifyBase
->libList
, libname
, IdentifyBase
);
155 strlcpy(funcNameStr
, searchFunction(libNode
, offset
), strLength
);
156 if (funcNameStr
== NULL
)
158 retVal
= IDERR_OFFSET
;
166 ReleaseSemaphore(&IdentifyBase
->sem
);
176 static struct LibNode
*searchLibrary(struct List
*libList
, CONST_STRPTR libname
)
178 struct LibNode
*libNode
;
180 STRPTR dot
= strchr(libname
, '.');
184 len
= (IPTR
)dot
- (IPTR
)libname
;
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
));
201 D(bug("[idfunction/searchLibrary] found nothing\n"));
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
));
212 memset(newNode
, 0, sizeof (struct FuncNode
));
215 STRPTR bracket
= strchr(line
, '(');
218 len
= (IPTR
)bracket
- (IPTR
)line
;
225 STRPTR name
= AllocVecPooled(libBase
->poolMem
, len
+ 1);
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
));
237 FreeVecPooled(libBase
->poolMem
, newNode
);
240 D(bug("[idfunction/addFuncNode] failed to create funcnode\n"));
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
;
254 STRPTR dot
= strchr(libname
, '.');
256 D(bug("[idfunction/loadFD] libList %p libname %s\n", libList
, libname
));
260 len
= (IPTR
)dot
- (IPTR
)libname
;
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"));
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"));
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"));
292 newNode
= AllocVecPooled(libBase
->poolMem
, sizeof (struct LibNode
));
295 D(bug("[idfunction/loadFD] out of mem for LibNode\n"));
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"));
317 StrToLong(buffer
+ 6, &value
);
320 else if (strncmp(buffer
, "##end", 5) == 0)
322 D(bug("[idfunction/loadFD] ##end\n"));
327 D(bug("[idfunction/loadFD] unknown command\n"));
332 addFuncNode(&newNode
->funcList
, buffer
, offset
, libBase
);
336 AddTail(libList
, (struct Node
*)newNode
);
340 if (fileHandle
) Close(fileHandle
);
341 FreeVecPooled(libBase
->poolMem
, fileName
);
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?