home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
177.lha
/
DRes_v1.3
/
libref.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-04-28
|
12KB
|
564 lines
/*
* LIBREF.C
*
* LIBREF [cmdfile]
* (default func.def)
*/
#include <stdio.h>
#include <fcntl.h>
#include <local/typedefs.h>
#define FLIST struct _FLIST
FLIST {
MNODE Node;
uword RegMask;
uword IsAsm;
char FName[64];
};
extern char *MToS();
char LibGlob[64] = { "SomeUnknownLibBase" };
char MName[128] = { "ram:MakeLib.c" };
char LName[128] = { "ram:LinkTag.asm" };
char TName[128] = { "ram:LibTag.asm" };
char LibName[128] = { "ram:Lib.lib" };
MLIST FBase;
main(ac,av)
char *av[];
{
FILE *fi;
char *file = "func.def";
char buf[128];
puts("LIBREF V1.00 Sept 1988, (c)Copyright 1988 Matthew Dillon, All Rights Reserved");
puts(" source/executable Freely distributable for non-profit only. May be USED");
puts(" in-house to generate commercial libraries.");
NewList(&FBase);
if (ac == 2)
file = av[1];
fi = fopen(file, "r");
if (!fi) {
printf("%s not found\n", file);
puts("LIBREF [cmdfile]");
exit(1);
}
while (fgets(buf, sizeof(buf), fi)) {
buf[strlen(buf)-1] = 0;
if (!buf[0] || buf[0] == ';')
continue;
switch((buf[0]<<8)|buf[1]) {
case '1=':
sscanf(buf+2, "%s", MName);
break;
case '2=':
sscanf(buf+2, "%s", LName);
break;
case '3=':
sscanf(buf+2, "%s", TName);
break;
case '4=':
sscanf(buf+2, "%s", LibGlob);
break;
case '5=':
sscanf(buf+2, "%s", LibName);
break;
case '6=':
case '7=':
case '8=':
case '9=':
break;
default:
scanfile(buf, buf, sizeof(buf));
break;
}
}
fclose(fi);
{
FILE *fi = fopen(MName, "w");
if (!fi) {
printf("Unable to open %s for write\n", MName);
exit(-1);
}
GenerateMakeLib(fi);
fclose(fi);
fi = fopen(TName, "w");
if (!fi) {
printf("Unable to open %s for write\n", MName);
exit(-1);
}
GenerateTags(fi);
fclose(fi);
GenerateLinkLib(LName, strlen(LName));
}
}
/*
* scan file for functions
*
* *FUNC=NAME REGS (C, assembly tag entry, add extra _)
* ;FUNC=NAME REGS (assembly, direct entry)
* D0-2/A0/A1/A2 ...
* REGISTERS ALWAYS LOADED D0-D7,A0-A7 (A6,A7 cannot be used)
*
* starting within the first 16 lines of the file.
*/
scanfile(file, buf, bufsize)
char *file;
char *buf;
long bufsize;
{
FILE *fi;
short i;
fi = fopen(file, "r");
if (!fi) {
printf("Unable to open file %s\n", file);
return(-1);
}
for (i = 0; i < 16; ++i) {
short isasm;
short j;
if (fgets(buf, bufsize, fi) == NULL)
return(0);
for (j = 0; buf[j] == ' ' || buf[j] == 9; ++j);
isasm = (buf[j] == ';' || buf[j] == 'A');
++j;
if (strncmp(buf+j, "FUNC=", 5) == 0) {
i = 0;
AddFunction(buf+j+5, isasm);
}
}
fclose(fi);
}
/*
* FuncName Regs (NULL SPECIAL)
*/
AddFunction(buf, isasm)
char *buf;
{
char fname[64];
char regs[64];
uword regmask = 0; /* A7-A0,D7-D0 */
if (sscanf(buf, "%s %s", fname, regs) != 2) {
printf("Argument Error: %s\n", buf);
return(-1);
}
if (strcmp(regs, "-") == 0)
regs[0] = 0;
{
register short i;
register short s, e;
for (i = 0; regs[i]; ) {
s = e = regs[i+1] - '0';
if (s < 0 || s > 7)
goto fail;
switch(regs[i]) {
case 'A':
s += 8;
e += 8;
i += 2;
if (regs[i] == '-') {
if (regs[i+1] != 'A')
goto fail;
e = regs[i+2] - '0';
if (e < 0 || e > 7)
goto fail;
e += 8;
i += 3;
}
break;
case 'D':
i += 2;
if (regs[i] == '-') {
if (regs[i+1] != 'D')
goto fail;
e = regs[i+2] - '0';
if (e < 0 || e > 7)
goto fail;
i += 3;
}
break;
default:
goto fail;
}
while (s <= e) {
regmask |= 1 << s;
++s;
}
if (regs[i]) {
if (regs[i] != '/')
goto fail;
++i;
}
}
}
/*
printf("Function: %-10s Regs: %04x Asm: %d\n", fname, regmask, isasm);
*/
{
register FLIST *fl = malloc(sizeof(FLIST));
if (fl) {
fl->RegMask = regmask;
fl->IsAsm = isasm;
if (strcmp(fname, "NULL") == 0)
fl->FName[0] = 0;
else
strcpy(fl->FName, fname);
AddTail(&FBase, fl);
}
}
return(0);
fail:
printf("Bad Register Spec: %s\n", buf);
return(-1);
}
GenerateMakeLib(fi)
FILE *fi;
{
register FLIST *fl;
short i;
fprintf(fi, "\n/*\n * Machine Generated Library Vectors\n */\n\n");
fprintf(fi, "#ifndef NULL\n#define NULL 0L\n#endif\n\n");
fprintf(fi, "extern long _LibOpen(), _LibClose(), _LibExpunge();\n");
for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
if (fl->FName[0]) {
if (fl->IsAsm) { /* If assembly, direct reference */
fprintf(fi, "extern long l%s();\n", fl->FName);
} else { /* If not, reference to tag */
fprintf(fi, "extern long _l%s();\n", fl->FName);
}
}
}
fprintf(fi, "\n\n/*\n * -30-6*X\n */\n\n");
fprintf(fi, "long (*LibVectors[])() = {\n");
fprintf(fi, " _LibOpen, _LibClose, _LibExpunge, NULL,\n\n");
for (i = 0, fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
if (fl->FName[0]) {
if (fl->IsAsm)
fprintf(fi, " l%-16s, /* %3ld %-20s */\n", fl->FName, -30-6*i, MToS(fl->RegMask));
else
fprintf(fi, " _l%-15s, /* %3ld %-20s */\n", fl->FName, -30-6*i, MToS(fl->RegMask));
} else {
fprintf(fi, " NULL,\n");
}
++i;
}
fprintf(fi, " (long (*)())-1\n};\n\n");
}
GenerateTags(fi)
FILE *fi;
{
register FLIST *fl;
fprintf(fi, "\n");
fprintf(fi, "\t; Machine Generated File\n");
fprintf(fi, "\t; Tags for library routines which are in C\n\n");
fprintf(fi, "\tFAR\tDATA\n\n");
for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
uword mask;
if (fl->IsAsm || !fl->FName[0])
continue;
fprintf(fi, "\n");
fprintf(fi, "\t\tpublic _l%s\n\t\tpublic __l%s\n\n", fl->FName, fl->FName);
fprintf(fi, "__l%s:\n", fl->FName);
/*
* Save the set D2/D3/A6, but don't bother saving D2 or
* D2 and D3 if passed as arguments.
*/
mask = 0x400C;
MoveToStack(fi, mask); /* Save some args */
MoveToStack(fi, fl->RegMask); /* Push some args */
fprintf(fi, "\t\tbsr\t_l%s\n", fl->FName);
PopStack(fi, fl->RegMask);
MoveFromStack(fi, mask);
fprintf(fi,"\t\trts\n");
}
}
/*
* Generate the link library. Create N output modules for
* each function reference by appending a number to the name
*/
GenerateLinkLib(dir, dirlen)
char *dir;
short dirlen;
{
char tmp[128];
short i, nobj, nj;
FILE *fi;
FILE *fi2;
register FLIST *fl;
register short off;
strcpy(dir+dirlen, "Makefile");
fi = fopen(dir, "w");
if (!fi)
goto fail;
strcpy(dir+dirlen, "Ordin");
fi2 = fopen(dir, "w");
if (!fi2)
goto fail;
fputs("\nAFLAGS = -D\n\n", fi);
nj = 0;
nobj = 1;
for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
if (!fl->FName[0])
continue;
fprintf(fi2, "%s.o\n", fl->FName);
if (nj == 0)
fprintf(fi, "OBJ%d = ", nobj);
fprintf(fi, "%s.o ", fl->FName);
nj += strlen(fl->FName) + 3;
if (nj > 70) {
fprintf(fi, "\n");
nj = 0;
++nobj;
}
}
fprintf(fi2, "lvo.o\n");
if (nj == 0)
fprintf(fi, "OBJ%d = ", nobj);
fprintf(fi, "lvo.o\n");
fclose(fi2);
fprintf(fi, "\nall:\t");
for (i = 1; i <= nobj; ++i) {
fprintf(fi, "$(OBJ%d) ", i);
}
fprintf(fi, "\n");
fprintf(fi, "\tord %s ", dir);
strcpy(dir+dirlen, "Ordout");
fprintf(fi, "\t%s\n", dir);
fprintf(fi, "\t-Delete %s\n", LibName);
fprintf(fi, "\tlb %s -f %s\n", LibName, dir);
strcpy(dir+dirlen, "lvo.asm");
fclose(fi);
fi = fopen(dir, "w");
if (!fi)
goto fail;
for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
if (fl->FName[0])
fprintf(fi, "\t\tpublic\t_LVO%s\n", fl->FName);
}
for (off = -30, fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
if (!fl->FName[0]) {
off -= 6;
continue;
}
sprintf(tmp, "_LVO%s", fl->FName);
fprintf(fi, "%-24s\tequ\t%d\n", tmp, off);
off -= 6;
}
fclose(fi);
for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
if (!fl->FName[0])
continue;
strcpy(dir+dirlen, "TEMP");
strcpy(tmp, dir);
strcpy(dir+dirlen, fl->FName);
strcat(dir+dirlen, ".asm");
fi = fopen(tmp, "w");
if (!fi)
goto fail;
fprintf(fi,"\n; Machine Generated Link Tag\n\n");
fprintf(fi,"\t\tFAR\tDATA\n");
fprintf(fi,"\t\tpublic\t_LVO%s\n", fl->FName);
fprintf(fi,"\t\tpublic\t_%s\n", LibGlob);
fprintf(fi,"\t\tpublic\t_%s\n\n", fl->FName);
fprintf(fi,"_%s:\n", fl->FName);
/*
* Generate linker tag to assembly. If neither A0 or A1 is
* used as an argument, use one as the link register, else
* save A6 and use that.
*
* If A2-A6 (inc A6 above), D2-D6 are required to hold
* parameters, they are saved before the call, restored
* after. If they are not required to hold any parameters,
* a JMP is issued instead of a JSR.
*/
{
uword argmask = fl->RegMask;
uword savmask = fl->RegMask;
short areg = 6;
if (!(argmask & 0x0100)) /* A0 not used */
areg = 0;
if (!(argmask & 0x0200)) /* A1 not used */
areg = 1;
savmask |= 1 << (areg+8); /* Add register usage */
MoveToStack(fi, savmask & 0xFCFC); /* save some regs */
LoadFromStack(fi, argmask, 4+Offset(argmask & 0xFCFC)); /* load params */
fprintf(fi,"\t\tmove.l\t_%s,A%d\n", LibGlob, areg);
if (savmask & 0xFCFC) {
fprintf(fi, "\t\tjsr\t_LVO%s(A%d)\n", fl->FName, areg);
MoveFromStack(fi, savmask & 0xFCFC); /* restore some regs */
fprintf(fi,"\t\trts\n");
} else {
fprintf(fi, "\t\tjmp\t_LVO%s(A%d)\n", fl->FName, areg);
}
}
fclose(fi);
if (cmp_file(tmp, dir) == 0) { /* update only if changed */
DeleteFile(dir);
Rename(tmp, dir);
}
}
return(0);
fail:
printf("Unable to open %s\n", dir);
return(-1);
}
char *
MToS(mask)
register uword mask;
{
register short i;
register short j = 0;
static char buf[64];
for (i = 0; i < 8; ++i, mask >>= 1) {
if (mask & 1) {
if (j)
buf[j++] = '/';
buf[j++] = 'D';
buf[j++] = i + '0';
}
}
for (i = 0; i < 8; ++i, mask >>= 1) {
if (mask & 1) {
if (j)
buf[j++] = '/';
buf[j++] = 'A';
buf[j++] = i + '0';
}
}
buf[j++] = 0;
return(buf);
}
MoveToStack(fi, mask)
FILE *fi;
{
char *str = MToS(mask);
if (!str[0])
return(0);
if (!str[2]) {
fprintf(fi, "\t\tmove.l\t%s,-(sp)\n", str);
} else {
fprintf(fi, "\t\tmovem.l\t%s,-(sp)\n", str);
}
}
MoveFromStack(fi, mask)
FILE *fi;
uword mask;
{
char *str = MToS(mask);
if (!str[0])
return(0);
if (!str[2])
fprintf(fi, "\t\tmove.l\t(sp)+,%s\n", str);
else
fprintf(fi, "\t\tmovem.l\t(sp)+,%s\n", str);
}
LoadFromStack(fi, mask, offset)
{
char *str = MToS(mask);
if (!str[0])
return(0);
if (!str[2])
fprintf(fi, "\t\tmove.l\t%d(sp),%s\n", offset, str);
else
fprintf(fi, "\t\tmovem.l\t%d(sp),%s\n", offset, str);
}
PopStack(fi, mask)
FILE *fi;
uword mask;
{
register short j;
if (j = Offset(mask)) {
if (j > 8)
fprintf(fi,"\t\tadd.w\t#%d,A7\n", j);
else
fprintf(fi,"\t\taddq.l\t#%d,A7\n", j);
}
}
Offset(mask)
uword mask;
{
register short i, j;
for (i = j = 0; i < 16; ++i) {
if (mask & (1 << i))
++j;
}
return(j*4);
}
cmp_file(name1, name2)
char *name1;
char *name2;
{
short i, fd1, fd2;
static char buf1[1024];
static char buf2[1024];
fd1 = open(name1, O_RDONLY);
if (fd1 < 0)
return(0);
fd2 = open(name2, O_RDONLY);
if (fd2 < 0) {
close(fd1);
return(0);
}
while ((i = read(fd1, buf1, sizeof(buf1))) > 0) {
if (read(fd2, buf2, i) != i)
goto fail;
if (bcmp(buf1, buf2, i) == 0)
goto fail;
}
if (read(fd2, buf2, 1) != 0)
goto fail;
close(fd1);
close(fd2);
return(1);
fail:
close(fd1);
close(fd2);
return(0);
}