mac-rom/Tools/ToolSource/MPWObjFuncs.c
2017-12-26 09:52:24 +08:00

696 lines
12 KiB
C

#define C_PAD 0
#define C_FIRST 1
#define C_LAST 2
#define C_COMMENT 3
#define C_DICT 4
#define C_MODULE 5
#define C_ENTRYPT 6
#define C_SIZE 7
#define C_CONTENTS 8
#define C_REF 9
#define C_COMPREF 10
/* DATA STRUCTURES */
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef unsigned short id;
/* Ugh! */
#ifndef __GNUC__
#define ntohs
#define ntohl
#define htons
#define htonl
#endif
#define NULL 0
ushort shortfrom(char *b)
{
return ntohs(*(ushort *)b);
}
void setshort(char *b, ushort to)
{
*(ushort *)b = htons(to);
}
ulong longfrom(char *b)
{
return ntohl(*(ulong *)b);
}
void setlong(char *b, ulong to)
{
*(ulong *)b = htonl(to);
}
/* Wraps an MPW Object buffer */
struct obj
{
char *buf, *at;
id next_id;
};
/* PASCAL STRING COMPARISON, CASE-INSENSITIVE */
int cisc(uchar *a, uchar *b)
{
int i;
if(*a != *b) return 0;
for(i=1; i<=*a; i++)
{
uchar c, d;
c = a[i];
d = b[i];
// if(c >= 'a' && c <= 'z') c &= 223;
// if(d >= 'a' && d <= 'z') d &= 223;
if(c == d) continue;
return 0;
}
return 1;
}
void upperpas(uchar *a)
{
int i;
for(i=1; i<=*a; i++)
{
if(a[i] >= 'a' && a[i] <= 'z') a[i] &= 223;
}
}
/* ACCESSOR FUNCTIONS */
/* Valid for all types */
char obj_type(struct obj *o)
{
return o->at[0];
}
/* Valid for First, Dict, Module, EntryPt, Size, Contents, Ref, CompRef */
char obj_flags(struct obj *o)
{
return o->at[1];
}
/* Valid for Module, EntryPt */
id obj_id(struct obj *o)
{
return ntohs(*(id *)(o->at + 2));
}
/* Valid for Dict */
id obj_dictfirst(struct obj *o)
{
return ntohs(*(id *)(o->at + 4));
}
/* Valid for Comment, Dict, Contents, Ref, CompRef */
unsigned short obj_recsize(struct obj *o)
{
return ntohs(*(unsigned short *)(o->at + 2));
}
/* Valid for Size */
unsigned short obj_contsize(struct obj *o)
{
return ntohs(*(unsigned long *)(o->at + 2));
}
/* Valid for all types */
unsigned long obj_size(struct obj *o)
{
char t;
t = obj_type(o);
if(t == C_COMMENT || t == C_DICT || t == C_CONTENTS || t == C_REF || t == C_COMPREF)
{
return obj_recsize(o);
}
else if(t == C_PAD)
{
return 1;
}
else if(t == C_FIRST)
{
return 4;
}
else if(t == C_MODULE)
{
return 6;
}
else if(t == C_ENTRYPT)
{
return 8;
}
else if(t == C_SIZE)
{
return 6;
}
else if(t == C_LAST)
{
return 2;
}
else
{
printf("Illegal object type at offset 0x%x: %d\n", (ulong)o->at - (ulong)o->buf, t);
return 1;
}
}
/* CURSOR MANIPULATOR FUNCTIONS */
void obj_init(struct obj *o, char *buf)
{
o->at = o->buf = buf;
}
void _obj_next_general(struct obj *o, int can_loop)
{
if((long)o->at & 1) o->at ++;
if(obj_type(o) == C_LAST)
{
//printf("Got a lastie\n");
if(can_loop) o->at = o->buf;
}
else
{
//printf("Got a %d %d\n", obj_type(o), obj_size(o));
o->at += obj_size(o);
}
if((long)o->at & 1) o->at ++;
}
/* Gets the next object without looping */
void obj_next(struct obj *o)
{
_obj_next_general(o, 0);
}
/* Gets the specified module with looping */
void obj_findmod(struct obj *o, id mod_id)
{
char *first;
first = o->at;
while(obj_type(o) != C_MODULE || obj_id(o) != mod_id)
{
_obj_next_general(o, 1);
if(o->at == first)
{
o->at = o->buf;
}
}
}
/* Gets the next dict with looping */
void dict_next(struct obj *o)
{
do
{
printf("xx %d\n", obj_type(o));
_obj_next_general(o, 1);
}
while(obj_type(o) != C_DICT);
}
void obj_pad(struct obj *o)
{
if((long)o->at & 1) *o->at++ = 0;
}
int obj_nextinmod(struct obj *o)
{
char *at = o->at;
if(obj_type(o) == C_LAST) return 0;
_obj_next_general(o, 0);
if(obj_type(o) == C_LAST || obj_type(o) == C_MODULE)
{
return 0;
o->at = at;
}
return 1;
}
int obj_nextmod(struct obj *o)
{
char *at = o->at;
if(obj_type(o) == C_LAST) return 0;
do
{
_obj_next_general(o, 0);
if(obj_type(o) == C_LAST) return 0;
} while(obj_type(o) != C_MODULE);
return 1;
}
/* DICT APPEND FUNCTION */
void dict_append_v(struct obj *o, uchar *s, id hint_id)
{
ushort oldlen;
if(obj_type(o) != C_DICT || shortfrom(o->at + 2) > 10000)
{
obj_next(o);
o->at[0] = C_DICT;
o->at[1] = 0; /* flags */
setshort(o->at+2, 6); /* size */
setshort(o->at+4, hint_id); /* first id */
}
oldlen = shortfrom(o->at + 2);
o->at[oldlen+0] = *s + 5;
o->at[oldlen+1] = '_';
o->at[oldlen+2] = '_';
o->at[oldlen+3] = 'v';
o->at[oldlen+4] = '_';
o->at[oldlen+5] = '_';
memcpy(o->at + oldlen + 6, s + 1, *s);
setshort(o->at + 2, oldlen + *s + 6);
}
/* DICT SEARCH FUNCTIONS, WHICH HAVE SIDE EFFECTS */
id dict_id_from_str(struct obj *o, unsigned char *str)
{
char *first_searched = NULL;
//printf("DICT %x: %.*s = \n", o, *str, str+1);
for(;;)
{
if(obj_type(o) == C_DICT)
{
unsigned int ctr, tlen;
unsigned char *ptr;
tlen = ntohs(*(unsigned short *)(o->at + 2));
ctr = ntohs(*(unsigned short *)(o->at + 4));
ptr = (uchar *)((long)o->at + 6);
do
{
//if(ptr[0] == str[0] && !memcmp(ptr+1, str+1, str[0]))
if(cisc(ptr, str))
{
//printf("%d\n", ctr);
return ctr;
}
ptr += ptr[0] + 1;
ctr++;
} while((ulong)ptr < (ulong)o->at + tlen);
}
_obj_next_general(o, 1);
if(o->at == first_searched) return 0;
if(!first_searched) first_searched = o->at;
}
//printf("(not found)\n");
return 0;
}
uchar *dict_str_from_id(struct obj *o, id id)
{
char *first_searched = NULL;
//printf("DICT %x: %d = ", o, id);
for(;;)
{
if(obj_type(o) == C_DICT)
{
unsigned int ctr, tlen;
unsigned char *ptr;
tlen = ntohs(*(unsigned short *)(o->at + 2));
ctr = ntohs(*(unsigned short *)(o->at + 4));
ptr = (uchar *)((long)o->at + 6);
if(ctr <= id)
{
do
{
if(ctr == id)
{
//printf("%.*s\n", *ptr, ptr+1);
return ptr;
}
ptr += ptr[0] + 1;
ctr++;
} while((ulong)ptr < (ulong)o->at + tlen);
}
}
_obj_next_general(o, 1);
if(o->at == first_searched) return 0;
if(!first_searched) first_searched = o->at;
}
//printf("(not found)\n");
return NULL;
}
id dict_highestid(struct obj *o)
{
id ctr;
unsigned int tlen;
unsigned char *ptr;
tlen = ntohs(*(unsigned short *)(o->at + 2));
ctr = (id)ntohs(*(unsigned short *)(o->at + 4));
ptr = (uchar *)((long)o->at + 6);
do
{
ptr += ptr[0] + 1;
ctr++;
} while((ulong)ptr < (ulong)o->at + tlen);
return ctr - 1;
}
/* NEWDICT FUNCTIONS */
struct newdict
{
struct newdict *prev, *next; /* linked list */
id new_id; /* increments from 256 */
id old_id;
id patch_id; /* if this ID is just vector glue and self.next is the implementation */
uchar name[256]; /* duh */
int defining_file;
int malloc_size; /* only for the main dict object */
int fcnt;
struct newdict ***cache;
//id id_in_file[99]; /* malloc makes this array *just right* */
};
void newdict_init(struct newdict *d, int file_count)
{
d->prev = d->next = d;
d->new_id = 255;
d->fcnt = file_count;
d->malloc_size = sizeof *d; //sizeof(*d) + (file_count - 99) * sizeof(d->id_in_file[0]);
}
void newdict_cache(struct newdict *d)
{
int i;
struct newdict *s;
d->cache = (struct newdict ***)calloc(d->fcnt, sizeof d->cache[0]);
for(i=0; i<d->fcnt; i++)
{
d->cache[i] = (struct newdict **)calloc(65536, sizeof d->cache[0][0]);
}
for(s = d->next; s != d; s = s->next)
{
d->cache[s->defining_file][s->old_id] = s;
}
}
id newdict_append(struct newdict *d, int file_idx, id orig_id, uchar *name)
{
struct newdict *s;
s = (struct newdict *)calloc(d->malloc_size, 1);
if(!s)
{
return 0;
}
s->next = d;
s->prev = d->prev;
s->prev->next = s;
d->prev = s;
s->new_id = s->prev->new_id + 1;
memcpy(s->name, name, name[0]+1);
s->defining_file = file_idx;
//s->id_in_file[file_idx] = orig_id;
s->old_id = orig_id;
return s->new_id;
}
struct newdict *newdict_find(struct newdict *d, int file_idx, id mid)
{
// struct newdict *s;
// for(s = d->next; s != d; s = s->next)
// {
// if(s->id_in_file[file_idx] == mid) return s;
// }
// return (struct newdict *)0;
return d->cache[file_idx][mid];
}
// void newdict_debug_dump(struct newdict *d, char **file_names)
// {
// struct newdict *s;
// int i;
// printf("NEWDICT_DEBUG_DUMP\n");
// for(s = d->next; s != d; s = s->next)
// {
// printf(" %d %.*s", s->new_id, *s->name, s->name+1);
// if(s->defining_file != -1)
// {
// if(file_names)
// {
// printf(" (%s:%d)", file_names[s->defining_file], s->id_in_file[s->defining_file]);
// }
// else
// {
// printf(" (file_%d:%d)", s->defining_file, s->id_in_file[s->defining_file]);
// }
// }
// if(s->patch_id)
// {
// printf(" (patch ID %d, next line is implementation:)", s->patch_id);
// }
// printf("\n %d:%d", s->defining_file, s->id_in_file[s->defining_file]);
// for(i=0; i<d->fcnt; i++)
// {
// if(i == s->defining_file) continue;
// if(!s->id_in_file[i]) continue;
// printf(" %d:%d", i, s->id_in_file[i]);
// }
// printf("\n");
// }
// }
unsigned long newdict_dump(struct newdict *d, char *o)
{
unsigned long l = 0;
struct newdict *s = d->next;
while(s != d)
{
long tl = 0;
o[l] = C_DICT;
o[l+1] = 0; /* 0 => names needed for code/data relocation.
1 => names needed for symbolic debugging only
(in which case they are ignored when doing a
non-symbolic link) */
*(ushort *)(o + l + 4) = htons(s->new_id);
tl = 6;
while(s != d && tl < 10000)
{
memcpy(o + l + tl, s->name, s->name[0]+1);
tl += s->name[0]+1;
s = s->next;
}
/* doing the record! */
*(id *)(o + l + 2) = htons(tl);
if(tl & 1) o[l + tl++] = 0;
l += tl;
}
return l;
}
// id newdict_lookup_backend(struct newdict *d, uchar *str, long major, long minor)
// {
// struct newdict *s;
// for(s = d->prev; s != d; s = s->prev)
// {
// if(major == -1 || minor == -1 || (s->major == major && s->minor == minor))
// {
// if(cisc(str, s->str))
// {
// return s->n;
// }
// }
// }
// return 0;
// }
// id newdict_id_from_str_with_hint(struct newdict *d, uchar *str, long major, long minor)
// {
// id id;
// id = newdict_lookup_backend(d, str, major, minor);
// if(id) return id;
// id = newdict_lookup_backend(d, str, -1, -1);
// if(id) return id;
// id = newdict_append(d, str, major, minor);
// return id;
// }
/* COMPLETE ODDBALL */
// void reref(char **dest, long major, struct newdict *destdict, struct obj *src, struct obj *srcdict, id specialfrom, id specialto)
// {
// const char OFFSETS[11][3] = {
// /* 0*/ {0},
// /* 1*/ {0},
// /* 2*/ {0},
// /* 3*/ {0},
// /* 4*/ {0},
// /* 5*/ {2,4,0},
// /* 6*/ {2,0},
// /* 7*/ {0},
// /* 8*/ {0},
// /* 9*/ {4,0},
// /*10*/ {4,6,0},
// };
// unsigned long len;
// char t;
// int i;
// len = obj_size(src);
// t = obj_type(src);
// memcpy(*dest, src->at, len);
// for(i=0; OFFSETS[t][i]; i++)
// {
// id is;
// is = ntohs(*(id *)(*dest + OFFSETS[t][i]));
// //printf("Converting: type %d offset %d original %d special %d->%d\n", t, OFFSETS[t][i], is, specialfrom, specialto);
// if(is == specialfrom)
// {
// is = specialto;
// }
// else
// {
// uchar *str = dict_str_from_id(srcdict, is);
// if(!str) printf("Bullshit string\n");
// //printf("... intermediate string %x %.*s\n", str, *str, str+1);
// is = newdict_id_from_str_with_hint(destdict, str, major, is);
// }
// //printf("... to %d\n", is);
// *(id *)(*dest + OFFSETS[t][i]) = htons(is);
// }
// *dest += len;
// if((long)(*dest) & 1) *(*dest)++ = 0;
// }
void obj_copy(struct obj *dest, struct obj *src)
{
char *destthing;
obj_next(dest);
destthing = dest->at;
memcpy(destthing, src->at, obj_size(src));
obj_next(dest);
obj_pad(dest);
dest->at = destthing;
}
int obj_islastinmod(struct obj *o)
{
struct obj j;
char t;
memcpy(&j, o, sizeof (struct obj));
obj_next(&j);
t = obj_type(&j);
return t == C_MODULE || t == C_LAST;
}