text: /*
   * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
   *
   * @APPLE_LICENSE_HEADER_START@
   * 
   * This file contains Original Code and/or Modifications of Original Code
   * as defined in and that are subject to the Apple Public Source License
   * Version 2.0 (the 'License'). You may not use this file except in
   * compliance with the License. Please obtain a copy of the License at
   * http://www.opensource.apple.com/apsl/ and read it before using this
   * file.
   * 
   * The Original Code and all software distributed under the License are
   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   * Please see the License for the specific language governing rights and
   * limitations under the License.
   * 
   * @APPLE_LICENSE_HEADER_END@
   */
  #ifndef RLD
  #include <string.h>
  #include "stuff/bool.h"
  #include "stuff/errors.h"
  #include "stuff/allocate.h"
  #include "stuff/guess_short_name.h"
  
  static char *look_back_for_slash(
      char *name,
      char *p);
  
  /*
   * guess_short_name() is passed a name of a dynamic library and returns a guess
   * on what the short name is.  Then name is returned as a pointer to allocated
   * memory that can be free()'ed later.  The name of the dynamic library is
   * recognized as a framework if it has one of the two following forms:
   *	Foo.framework/Versions/A/Foo
   *	Foo.framework/Foo
   * Where A and Foo can be any string.  And may contain a trailing suffix
   * starting with an underbar.  If the name is recognized as a framework then
   * *is_framework is set to TRUE else it is set to FALSE.  If the name has a
   * suffix then *return_suffix is set to allocated memory that contains the
   * suffix else it is set to NULL.
   *
   * The name of the dynamic library is recognized as a library name if it has
   * one of the two following forms:
   *	libFoo.A.dylib
   *	libFoo.dylib
   * The library may have a suffix trailing the name Foo of the form:
   *	libFoo_profile.A.dylib
   *	libFoo_profile.dylib
   *
   * The name of the dynamic library is also recognized as a library name if it
   * has the following form:
   *	Foo.qtx
   *
   * If the name of the dynamic library is none of the forms above then NULL is
   * returned.
   */
  __private_extern__
  char *
  guess_short_name(
  char *name,
  enum bool *is_framework,
  char **return_suffix)
  {
      char *foo, *a, *b, *c, *d, *suffix, *guess;
      unsigned long l, s;
  
  	*is_framework = FALSE;
  	*return_suffix = NULL;
  	/* pull off the last component and make foo point to it */
  	a = strrchr(name, '/');
  	if(a == NULL)
  	    goto guess_library;
  	if(a == name)
  	    goto guess_library;
  	foo = a + 1;
  	l = strlen(foo);
  	
  	/* look for a suffix starting with a '_' */
  	suffix = strrchr(foo, '_');
  	if(suffix != NULL){
  	    s = strlen(suffix);
  	    if(suffix == foo || s < 2)
  		suffix = NULL;
  	    else{
  		l -= s;
  		*return_suffix = allocate(s + 1);
  		strncpy(*return_suffix, suffix, s);
  		(*return_suffix)[s] = '\0';
  	    }
  	}
  
  	/* first look for the form Foo.framework/Foo */
  	b = look_back_for_slash(name, a);
  	if(b == NULL){
  	    if(strncmp(name, foo, l) == 0 &&
  	       strncmp(name + l, ".framework/", sizeof(".framework/")-1 ) == 0){
  		guess = allocate(l + 1);
  		strncpy(guess, name, l);
  		guess[l] = '\0';
  		*is_framework = TRUE;
  		return(guess);
  	    }
  	    else
  		goto guess_library;
  	}
  	else{
  	    if(strncmp(b+1, foo, l) == 0 &&
  	       strncmp(b+1 + l, ".framework/", sizeof(".framework/")-1 ) == 0){
  		guess = allocate(l + 1);
  		strncpy(guess, b+1, l);
  		guess[l] = '\0';
  		*is_framework = TRUE;
  		return(guess);
  	    }
  	}
  
  	/* next look for the form Foo.framework/Versions/A/Foo */
  	if(b == name)
  	    goto guess_library;
  	c = look_back_for_slash(name, b);
  	if(c == NULL ||
  	   c == name ||
  	   strncmp(c+1, "Versions/", sizeof("Versions/")-1) != 0)
  	    goto guess_library;
  	d = look_back_for_slash(name, c);
  	if(d == NULL){
  	    if(strncmp(name, foo, l) == 0 &&
  	       strncmp(name + l, ".framework/", sizeof(".framework/")-1 ) == 0){
  		guess = allocate(l + 1);
  		strncpy(guess, name, l);
  		guess[l] = '\0';
  		*is_framework = TRUE;
  		return(guess);
  	    }
  	    else
  		goto guess_library;
  	}
  	else{
  	    if(strncmp(d+1, foo, l) == 0 &&
  	       strncmp(d+1 + l, ".framework/", sizeof(".framework/")-1 ) == 0){
  		guess = allocate(l + 1);
  		strncpy(guess, d+1, l);
  		guess[l] = '\0';
  		*is_framework = TRUE;
  		return(guess);
  	    }
  	    else
  		goto guess_library;
  	}
  
  guess_library:
  	/* pull off the suffix after the "." and make a point to it */
  	a = strrchr(name, '.');
  	if(a == NULL)
  	    return(NULL);
  	if(a == name)
  	    return(NULL);
  	if(strcmp(a, ".dylib") != 0)
  	    goto guess_qtx;
  
  	/* first pull off the version letter for the form Foo.A.dylib */
  	if(a - name >= 3 && a[-2] == '.')
  	    a = a - 2;
  
  	b = look_back_for_slash(name, a);
  	if(b == name)
  	    return(NULL);
  	if(b == NULL){
  	    /* ignore any suffix after an underbar
  	       like Foo_profile.A.dylib */
  	    c = strchr(name, '_');
  	    if(c != NULL && c != name){
  		l = c - name;
  		suffix = c;
  		for(s = 0; suffix[s] != '.'; s++)
  		    ;
  		*return_suffix = allocate(s + 1);
  		strncpy(*return_suffix, suffix, s);
  		(*return_suffix)[s] = '\0';
  	    }
  	    else
  		l = a - name;
  	    /* there are incorrect library names of the form:
  	       libATS.A_profile.dylib so check for these */
  	    if(l >= 3 && name[l-2] == '.')
  		l = l - 2;
  	    guess = allocate(l + 1);
  	    strncpy(guess, name, l);
  	    guess[l] = '\0';
  	    return(guess);
  	}
  	else{
  	    /* ignore any suffix after an underbar
  	       like Foo_profile.A.dylib */
  	    c = strchr(b+1, '_');
  	    if(c != NULL && c != b+1){
  		l = c - (b+1);
  		suffix = c;
  		for(s = 0; suffix[s] != '.'; s++)
  		    ;
  		*return_suffix = allocate(s + 1);
  		strncpy(*return_suffix, suffix, s);
  		(*return_suffix)[s] = '\0';
  	    }
  	    else
  		l = a - (b+1);
  	    /* there are incorrect library names of the form:
  	       libATS.A_profile.dylib so check for these */
  	    if(l >= 3 && b[1+l-2] == '.')
  		l = l - 2;
  	    guess = allocate(l + 1);
  	    strncpy(guess, b+1, l);
  	    guess[l] = '\0';
  	    return(guess);
  	}
  
  guess_qtx:
  	a = strrchr(name, '.');
  	if(strcmp(a, ".qtx") != 0)
  	    return(NULL);
  
  	b = look_back_for_slash(name, a);
  	if(b == name)
  	    return(NULL);
  	if(b == NULL){
  	    l = a - name;
  	    /* there are library names of the form:
  	       QT.A.qtx so check for these */
  	    if(l >= 3 && name[l-2] == '.')
  		l = l - 2;
  	    guess = allocate(l + 1);
  	    strncpy(guess, name, l);
  	    guess[l + 1] = '\0';
  	    return(guess);
  	}
  	else{
  	    l = a - (b+1);
  	    /* there are library names of the form:
  	       QT.A.qtx so check for these */
  	    if(l >= 3 && b[1+l-2] == '.')
  		l = l - 2;
  	    guess = allocate(l + 1);
  	    strncpy(guess, b+1, l);
  	    guess[l + 1] = '\0';
  	    return(guess);
  	}
  }
  
  /*
   * look_back_for_slash() is passed a string name and an end point in name to
   * start looking for '/' before the end point.  It returns a pointer to the
   * '/' back from the end point or NULL if there is none.
   */
  static
  char *
  look_back_for_slash(
  char *name,
  char *p)
  {
  	for(p = p - 1; p >= name; p--){
  	    if(*p == '/')
  		return(p);
  	}
  	return(NULL);
  }
  #endif /* !defined(RLD) */
  