/* Stubby - Generate stubs for dynamic-link libraries.
 * Copyright 1999 Tom Rothamel
 *
 * Stubby is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version. It is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * This program generates another computer program. I do not assert a      
 * copyright on the generated program that is the normal output of this    
 * program. This is _not_, however, an authorization for you to modify     
 * this program to cause it to output more of itself than necessary for    
 * its proper operation in order to circumvent my copyright.               
 */

/* This code is massively platform dependant. What it can do is convert
 * the command-line options. (Which looks like gcc LDFLAGS.) This can then
 * be included into a stub file.
 */

#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>

#define error(x, args...) { fprintf(stderr, "stubby-auto: " x "\n" , ## args); \
				exit(-1); }
#define warning(x, args...) { fprintf(stderr, "stubby-auto: " x "\n" , ## args); \
			    }
struct libpath {
	struct libpath *next;
	char *path;
};

struct libpath *first_libpath = NULL;

/* This attempts to find the location of a library. If it can do so, it
 * prints out a line that can be included in a stub file. */
void library(char *lib, char *prefix, int first) {
	struct libpath *lp;
	char buf[256];
	char rlpath[256];
	int rlcount;
	char *s = NULL;
	char *ss;
	
	lp = first_libpath;
	while (lp) {
		snprintf(buf, 256, "%s/lib%s.so", lp->path, lib);
		rlcount = readlink(buf, rlpath, 255);
		if (rlcount != -1) break;

		lp = lp->next;
	}

	if (!lp) error("Couldn't find lib%s.so", lib);

	rlpath[rlcount] = 0;

	s = rindex(rlpath, '/');
	if (s) {
		s++;
	} else {
		s = rlpath;
	}

	ss = strstr(s, ".so.");
	if (ss) {
		ss += 4;
		while (*ss) {
			if (*ss == '.') {
				*ss = 0;
				break;
			}
			ss++;
		}
	}

	if (first) {
		printf("library %s \"%s\";\n", prefix, s);
	} else {
		printf("load \"%s\";\n", s);
	}
}
		
/* This adds a path to the list of library paths. */
void add_libpath(char *path) {
	struct libpath *nlp;

	nlp = (struct libpath *)  malloc(sizeof(struct libpath));
	nlp->next = first_libpath;
	nlp->path = path;
	first_libpath = nlp;
}


int main(int argc, char **argv) {
	char *s;
	int i;
	int first = 1;
	char *prefix = "stub";

	add_libpath("/lib");
	add_libpath("/usr/lib");
	
	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-')
			error("%s is not a flag.", argv[i]);

		switch(argv[i][1]) {
		case 'P':
			prefix = &argv[i][2];
			break;
		case 'L':
			add_libpath(&argv[i][2]);
			break;
		case 'l':
			library(&argv[i][2], prefix, first);
			first = 0;
			break;
		default:
			warning("Unknown flag '-%c'.", argv[i][1]);
		}
	}

	exit(0);
}
			
		       
	

	
					 
