/* * LIBREF.C * * LIBREF [cmdfile] * (default func.def) */ #include #include #include #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); }