/*
* The routines here generate legal Ada identifiers from
* C identifiers. All the klugy unique name munging is
* done here as well
*/
#include <sys/types.h>
#include "ansi.h"
#include "config.h"
#include "host.h"
#include "allocate.h"
#include "ada_name.h"
#include "hash.h"
#include "files.h"
#include "il.h"
extern int auto_package;
#undef NULL
#define NULL 0
#define HTAB 512 /* unique name hash table size */
/*
* Unique name hash table node type
*/
typedef struct uniq_name_t {
char *uname;
int uord;
hash_t uhash;
struct uniq_name_t *ulink;
} uniq_name_t;
static uniq_name_t *hash_table[HTAB];
/*
* allocator for unique name hash table nodes
*/
static uniq_name_t*
new_uniq_name()
{
static uniq_name_t *free = NULL;
static int free_index;
if (free == NULL || free_index > 63) {
free = (uniq_name_t*) allocate(sizeof(uniq_name_t) * 64);
free_index = 0;
}
return &free[free_index++];
}
/*
* Function to determine if a name is an Ada83 keyword
*/
int
is_ada_keyword(name)
char *name;
{
#ifdef PUBLIC
struct resword {char *name; short token;};
extern struct resword *ada_rsvd();
struct resword *r;
#endif
char buf[16];
char *p;
assert(name != NULL);
if (strlen(name) > 9) {
return 0;
}
for (p = buf; *name; name++) {
*p++ = lcase(*name);
}
*p = 0;
#ifdef PUBLIC
return ada_rsvd(buf, p-buf) != NULL;
#else
return ada_rsvd(buf) != -1;
#endif
}
/*
* Function to generate a legal Ada83 identifier
*/
void
make_ada_identifier(name, buf)
char *name, *buf;
{
assert(name != NULL);
assert(buf != NULL);
while (*name == '_' || *name == '$') {
name++;
}
if (*name == 0) {
strcpy(buf, "YIKES");
}
while (*name) {
switch (*name) {
case '$':
name++;
break;
case '_':
if (name[1] != '_' && name[1] != 0) {
*buf++ = *name;
}
name++;
break;
default:
*buf++ = *name++;
break;
}
}
*buf = 0;
}
/*
* Function to determine if an identifier has already
* been used.
*/
static uniq_name_t*
find_uniq(name, unit)
char *name;
int unit;
{
uniq_name_t *un;
hash_t hash;
int index;
hash = lcase_hash(name);
index = hash & (HTAB-1);
if (!auto_package) {
unit = 0;
}
for (un = hash_table[index]; un; un = un->ulink) {
if (un->uord == unit && un->uhash == hash && !lcasecmp(un->uname, name)) {
return un;
}
}
return NULL;
}
int
is_uniq_name(name, unit)
char *name;
int unit;
{
assert(name != NULL);
return find_uniq(name,unit) == NULL;
}
char*
uniq_name(name, unit)
char *name;
int unit;
{
char buf[2048];
uniq_name_t *un;
int index, i, j, k;
int last;
strcpy(buf, name);
if (find_uniq(name, unit) == NULL) {
goto done;
}
strcat(buf, "_c");
last = strlen(buf);
buf[last+1] = 0;
for (i = '0'; i <= '9'; i++) {
buf[last] = i;
if (find_uniq(buf) == NULL) {
goto done;
}
}
buf[last+2] = 0;
for (i = '0'; i <= '9'; i++) {
buf[last] = i;
for (j = '0'; j <= '9'; j++) {
buf[last+1] = j;
if (find_uniq(buf) == NULL) {
goto done;
}
}
}
buf[last+3] = 0;
for (i = '0'; i <= '9'; i++) {
buf[last] = i;
for (j = '0'; j <= '9'; j++) {
buf[last+1] = j;
for (k = '0'; k <= '9'; k++) {
buf[last+2] = k;
if (find_uniq(buf) == NULL) {
goto done;
}
}
}
}
assert(0);
done:
un = new_uniq_name();
un->uname = new_string(buf);
un->uhash = common_hash(buf);
un->uord = (auto_package) ? unit : 0;
index = un->uhash & (HTAB-1);
un->ulink = hash_table[index];
hash_table[index] = un;
return un->uname;
}
/*
* I do a half-hearted attempt at preserving the case
* of the original C identifier. This is done so that
* SIGINT doesn't turn into sigint.
*/
ident_case_t
id_case(id)
char *id;
{
if (id[0] >= 'A' && id[0] <= 'Z') {
if (id[1] >= 'A' && id[1] <= 'Z') {
return Upper;
}
return Cap;
}
return Lower;
}
static void
uppercase(id)
char *id;
{
char c;
for (; *id; id++) {
c = *id;
if (c >= 'a' && c <= 'z') {
*id = 'A' + (c - 'a');
}
}
}
static void
capitalize(id)
char *id;
{
char *prev;
char c;
for (prev = id; *id; id++) {
if (*id == '_') {
c = *prev;
if (c >= 'a' && c <= 'z') {
*prev = 'A' + (c - 'a');
}
prev = id + 1;
}
}
}
void
id_format(id, icase)
char *id;
ident_case_t icase;
{
switch (icase) {
case Upper:
uppercase(id);
break;
case Cap:
capitalize(id);
break;
}
}
char*
ada_name(name, unit)
char *name;
int unit;
{
char buf[2048];
char *p;
ident_case_t icase;
for (; *name == '_'; name++);
if (*name == 0) {
name = "YIKES";
}
if (is_ada_keyword(name)) {
icase = id_case(name);
strcpy(buf, ADA_RESERVED_PREFIX);
strcat(buf, name);
}
else {
switch (name[0]) {
case ENUM_PREFIX:
strcpy(buf, ENUM_TYPE_PREFIX);
name++;
break;
case STRUCT_PREFIX:
strcpy(buf, STRUCT_TYPE_PREFIX);
name++;
break;
case UNION_PREFIX:
strcpy(buf, UNION_TYPE_PREFIX);
name++;
break;
default:
buf[0] = 0;
break;
}
icase = id_case(name);
for (p = buf; *p; p++);
make_ada_identifier(name, p);
}
if (unit == -1) {
p = new_string(buf);
}
else {
p = uniq_name(buf, unit);
}
id_format(p, icase);
return p;
}
syntax highlighted by Code2HTML, v. 0.9.1