ftp.nice.ch/pub/next/developer/languages/ada/Adaed.1.11.s.tar.gz#/Adaed-1.11.0a/load.c

This is load.c in view mode; [Download] [Up]

/*
 * Copyright (C) 1985-1992  New York University
 * 
 * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
 * warranty (none) and distribution info and also the GNU General Public
 * License for more details.

 */

/* load.c - procedures to load to libraries and axq files */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "int.h"
#include "segment.h"
#include "slot.h"
#include "ivars.h"
#include "ifile.h"
#ifdef vms
/*
#include "adaexec.h"
#include descrip
*/
#endif
#include "miscprots.h"
#include "libfprots.h"
#include "axqrprots.h"
#include "loadprots.h"

static void init_predef();
static void init_library(IFILE *, char *);
static char *unit_name_name(char *);
static int *unit_list_new();
static void unit_list_copy(int *, int *);
static int unit_list_next(int *);
static int in_loaded(char *);

/* Various sets and maps in the SETL version are represented using
 * strings in the C version. This is possible since they all have as
 * their domain unit_numbers, and the total number of unit_numbers is
 * known before these are needed. The initial values of these items
 * are set by 
 *	s = unit_list_new(). 
 * Once defined, s[i] is YES if unit i is in the set, NO otherwise.
 * These sets are kept as a vector of (short) integers, with the
 * first (zeroth) element giving the number of elements, in much the
 * way is tuples are represented in the other parts of the compiler.
 */
#define YES 1
#define NO 0

static char  **file_number;
static int  **PRECEDES_MAP;
static char  **unit_names;
static int     unit_count;
static int   interfaced_unit = 0;
static int   obsolete_error = FALSE;

/* The following struct is used main a list of the units actually loaded. */
struct axq_loaded {
	struct axq_loaded  *loaded_next;
	char   *loaded_name;
};
static struct axq_loaded  *ll_head; /* pointer to head of list */

static void init_predef()										/*;init_predef*/
{
	int     i;
	static char *predef_units[] = {
		"spSYSTEM", "spIO_EXCEPTIONS", "spSEQUENTIAL_IO",
		"boSEQUENTIAL_IO", "spDIRECT_IO", "boDIRECT_IO",
		"spTEXT_IO", "boTEXT_IO", "spCALENDAR", "boCALENDAR",
		"ssUNCHECKED_DEALLOCATION", "suUNCHECKED_DEALLOCATION",
		"ssUNCHECKED_CONVERSION", "suUNCHECKED_CONVERSION"
#ifdef PREDEF_PC
		,"spTEXT_IO_TYPES", "spTIO_MANAGE", "boTIO_MANAGE",
		"spTIO_DEFAULT", "boTIO_DEFAULT", "spTIO_LENGTH",
		"boTIO_LENGTH", "spTIO_LAYOUT", "boTIO_LAYOUT",
		"spTIO_STRING", "boTIO_STRING", 
		"spTIO_INTEGER", "boTIO_INTEGER",
		"spTIO_FLOAT", "boTIO_FLOAT",
		"spTIO_FIXED", "boTIO_FIXED",
		"spTIO_ENUMERATION", "boTIO_ENUMERATION",
		"spINTEGER_TEXT_IO", "boINTEGER_TEXT_IO", 
		"spFLOAT_TEXT_IO", "boFLOAT_TEXT_IO"
#endif
	};

	/* Set values for unit_names, file_number and PRECEDES information for
	 * predefined compilation units, since they do not appear in any library
	 */
	/* allocate unit names - recalling it is ones origin */
#ifdef PREDEF_PC
	unit_count = 37;
#else 
	unit_count = 14;
#endif
	unit_names = (char **) emalloct((unit_count + 1) * sizeof(char *),
	  "unit_names");
	PRECEDES_MAP = (int **) emalloct(sizeof(char **) *(unit_count + 1),
	  "precedes_map");
	PRECEDES_MAP[0] =  (int *) unit_count;
	file_number = (char **) emalloct(sizeof(char **) *(unit_count + 1),
	  "file_number");
	for (i = 1; i <= unit_count; i++) {
		unit_names[i] = predef_units[i - 1];
		file_number[i] = "0";
		PRECEDES_MAP[i] = unit_list_new();
	}
}

