#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include "host.h"
#include "ansi.h"
#include "files.h"
#include "units.h"
#include "allocate.h"
#include "vendor.h"
#include "config.h"
extern int auto_package;
#undef NULL
#define NULL 0
/* from limits.h */
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#ifndef MAX_NEST
#define MAX_NEST 64 /* Arbitrary limit */
#endif
FILE *cur_unit_fd;
static ada_unit_t *table[MAX_UNIQ_FNAMES];
static int cur_unit;
static int nesting_table[MAX_NEST];
static int nest_level;
int
current_unit()
{
if (! auto_package) return 0;
assert(cur_unit < num_files());
return cur_unit;
}
static void
set_reference(ref, ord)
unit_ref_t ref;
int ord;
{
int index;
int bit;
index = ord / BITS_PER_INT;
assert(index < UNIT_SET_SIZE);
bit = 1 << (ord % BITS_PER_INT);
ref[index] |= bit;
}
static void
clear_reference(ref, ord)
unit_ref_t ref;
int ord;
{
int index;
int bit;
index = ord / BITS_PER_INT;
assert(index < UNIT_SET_SIZE);
bit = 1 << (ord % BITS_PER_INT);
ref[index] &= ~bit;
}
static int
is_referenced(ref, ord)
unit_ref_t ref;
int ord;
{
int index;
int bit;
index = ord / BITS_PER_INT;
assert(index < UNIT_SET_SIZE);
bit = 1 << (ord % BITS_PER_INT);
return (ref[index] & bit) != 0;
}
static void
ref_merge(r1, r2)
unit_ref_t r1, r2;
{
int i;
for (i = 0; i < UNIT_SET_SIZE; i++) {
r1[i] |= r2[i];
}
}
static void
merge_direct_refs()
{
ada_unit_t *unit, *ref;
int last, i, j;
if (! auto_package) return;
last = num_files();
for (i = 0; i < last; i++) {
unit = table[i];
assert(unit != NULL);
for (j = 0; j < last; j++) {
if (j != i && is_referenced(unit->direct_ref, j)) {
ref = table[j];
assert(ref != NULL);
ref_merge(unit->direct_ref, ref->direct_ref);
}
}
/* Don't let unit "i" reference itself */
clear_reference(unit->direct_ref, i);
clear_reference(unit->unit_ref, i);
}
}
static void
merge_refs()
{
ada_unit_t *unit, *ref;
int last, i, j;
if (! auto_package) return;
last = num_files();
for (i = 0; i < last; i++) {
unit = table[i];
assert(unit != NULL);
for (j = 0; j < last; j++) {
if (j != i && is_referenced(unit->unit_ref, j)) {
ref = table[j];
assert(ref != NULL);
ref_merge(unit->unit_ref, ref->unit_ref);
}
}
/* Don't let unit "i" reference itself */
clear_reference(unit->direct_ref, i);
clear_reference(unit->unit_ref, i);
}
}
void
unit_start_gen()
{
cur_unit_fd = stdout;
#if 0
merge_direct_refs();
#else
merge_refs();
#endif
}
static char*
gen_unit_name(path)
char *path;
{
char buf[PATH_MAX];
char res[PATH_MAX];
char *p;
if (!strncmp(path, "/usr/include/", 13)) {
p = buf;
path = &path[13];
}
else {
char *last = path;
char *s;
for (s = path; *s; s++) {
if (*s == '/') {
last = s;
}
}
path = last;
p = buf;
}
for (; *path; path++) {
switch (*path) {
case '.':
#ifdef HEADER_POSTFIX
if (path[1] == 'h' && path[2] == 0) {
strcpy(p, HEADER_POSTFIX);
path++;
break;
}
#endif
case '/':
*p++ = '_';
break;
default:
*p++ = *path;
break;
}
}
*p = 0;
make_ada_identifier(buf, res);
return new_string(res);
}
static void
initialize_unit(ord)
int ord;
{
char buf[PATH_MAX];
ada_unit_t *unit;
assert(table[ord] == NULL);
unit = allocate(sizeof(ada_unit_t));
unit->src_path = file_name_from_ord(ord);
assert(unit->src_path != NULL);
unit->unit_name = gen_unit_name(unit->src_path);
assert(unit->unit_name != NULL);
strcpy(buf, "bindings/");
strcat(buf, unit->unit_name);
switch (ada_compiler) {
case GNAT:
strcat(buf, ".ads");
break;
case VADS:
strcat(buf, ".a");
break;
case Rational:
strcat(buf, ".1.ada");
break;
default:
strcat(buf, ".ada");
break;
}
unit->unit_path = new_string(buf);
unit->initialized = 1;
table[ord] = unit;
}
static void
dump_unit(ord)
int ord;
{
ada_unit_t *unit;
unit = table[ord];
assert(unit != NULL);
printf("unit %d\n", ord);
printf("\tsrc = %s\n", unit->src_path);
printf("\tname = %s\n", unit->unit_name);
printf("\tpath = %s\n", unit->unit_path);
fflush(stdout);
}
void
unit_included(pos, nest)
file_pos_t pos;
int nest;
{
ada_unit_t *unit;
int ord;
int uord;
if (! auto_package) return;
if (nest < 1) return;
if (nest >= MAX_NEST) return;
ord = FILE_ORD(pos);
if (nest > nest_level) {
uord = nesting_table[nest_level];
unit = table[uord];
assert(unit != NULL);
set_reference(unit->direct_ref, ord);
set_reference(unit->unit_ref, ord);
}
nest_level = nest;
nesting_table[nest] = ord;
}
void
init_unit(pos)
file_pos_t pos;
{
int ord;
if (! auto_package) return;
ord = FILE_ORD(pos);
if (table[ord] == NULL) {
initialize_unit(ord);
}
}
int
set_unit(ord)
int ord;
{
ada_unit_t *unit;
if (! auto_package) return 0;
assert(ord < num_files());
unit = table[ord];
assert(unit != NULL);
mkdir("bindings", 0777);
cur_unit = ord;
cur_unit_fd = fopen(unit->unit_path, "w");
if (cur_unit_fd == NULL) {
syserr(unit->unit_path, 0);
return 1;
}
inform(0, 0, "Generating %s", unit->unit_path);
return 0;
}
void
unit_completed()
{
if (auto_package) {
fclose(cur_unit_fd);
cur_unit = MAX_UNIQ_FNAMES + 1;
}
}
void
unit_dependency(ord, dep)
int ord, dep;
{
ada_unit_t *unit;
int last;
if (! auto_package) return;
last = num_files();
assert(ord >= 0 && ord < last);
assert(dep >= 0 && dep < last);
unit = table[ord];
assert(unit != NULL);
set_reference(unit->unit_ref, dep);
}
char*
unit_name(ord)
int ord;
{
ada_unit_t *unit;
if (! auto_package) return "y";
assert(ord < num_files());
unit = table[ord];
assert(unit != NULL);
assert(unit->unit_name != NULL);
return unit->unit_name;
}
char*
include_path(ord)
int ord;
{
ada_unit_t *unit;
if (! auto_package) return NULL;
assert(ord < num_files());
unit = table[ord];
assert(unit != NULL);
assert(unit->src_path != NULL);
return unit->src_path;
}
char*
cur_unit_name()
{
return unit_name(current_unit());
}
char*
cur_unit_source()
{
ada_unit_t *unit;
int ord;
if (! auto_package) return NULL;
ord = current_unit();
assert(ord < num_files());
unit = table[ord];
assert(unit != NULL);
assert(unit->src_path != NULL);
return unit->src_path;
}
char*
cur_unit_path()
{
ada_unit_t *unit;
int ord;
if (! auto_package) return NULL;
ord = current_unit();
assert(ord < num_files());
unit = table[ord];
assert(unit != NULL);
assert(unit->unit_path != NULL);
return unit->unit_path;
}
int
nth_ref_unit_ord(n)
int n;
{
ada_unit_t *unit;
int count, i, last;
if (auto_package) {
unit = table[current_unit()];
assert(unit != NULL);
last = num_files();
for (count = 0, i = 0; i < last; i++) {
if (is_referenced(unit->unit_ref, i)) {
if (count == n) {
return i;
}
count++;
}
}
}
return -1;
}
int
nth_direct_ref_unit_ord(n)
int n;
{
ada_unit_t *unit;
int count, i, last;
int cur;
if (auto_package) {
cur = current_unit();
unit = table[cur];
assert(unit != NULL);
last = num_files();
for (count = 0, i = 0; i < last; i++) {
if (cur != i && is_referenced(unit->direct_ref, i)) {
if (count == n) {
return i;
}
count++;
}
}
}
return -1;
}
syntax highlighted by Code2HTML, v. 0.9.1