nm: Add nm.c source and support for building the nm tool
[striptease.git] / libstuff / guess_short_name.c
blob353eb571e9ac48a0eda5dca40522a9b4f35ddc13
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 #ifndef RLD
24 #include <string.h>
25 #include "stuff/bool.h"
26 #include "stuff/errors.h"
27 #include "stuff/allocate.h"
28 #include "stuff/guess_short_name.h"
30 static char *look_back_for_slash(
31 char *name,
32 char *p);
35 * guess_short_name() is passed a name of a dynamic library and returns a guess
36 * on what the short name is. Then name is returned as a pointer to allocated
37 * memory that can be free()'ed later. The name of the dynamic library is
38 * recognized as a framework if it has one of the two following forms:
39 * Foo.framework/Versions/A/Foo
40 * Foo.framework/Foo
41 * Where A and Foo can be any string. And may contain a trailing suffix
42 * starting with an underbar. If the name is recognized as a framework then
43 * *is_framework is set to TRUE else it is set to FALSE. If the name has a
44 * suffix then *return_suffix is set to allocated memory that contains the
45 * suffix else it is set to NULL.
47 * The name of the dynamic library is recognized as a library name if it has
48 * one of the two following forms:
49 * libFoo.A.dylib
50 * libFoo.dylib
51 * The library may have a suffix trailing the name Foo of the form:
52 * libFoo_profile.A.dylib
53 * libFoo_profile.dylib
55 * The name of the dynamic library is also recognized as a library name if it
56 * has the following form:
57 * Foo.qtx
59 * If the name of the dynamic library is none of the forms above then NULL is
60 * returned.
62 __private_extern__
63 char *
64 guess_short_name(
65 char *name,
66 enum bool *is_framework,
67 char **return_suffix)
69 char *foo, *a, *b, *c, *d, *suffix, *guess;
70 unsigned long l, s;
72 *is_framework = FALSE;
73 *return_suffix = NULL;
74 /* pull off the last component and make foo point to it */
75 a = strrchr(name, '/');
76 if(a == NULL)
77 goto guess_library;
78 if(a == name)
79 goto guess_library;
80 foo = a + 1;
81 l = strlen(foo);
83 /* look for a suffix starting with a '_' */
84 suffix = strrchr(foo, '_');
85 if(suffix != NULL){
86 s = strlen(suffix);
87 if(suffix == foo || s < 2)
88 suffix = NULL;
89 else{
90 l -= s;
91 *return_suffix = allocate(s + 1);
92 strncpy(*return_suffix, suffix, s);
93 (*return_suffix)[s] = '\0';
97 /* first look for the form Foo.framework/Foo */
98 b = look_back_for_slash(name, a);
99 if(b == NULL){
100 if(strncmp(name, foo, l) == 0 &&
101 strncmp(name + l, ".framework/", sizeof(".framework/")-1 ) == 0){
102 guess = allocate(l + 1);
103 strncpy(guess, name, l);
104 guess[l] = '\0';
105 *is_framework = TRUE;
106 return(guess);
108 else
109 goto guess_library;
111 else{
112 if(strncmp(b+1, foo, l) == 0 &&
113 strncmp(b+1 + l, ".framework/", sizeof(".framework/")-1 ) == 0){
114 guess = allocate(l + 1);
115 strncpy(guess, b+1, l);
116 guess[l] = '\0';
117 *is_framework = TRUE;
118 return(guess);
122 /* next look for the form Foo.framework/Versions/A/Foo */
123 if(b == name)
124 goto guess_library;
125 c = look_back_for_slash(name, b);
126 if(c == NULL ||
127 c == name ||
128 strncmp(c+1, "Versions/", sizeof("Versions/")-1) != 0)
129 goto guess_library;
130 d = look_back_for_slash(name, c);
131 if(d == NULL){
132 if(strncmp(name, foo, l) == 0 &&
133 strncmp(name + l, ".framework/", sizeof(".framework/")-1 ) == 0){
134 guess = allocate(l + 1);
135 strncpy(guess, name, l);
136 guess[l] = '\0';
137 *is_framework = TRUE;
138 return(guess);
140 else
141 goto guess_library;
143 else{
144 if(strncmp(d+1, foo, l) == 0 &&
145 strncmp(d+1 + l, ".framework/", sizeof(".framework/")-1 ) == 0){
146 guess = allocate(l + 1);
147 strncpy(guess, d+1, l);
148 guess[l] = '\0';
149 *is_framework = TRUE;
150 return(guess);
152 else
153 goto guess_library;
156 guess_library:
157 /* pull off the suffix after the "." and make a point to it */
158 a = strrchr(name, '.');
159 if(a == NULL)
160 return(NULL);
161 if(a == name)
162 return(NULL);
163 if(strcmp(a, ".dylib") != 0)
164 goto guess_qtx;
166 /* first pull off the version letter for the form Foo.A.dylib */
167 if(a - name >= 3 && a[-2] == '.')
168 a = a - 2;
170 b = look_back_for_slash(name, a);
171 if(b == name)
172 return(NULL);
173 if(b == NULL){
174 /* ignore any suffix after an underbar
175 like Foo_profile.A.dylib */
176 c = strchr(name, '_');
177 if(c != NULL && c != name){
178 l = c - name;
179 suffix = c;
180 for(s = 0; suffix[s] != '.'; s++)
182 *return_suffix = allocate(s + 1);
183 strncpy(*return_suffix, suffix, s);
184 (*return_suffix)[s] = '\0';
186 else
187 l = a - name;
188 /* there are incorrect library names of the form:
189 libATS.A_profile.dylib so check for these */
190 if(l >= 3 && name[l-2] == '.')
191 l = l - 2;
192 guess = allocate(l + 1);
193 strncpy(guess, name, l);
194 guess[l] = '\0';
195 return(guess);
197 else{
198 /* ignore any suffix after an underbar
199 like Foo_profile.A.dylib */
200 c = strchr(b+1, '_');
201 if(c != NULL && c != b+1){
202 l = c - (b+1);
203 suffix = c;
204 for(s = 0; suffix[s] != '.'; s++)
206 *return_suffix = allocate(s + 1);
207 strncpy(*return_suffix, suffix, s);
208 (*return_suffix)[s] = '\0';
210 else
211 l = a - (b+1);
212 /* there are incorrect library names of the form:
213 libATS.A_profile.dylib so check for these */
214 if(l >= 3 && b[1+l-2] == '.')
215 l = l - 2;
216 guess = allocate(l + 1);
217 strncpy(guess, b+1, l);
218 guess[l] = '\0';
219 return(guess);
222 guess_qtx:
223 a = strrchr(name, '.');
224 if(strcmp(a, ".qtx") != 0)
225 return(NULL);
227 b = look_back_for_slash(name, a);
228 if(b == name)
229 return(NULL);
230 if(b == NULL){
231 l = a - name;
232 /* there are library names of the form:
233 QT.A.qtx so check for these */
234 if(l >= 3 && name[l-2] == '.')
235 l = l - 2;
236 guess = allocate(l + 1);
237 strncpy(guess, name, l);
238 guess[l + 1] = '\0';
239 return(guess);
241 else{
242 l = a - (b+1);
243 /* there are library names of the form:
244 QT.A.qtx so check for these */
245 if(l >= 3 && b[1+l-2] == '.')
246 l = l - 2;
247 guess = allocate(l + 1);
248 strncpy(guess, b+1, l);
249 guess[l + 1] = '\0';
250 return(guess);
255 * look_back_for_slash() is passed a string name and an end point in name to
256 * start looking for '/' before the end point. It returns a pointer to the
257 * '/' back from the end point or NULL if there is none.
259 static
260 char *
261 look_back_for_slash(
262 char *name,
263 char *p)
265 for(p = p - 1; p >= name; p--){
266 if(*p == '/')
267 return(p);
269 return(NULL);
271 #endif /* !defined(RLD) */