void load_lib(char *filename, IFILE *libfile, Axq axq, char *main_unit,
  char **argv)													/*;load_lib*/
{
	/* This procedure looks for the main unit
	 * and loads it, together with all units on which it depends directly
	 * or indirectly. Dependences are taken from map precedes.
	 */

	struct axq_loaded  *ll_new;
	int   *main_units, *bound_units, *new_main_units, *to_read, *precedes;
	int	   unitn;
	int     i, name, pi;
	int     is_predef_unit;
	int     nmain_units;
	char   *idle_task_name, *unit_file;
	IFILE * axqfile;
	char    exename[100];
	char   *PREDEFNAME;
	char   *file_name, *l_name, *t_name;
#ifdef vms
	struct      dsc$descriptor_s string_desc;
#endif

	ll_head = (struct axq_loaded   *) 0; /* Initially, no files loaded */
	init_library(libfile,main_unit);
	main_units = unit_list_new();
	bound_units = unit_list_new();
	for (i = 1; i <= unit_count; i++) {
		if (streq(unit_name_type(unit_names[i]), "ma"))
			main_units[i] = YES;
	}
	if (main_unit != (char *) 0) {
		/* main_units := {[x,y]: [x,y] in main_units 
    	 *		| y = '_'+MAINUNIT+'_idle_task'}; 
    	 */
		idle_task_name = strjoin(main_unit, "_idle_task");
		for (name = 1; name <= unit_count; name++) {
			if (main_units[name] == NO)
				continue;
			if (streq(idle_task_name, unit_names[name]+2))
				bound_units[name] = YES;
		}
		unit_list_copy(main_units, bound_units);
	}
	nmain_units = 0;
	for (i = 1; i <= main_units[0]; i++)
		if (main_units[i]) nmain_units++;
	if (nmain_units == 0) {
#ifdef vms
		LIB$SIGNAL(MSG_NOTBOUND);
		exit();
#else
		printf("*** Unbound library, execution not allowed\n");
		exit(RC_ERRORS);
#endif
	}
	else if (nmain_units > 1) {
#ifdef vms
		LIB$SIGNAL(MSG_MANYMAIN);
		LIB$SIGNAL(MSG_SPECIFY);
		for (name = 1; name <= unit_count; name++) {
			if (main_units[name] == NO)
				continue;
			/* name of the form _xxx_idle_task, print only xxx */
			unit_names[name][strlen(unit_names[name])-10] = '\0';
			string_desc.dsc$w_length = strlen(unit_names[name]+2);
			string_desc.dsc$b_dtype = DSC$K_DTYPE_T;
			string_desc.dsc$b_class = DSC$K_CLASS_S;
			string_desc.dsc$a_pointer = unit_names[name]+2;
			LIB$SIGNAL(MSG_MAIN,1,&string_desc);
		}
		exit();
#else
		printf("*** More than one main program in library\n");
		printf("    Use option: -m(one of the following)\n");
		for (name = 1; name <= unit_count; name++) {
			if (main_units[name] == NO)
				continue;
			unit_names[name][strlen(unit_names[name])-10] = '\0';
			/* name of the form _xxx_idle_task, print only xxx */
			printf("    %s\n", unit_names[name]+2);
		}
		exit(RC_ERRORS);
#endif
	}
	else {
#ifndef INTERFACE
#ifdef SUPPORT_PRAGMA_INTERFACE
		/* at this point, if the main binding unit is interfaced, we run
         * the executable which has been built with the procedure interface
         */
		if (interfaced_unit != 0) {
			sprintf(exename,"%s%s%s.exe",filename,DIR_DELIMITER,
			  file_number[interfaced_unit]);
			execvp(exename,argv);
		}
#endif
#endif
		if (obsolete_error) {
			printf(
			  "*** Main binding unit obsolete, please recompile or rebind \n");
			exit(RC_ERRORS);
		}
		to_read = unit_list_new();
		while(unit_list_next(main_units)) {
			for (name = 1; name <= unit_count; name++) {
				if (main_units[name] == NO)
					continue;
				to_read[name] = YES;
			}
			/* main_units := {} +/{ precedes{u} : u in main_units}; */
			new_main_units = unit_list_new();
			/* for name in main_units */
			for (name = 1; name <= unit_count; name++) {
				if (main_units[name] == NO)
					continue;
				precedes = PRECEDES_MAP[name];
				for (pi = 1; pi <= unit_count; pi++) {
					if (precedes[pi] == NO)
						continue;
					new_main_units[pi] = YES;
				}
			}
			unit_list_copy(main_units, new_main_units);
		}
		while((unitn = unit_list_next(to_read))) {
			to_read[unitn]  = NO;		/* remove from set */
			if (unitn == 0) {
				/* junk unit number - binder shouldn't be putting this out */
				printf("load.c: skipping 0 case\n");
				continue;
			}
			if (unitn <= unit_count	/* false if "ghost package body" */
			&&(!in_loaded(file_number[unitn]))) {
				unit_file = (char *) file_number[unitn];
				file_name = unit_file;
				is_predef_unit =  streq(unit_file,"0");
				if (is_predef_unit) {
					PREDEFNAME = predef_env();
					l_name = libset(PREDEFNAME); /* use predef library */
					file_name = "predef";
				}
				axqfile = ifopen(file_name, "axq", "r", "a", iot_ais_r, 0);
				read_axq(axqfile, axq);
				ifclose(axqfile);
				if (is_predef_unit)
					t_name = libset(l_name); /* restore user library */
				if (!in_loaded(unit_file))
					ll_new = (struct axq_loaded *)
					  smalloc(sizeof(struct axq_loaded));
				ll_new->loaded_next = ll_head;
				ll_new->loaded_name = unit_file;
				ll_head = ll_new;
			}
		}			/* while */
	}
}

