
/*
 *  $Header: /data/01/postgres/src/backend/port/dld/RCS/dynloader.c,v 1.5 1993/06/03 23:56:15 andrew Exp $
 */


/*
 * DLD ver 3.2.3
 *
 * How does this work?  
 *
 * pretty simple (read the DLD docs). But still need to make sure
 * loaded objects are compiled with "-G 0" on DECs.
 *
 */ 

#include <stdio.h>
#include "tmp/c.h"
#include "fmgr.h"
#include "utils/log.h"

extern char pg_pathname[];
DynamicFunctionList *load_symbols();
static void check_undefined();

extern char **dld_list_undefined_sym();	/* in dld.h */
extern int dld_undefSymCount(); 	/* in dld.c */


DynamicFunctionList *
dynamic_file_load(err, filename, start_addr, size)

char **err, *filename, **start_addr;
long *size;

{
	static int dld_initialized= 0;

	if (!dld_initialized) {	  /* only need to do this once */
	    dld_init(pg_pathname);
	    dld_initialized= 1;
	}

	/* note that start_addr and size will not (and should
	   not) be used by other routines, so we don't bother
	   to return anything real */
	*start_addr = 0;
	*size = 0;

	if (dld_link(filename)) {
	    char err_msg[500];
	    dld_sperror(err_msg, "dynamic_file_load: Can't link %s");
	    elog(WARN, err_msg, filename);
	    return NULL;
	}

	return load_symbols(filename,0);
}

/*
 * Cheat massively because I can't figure out how to read the symbol table
 * properly, so use system("nm ...") to do it instead.
 *
 * I choose to keep "nm" around because it takes only an insignificant 
 * amount of time to do. Also, DLD hashes the function names and addresses
 * which makes it hard to just pull out those for the desired object.
 *  -- AKY
 */

DynamicFunctionList *
load_symbols(filename, entry_addr)

char *filename; int entry_addr;

{
	char command[256];
	char line[256];
	char *tmp_file;
	FILE *fp;
	DynamicFunctionList *head, *scanner;
	int entering = 1, func_addr;
	char funcname[256];

	/* create a temporary file name */
	tmp_file = (char *) palloc(64);
	sprintf(tmp_file, "/tmp/_pg_dyn%ld", getpid());

	sprintf(command, "/usr/bin/nm %s | grep \' T \' > %s", filename, tmp_file);

	if (system(command))
		fprintf(stderr, "system() died\n");

	fp = fopen(tmp_file, "r");

	while (fgets(line, 255, fp) != NULL)
	{
#ifndef __mips
                /* _overpaid() -> overpaid() */
                sscanf(line, "%lx T _%s", &func_addr, funcname);
#else
		sscanf(line, "%lx T %s", &func_addr, funcname);
#endif
		if (entering)
		{
			head = (DynamicFunctionList *)
				   malloc(sizeof(DynamicFunctionList));
			scanner = head;
			entering = 0;
		}
		else
		{
			scanner->next = (DynamicFunctionList *)
							malloc(sizeof(DynamicFunctionList));
			scanner = scanner->next;
		}

		scanner->funcname= (char *)strcpy(malloc(strlen(funcname)+1),funcname);
		if(dld_function_executable_p(funcname)) {
		    scanner->func = (func_ptr) (dld_get_func(funcname));
		}else {
		    scanner->func = (func_ptr) 0;
		}
		scanner->next = NULL;
	}

	check_undefined();
	fclose(fp);
	unlink(tmp_file);
	pfree(tmp_file);
	return(head);
}

static void check_undefined () 
{
    char **list = dld_list_undefined_sym ();
    int count= dld_undefSymCount();

    if (list) {
	int i;
	elog(NOTICE, " undefined symbols:");
	for (i = 0; i < count; i++)
	    elog(NOTICE, "     %s", list[i]);
	elog(WARN, "load_symbols: total of %d undefined symbols.", count);
    }
}