static void init_library(IFILE *ifile, char *main_unit)		/*;init_library*/
{
	/*
	 * retrieve information from ifile
	 */

	int     i, j, n, m, unumber,cur_level;
	int	    ignore;
	int     punit;
	char   *uname, *aisname;
	int    *precedes;
	char   *main_binding_unit = (char *)0;
	int    units_lib;
	int    is_interfaced,comp_status;

	init_predef();
	ll_head = (struct axq_loaded   *) 0;
	if (ifile == (IFILE *) 0) {
#ifdef vms
		LIB$SIGNAL(MSG_LIBRARY);
		exit();
#else
		printf("*** library is empty\n");
		exit(RC_ERRORS);
#endif
	}
	units_lib = getnum(ifile, "lib-unit-count");
	unit_count = getnum(ifile, "lib-unit_num");
	getnum(ifile, "lib-empty-slots"); /* ignore */
	getstr(ifile, "lib-tmp-str");     /* ignore */
	unit_names = (char **) erealloct((char *)unit_names,
	  (unit_count+1) * sizeof(char **), "unit_names-re");

	file_number = (char **) erealloct((char *)file_number,
	    sizeof(char **) *(unit_count+1),"file_number-re");
#ifndef INTERFACE
	if (main_unit != (char *)0) {
		/* a main unit was specified */
		main_binding_unit = strjoin("ma",main_unit);
		main_binding_unit = strjoin(main_binding_unit,"_idle_task");
	}
#endif
	for (i = 1; i <= units_lib; i++) {
		uname = getstr(ifile, "lib-unit-name");
		unumber = getnum(ifile, "lib-unit-number");
		aisname = getstr(ifile, "lib-ais-name");
		getstr(ifile, "comp-date");   /* ignore */
		getnum(ifile, "lib-symbols"); /* ignore */
		getnum(ifile, "lib-nodes");   /* ignore */
		is_interfaced = getnum(ifile, "lib-is-main");
#ifdef SUPPORT_PRAGMA_INTERFACE
#ifndef INTERFACE
		if (main_binding_unit != (char *) 0) {
			/* check is_main (interfaced flag) only for binding unit 
			 * corresponding to specified main unit
			 */
			if (streq(uname,main_binding_unit) && is_interfaced)
				interfaced_unit = unumber;
		}
		else {
			/* look at is_main (interfaced flag) for any main binding unit.
			 * if there is more that one of these, we will report an error
			 * later !!
			 */
			if (streq(unit_name_type(uname),"ma") && is_interfaced)
				interfaced_unit = unumber;
		}
#endif
#endif
		comp_status = getnum(ifile, "lib-status");
		/* verify that main binding unit status is not obsolete */
		/* ignore this field for all other units */
		if (main_binding_unit != (char *) 0) {
			/* check comp_status only for specified main binding unit */
			if (streq(uname,main_binding_unit) && !comp_status)
				obsolete_error = TRUE;
		}
		else {
			/* if none specified, check for any main binding unit */
			if (streq(unit_name_type(uname),"ma") && !comp_status)
				obsolete_error = TRUE;
		}
		unit_names[unumber] = strjoin(uname, "");
		file_number[unumber] = strjoin(aisname, "");
	}
	/* read but ignore stub info */
	n = getnum(ifile, "lib-n");
	for (i = 1; i <= n; i++) {
		uname = getstr(ifile, "lib-unit-name");
		aisname = getstr(ifile, "lib-ais-name");
		ignore = getnum(ifile, "lib-parent");
		cur_level = getnum(ifile, "lib-cur_level");
		m = getnum(ifile, "stub-file-size");
		for (j = 1; j <= m; j++)
			ignore = getnum(ifile, "stub-file");
	}

	PRECEDES_MAP = (int **) emalloct(sizeof(char **) *(unit_count + 1),
	  "precedes_map");
	for (i = 1; i <= unit_count; i++)
		PRECEDES_MAP[i] = unit_list_new();
	n = getnum(ifile, "precedes-map-size");
	for (i = 1; i <= n; i += 2) {
		unumber = getnum(ifile, "precedes-map-ent");
		m = getnum(ifile, "precedes-map-set-size");
		precedes = unit_list_new();
		for (j = 1; j <= m; j++) {
			punit = getnum(ifile, "precedes-map-ent");
			precedes[punit] = YES;
		}
		if (unumber==0) chaos("unit number zero");
		PRECEDES_MAP[unumber] = precedes;
	}
	return;
}

static char *unit_name_name(char *u)						/*;unit_name_name*/
{
	int     n;
	char   *s1, *s2;

	n = strlen(u);
	if (n <= 2)
		return (char *) 0;

	s1 = u + 2;			/* point to start of name */
	s2 = strchr(s1, '.');	/* look for dot after first name */
	if (s2 == (char *) 0)	/* if no dot take rest of string */
		s2 = u + n;		/* find end */
	n = s2 - s1;
	s2 = smalloc((unsigned) n + 1);
	strncpy(s2, s1, n);
	s2[n] = '\0';		/* terminate result */
	return (s2);
}

long load_slots(char *fname, IFILE **ifile, Axq axq)			/*;load_slots*/
{
	IFILE  *AXQFILE;
	Slot slot;
	int     i;
	long    cde_pos;

	AXQFILE = ifopen(LIBFILENAME, "", "r", "l", iot_lib_r, 0);
	cde_pos = get_cde_slots(AXQFILE, axq);
	*ifile = AXQFILE;		/* store file pointer */

	code_slots_dim = axq->axq_code_segments_dim;
	data_slots_dim = axq->axq_data_segments_dim;
	exception_slots_dim = axq->axq_exception_slots_dim;
	code_slots = (char **) ecalloct(code_slots_dim, sizeof(char *),
	  "code_slots");
	data_slots = (char **) ecalloct(data_slots_dim, sizeof(char *),
	  "data_slots");
	exception_slots = (char **) ecalloct(exception_slots_dim, sizeof(char *),
	  "exception_slots");
	/* now get names from list and put in proper place */
	for (i = 1; i < axq->axq_code_slots_dim; i++) {
		slot = axq->axq_code_slots[i];
		if (slot == (Slot) 0)
			continue;
		if (slot->slot_number == 0)
			continue;
		code_slots[slot->slot_number] = slot->slot_name;
	}
	for (i = 1; i < axq->axq_data_slots_dim; i++) {
		slot = axq->axq_data_slots[i];
		if (slot == (Slot) 0)
			continue;
		if (slot->slot_number == 0)
			continue;
		data_slots[slot->slot_number] = slot->slot_name;
	}
	for (i = 1; i < axq->axq_exception_slots_dim; i++) {
		slot = axq->axq_exception_slots[i];
		if (slot == (Slot) 0)
			continue;
		if (slot->slot_number == 0)
			continue;
		exception_slots[slot->slot_number] = slot->slot_name;
	}
	code_segments_dim = axq->axq_code_segments_dim;
	code_segments = (char **) ecalloct(axq->axq_code_segments_dim, 
	  sizeof(char *),"code_segments");
	code_seglen = (int *) ecalloct(axq->axq_code_segments_dim, sizeof(int),
	  "code_seglen");
	axq->axq_code_segments = code_segments;
	axq->axq_code_seglen = code_seglen;
	data_segments_dim = axq->axq_data_segments_dim;
	data_segments = (int **) ecalloct(axq->axq_data_segments_dim, 
	  sizeof(char *),"data_segments");
	data_seglen = (int *) ecalloct(axq->axq_data_segments_dim, sizeof(int),
	  "data_seglen");
	axq->axq_data_segments = data_segments;
	axq->axq_data_seglen = data_seglen;

	if ((*ifile)->fh_trace) {
		for (i = 1; i < axq->axq_code_segments_dim; i++)
			printf("code_segment %2d length %8d\n",i,code_seglen[i]);
		for (i = 1; i < axq->axq_data_segments_dim; i++)
			printf("data_segment %2d length %8d\n",i,data_seglen[i]);
	}
	return cde_pos;
}

static int *unit_list_new() 								/*;unit_list_new*/
{
	int    *u;

	u = (int *) smalloc(sizeof(int) * (unit_count + 1));
	u[0] = unit_count;
	for (i = 1; i <= unit_count; i++)
		u[i] = NO;
	return u;
}

static void unit_list_copy(int *u1, int *u2) 			/*;unit_list_copy*/
{
	int n,i;

	n = u1[0];
	if (n != u2[0])
		chaos("unit_copy sizes differ");
	for (i = 1; i <= n; i++)
		u1[i] = u2[i];
}

static int unit_list_next(int *u1)						/*;unit_list_next*/
{
	int i,n;

	n = u1[0];
	for (i = 1; i <= n; i++)
		if (u1[i]) return i;
	return 0;
}

static int in_loaded(char *str)								/*;in_loaded*/
{
	/* test to see if named file has been loaded */
	struct axq_loaded  *p;

	for (p = ll_head; p != (struct axq_loaded  *) 0; p = p->loaded_next)
		if (streq(str, p->loaded_name))
			return TRUE;

	return FALSE;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.