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 >
C/C++ Source or Header  |  1988-04-28  |  12KB  |  564 lines

  1.  
  2. /*
  3.  *  LIBREF.C
  4.  *
  5.  *  LIBREF [cmdfile]
  6.  *  (default func.def)
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <fcntl.h>
  11. #include <local/typedefs.h>
  12.  
  13. #define FLIST    struct _FLIST
  14.  
  15. FLIST {
  16.     MNODE   Node;
  17.     uword   RegMask;
  18.     uword   IsAsm;
  19.     char    FName[64];
  20. };
  21.  
  22. extern char *MToS();
  23.  
  24. char LibGlob[64] = { "SomeUnknownLibBase" };
  25. char MName[128] = { "ram:MakeLib.c" };
  26. char LName[128] = { "ram:LinkTag.asm" };
  27. char TName[128] = { "ram:LibTag.asm" };
  28. char LibName[128] = { "ram:Lib.lib" };
  29. MLIST FBase;
  30.  
  31. main(ac,av)
  32. char *av[];
  33. {
  34.     FILE *fi;
  35.     char *file = "func.def";
  36.     char buf[128];
  37.  
  38.     puts("LIBREF V1.00 Sept 1988, (c)Copyright 1988 Matthew Dillon, All Rights Reserved");
  39.     puts("  source/executable Freely distributable for non-profit only.  May be USED");
  40.     puts("  in-house to generate commercial libraries.");
  41.  
  42.     NewList(&FBase);
  43.     if (ac == 2)
  44.     file = av[1];
  45.     fi = fopen(file, "r");
  46.     if (!fi) {
  47.     printf("%s not found\n", file);
  48.     puts("LIBREF [cmdfile]");
  49.     exit(1);
  50.     }
  51.     while (fgets(buf, sizeof(buf), fi)) {
  52.     buf[strlen(buf)-1] = 0;
  53.     if (!buf[0] || buf[0] == ';')
  54.         continue;
  55.     switch((buf[0]<<8)|buf[1]) {
  56.     case '1=':
  57.         sscanf(buf+2, "%s", MName);
  58.         break;
  59.     case '2=':
  60.         sscanf(buf+2, "%s", LName);
  61.         break;
  62.     case '3=':
  63.         sscanf(buf+2, "%s", TName);
  64.         break;
  65.     case '4=':
  66.         sscanf(buf+2, "%s", LibGlob);
  67.         break;
  68.     case '5=':
  69.         sscanf(buf+2, "%s", LibName);
  70.         break;
  71.     case '6=':
  72.     case '7=':
  73.     case '8=':
  74.     case '9=':
  75.         break;
  76.     default:
  77.         scanfile(buf, buf, sizeof(buf));
  78.         break;
  79.     }
  80.     }
  81.     fclose(fi);
  82.     {
  83.     FILE *fi = fopen(MName, "w");
  84.     if (!fi) {
  85.         printf("Unable to open %s for write\n", MName);
  86.         exit(-1);
  87.     }
  88.     GenerateMakeLib(fi);
  89.     fclose(fi);
  90.     fi = fopen(TName, "w");
  91.     if (!fi) {
  92.         printf("Unable to open %s for write\n", MName);
  93.         exit(-1);
  94.     }
  95.     GenerateTags(fi);
  96.     fclose(fi);
  97.     GenerateLinkLib(LName, strlen(LName));
  98.     }
  99. }
  100.  
  101. /*
  102.  * scan file for functions
  103.  *
  104.  *  *FUNC=NAME REGS     (C, assembly tag entry, add extra _)
  105.  *  ;FUNC=NAME REGS     (assembly, direct entry)
  106.  *         D0-2/A0/A1/A2 ...
  107.  *         REGISTERS ALWAYS LOADED D0-D7,A0-A7    (A6,A7 cannot be used)
  108.  *
  109.  *  starting within the first 16 lines of the file.
  110.  */
  111.  
  112. scanfile(file, buf, bufsize)
  113. char *file;
  114. char *buf;
  115. long bufsize;
  116. {
  117.     FILE *fi;
  118.     short i;
  119.  
  120.     fi = fopen(file, "r");
  121.     if (!fi) {
  122.     printf("Unable to open file %s\n", file);
  123.     return(-1);
  124.     }
  125.     for (i = 0; i < 16; ++i) {
  126.     short isasm;
  127.     short j;
  128.     if (fgets(buf, bufsize, fi) == NULL)
  129.         return(0);
  130.     for (j = 0; buf[j] == ' ' || buf[j] == 9; ++j);
  131.     isasm = (buf[j] == ';' || buf[j] == 'A');
  132.     ++j;
  133.     if (strncmp(buf+j, "FUNC=", 5) == 0) {
  134.         i = 0;
  135.         AddFunction(buf+j+5, isasm);
  136.     }
  137.     }
  138.     fclose(fi);
  139. }
  140.  
  141. /*
  142.  *  FuncName    Regs    (NULL SPECIAL)
  143.  */
  144.  
  145. AddFunction(buf, isasm)
  146. char *buf;
  147. {
  148.     char fname[64];
  149.     char regs[64];
  150.     uword regmask = 0;       /*  A7-A0,D7-D0 */
  151.  
  152.     if (sscanf(buf, "%s %s", fname, regs) != 2) {
  153.     printf("Argument Error: %s\n", buf);
  154.     return(-1);
  155.     }
  156.     if (strcmp(regs, "-") == 0)
  157.     regs[0] = 0;
  158.     {
  159.     register short i;
  160.     register short s, e;
  161.     for (i = 0; regs[i]; ) {
  162.         s = e = regs[i+1] - '0';
  163.         if (s < 0 || s > 7)
  164.         goto fail;
  165.         switch(regs[i]) {
  166.         case 'A':
  167.         s += 8;
  168.         e += 8;
  169.         i += 2;
  170.         if (regs[i] == '-') {
  171.             if (regs[i+1] != 'A')
  172.             goto fail;
  173.             e = regs[i+2] - '0';
  174.             if (e < 0 || e > 7)
  175.             goto fail;
  176.             e += 8;
  177.             i += 3;
  178.         }
  179.         break;
  180.         case 'D':
  181.         i += 2;
  182.         if (regs[i] == '-') {
  183.             if (regs[i+1] != 'D')
  184.             goto fail;
  185.             e = regs[i+2] - '0';
  186.             if (e < 0 || e > 7)
  187.             goto fail;
  188.             i += 3;
  189.         }
  190.         break;
  191.         default:
  192.         goto fail;
  193.         }
  194.         while (s <= e) {
  195.         regmask |= 1 << s;
  196.         ++s;
  197.         }
  198.         if (regs[i]) {
  199.         if (regs[i] != '/')
  200.             goto fail;
  201.         ++i;
  202.         }
  203.     }
  204.     }
  205.     /*
  206.     printf("Function: %-10s Regs: %04x  Asm: %d\n", fname, regmask, isasm);
  207.     */
  208.     {
  209.     register FLIST *fl = malloc(sizeof(FLIST));
  210.     if (fl) {
  211.         fl->RegMask = regmask;
  212.         fl->IsAsm    = isasm;
  213.         if (strcmp(fname, "NULL") == 0)
  214.         fl->FName[0] = 0;
  215.         else
  216.         strcpy(fl->FName, fname);
  217.         AddTail(&FBase, fl);
  218.     }
  219.     }
  220.     return(0);
  221. fail:
  222.     printf("Bad Register Spec: %s\n", buf);
  223.     return(-1);
  224. }
  225.  
  226. GenerateMakeLib(fi)
  227. FILE *fi;
  228. {
  229.     register FLIST *fl;
  230.     short i;
  231.  
  232.     fprintf(fi, "\n/*\n * Machine Generated Library Vectors\n */\n\n");
  233.     fprintf(fi, "#ifndef NULL\n#define NULL 0L\n#endif\n\n");
  234.     fprintf(fi, "extern long _LibOpen(), _LibClose(), _LibExpunge();\n");
  235.     for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
  236.     if (fl->FName[0]) {
  237.         if (fl->IsAsm) {    /*  If assembly, direct reference   */
  238.         fprintf(fi, "extern long l%s();\n", fl->FName);
  239.         } else {        /*  If not, reference to tag        */
  240.         fprintf(fi, "extern long _l%s();\n", fl->FName);
  241.         }
  242.     }
  243.     }
  244.  
  245.     fprintf(fi, "\n\n/*\n * -30-6*X\n */\n\n");
  246.     fprintf(fi, "long (*LibVectors[])() = {\n");
  247.     fprintf(fi, "    _LibOpen, _LibClose, _LibExpunge, NULL,\n\n");
  248.     for (i = 0, fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
  249.     if (fl->FName[0]) {
  250.         if (fl->IsAsm)
  251.         fprintf(fi, "    l%-16s,    /*  %3ld  %-20s  */\n", fl->FName, -30-6*i, MToS(fl->RegMask));
  252.         else
  253.         fprintf(fi, "    _l%-15s,    /*  %3ld  %-20s  */\n", fl->FName, -30-6*i, MToS(fl->RegMask));
  254.     } else {
  255.         fprintf(fi, "    NULL,\n");
  256.     }
  257.     ++i;
  258.     }
  259.     fprintf(fi, "    (long (*)())-1\n};\n\n");
  260. }
  261.  
  262. GenerateTags(fi)
  263. FILE *fi;
  264. {
  265.     register FLIST *fl;
  266.  
  267.     fprintf(fi, "\n");
  268.     fprintf(fi, "\t; Machine Generated File\n");
  269.     fprintf(fi, "\t; Tags for library routines which are in C\n\n");
  270.     fprintf(fi, "\tFAR\tDATA\n\n");
  271.     for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
  272.     uword mask;
  273.     if (fl->IsAsm || !fl->FName[0])
  274.         continue;
  275.     fprintf(fi, "\n");
  276.     fprintf(fi, "\t\tpublic _l%s\n\t\tpublic __l%s\n\n", fl->FName, fl->FName);
  277.     fprintf(fi, "__l%s:\n", fl->FName);
  278.  
  279.     /*
  280.      *  Save the set D2/D3/A6, but don't bother saving D2 or
  281.      *  D2 and D3 if passed as arguments.
  282.      */
  283.  
  284.     mask = 0x400C;
  285.     MoveToStack(fi, mask);          /*  Save some args  */
  286.     MoveToStack(fi, fl->RegMask);   /*  Push some args  */
  287.     fprintf(fi, "\t\tbsr\t_l%s\n", fl->FName);
  288.     PopStack(fi, fl->RegMask);
  289.     MoveFromStack(fi, mask);
  290.     fprintf(fi,"\t\trts\n");
  291.     }
  292. }
  293.  
  294.  
  295. /*
  296.  *  Generate the link library.    Create N output modules for
  297.  *  each function reference by appending a number to the name
  298.  */
  299.  
  300. GenerateLinkLib(dir, dirlen)
  301. char *dir;
  302. short dirlen;
  303. {
  304.     char tmp[128];
  305.     short i, nobj, nj;
  306.     FILE *fi;
  307.     FILE *fi2;
  308.     register FLIST *fl;
  309.     register short off;
  310.  
  311.     strcpy(dir+dirlen, "Makefile");
  312.     fi = fopen(dir, "w");
  313.     if (!fi)
  314.     goto fail;
  315.     strcpy(dir+dirlen, "Ordin");
  316.     fi2 = fopen(dir, "w");
  317.     if (!fi2)
  318.     goto fail;
  319.  
  320.     fputs("\nAFLAGS = -D\n\n", fi);
  321.  
  322.     nj = 0;
  323.     nobj = 1;
  324.     for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
  325.     if (!fl->FName[0])
  326.         continue;
  327.     fprintf(fi2, "%s.o\n", fl->FName);
  328.     if (nj == 0)
  329.         fprintf(fi, "OBJ%d = ", nobj);
  330.     fprintf(fi, "%s.o ", fl->FName);
  331.     nj += strlen(fl->FName) + 3;
  332.     if (nj > 70) {
  333.         fprintf(fi, "\n");
  334.         nj = 0;
  335.         ++nobj;
  336.     }
  337.     }
  338.     fprintf(fi2, "lvo.o\n");
  339.     if (nj == 0)
  340.     fprintf(fi, "OBJ%d = ", nobj);
  341.     fprintf(fi, "lvo.o\n");
  342.     fclose(fi2);
  343.     fprintf(fi, "\nall:\t");
  344.     for (i = 1; i <= nobj; ++i) {
  345.     fprintf(fi, "$(OBJ%d) ", i);
  346.     }
  347.     fprintf(fi, "\n");
  348.     fprintf(fi, "\tord %s ", dir);
  349.     strcpy(dir+dirlen, "Ordout");
  350.     fprintf(fi, "\t%s\n", dir);
  351.     fprintf(fi, "\t-Delete %s\n", LibName);
  352.     fprintf(fi, "\tlb %s -f %s\n", LibName, dir);
  353.  
  354.     strcpy(dir+dirlen, "lvo.asm");
  355.  
  356.  
  357.     fclose(fi);
  358.     fi = fopen(dir, "w");
  359.     if (!fi)
  360.     goto fail;
  361.     for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
  362.     if (fl->FName[0])
  363.         fprintf(fi, "\t\tpublic\t_LVO%s\n", fl->FName);
  364.     }
  365.     for (off = -30, fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
  366.     if (!fl->FName[0]) {
  367.         off -= 6;
  368.         continue;
  369.     }
  370.     sprintf(tmp, "_LVO%s", fl->FName);
  371.     fprintf(fi, "%-24s\tequ\t%d\n", tmp, off);
  372.     off -= 6;
  373.     }
  374.     fclose(fi);
  375.  
  376.     for (fl = (FLIST *)FBase.mlh_Head; (APTR)fl != (APTR)&FBase.mlh_Tail; fl = (FLIST *)fl->Node.mln_Succ) {
  377.     if (!fl->FName[0])
  378.         continue;
  379.     strcpy(dir+dirlen, "TEMP");
  380.     strcpy(tmp, dir);
  381.  
  382.     strcpy(dir+dirlen, fl->FName);
  383.     strcat(dir+dirlen, ".asm");
  384.     fi = fopen(tmp, "w");
  385.     if (!fi)
  386.         goto fail;
  387.  
  388.     fprintf(fi,"\n; Machine Generated Link Tag\n\n");
  389.     fprintf(fi,"\t\tFAR\tDATA\n");
  390.     fprintf(fi,"\t\tpublic\t_LVO%s\n", fl->FName);
  391.     fprintf(fi,"\t\tpublic\t_%s\n", LibGlob);
  392.     fprintf(fi,"\t\tpublic\t_%s\n\n", fl->FName);
  393.     fprintf(fi,"_%s:\n", fl->FName);
  394.  
  395.     /*
  396.      *  Generate linker tag to assembly.  If neither A0 or A1 is
  397.      *  used as an argument, use one as the link register, else
  398.      *  save A6 and use that.
  399.      *
  400.      *  If A2-A6 (inc A6 above), D2-D6 are required to hold
  401.      *  parameters, they are saved before the call, restored
  402.      *  after.   If they are not required to hold any parameters,
  403.      *  a JMP is issued instead of a JSR.
  404.      */
  405.  
  406.     {
  407.         uword argmask = fl->RegMask;
  408.         uword savmask = fl->RegMask;
  409.         short areg = 6;
  410.         if (!(argmask & 0x0100))   /*  A0 not used */
  411.         areg = 0;
  412.         if (!(argmask & 0x0200))   /*  A1 not used */
  413.         areg = 1;
  414.         savmask |= 1 << (areg+8);  /*  Add register usage  */
  415.         MoveToStack(fi, savmask & 0xFCFC);                          /*  save some regs      */
  416.         LoadFromStack(fi, argmask, 4+Offset(argmask & 0xFCFC));     /*  load params         */
  417.         fprintf(fi,"\t\tmove.l\t_%s,A%d\n", LibGlob, areg);
  418.         if (savmask & 0xFCFC) {
  419.         fprintf(fi, "\t\tjsr\t_LVO%s(A%d)\n", fl->FName, areg);
  420.         MoveFromStack(fi, savmask & 0xFCFC);                    /*  restore some regs   */
  421.         fprintf(fi,"\t\trts\n");
  422.         } else {
  423.         fprintf(fi, "\t\tjmp\t_LVO%s(A%d)\n", fl->FName, areg);
  424.         }
  425.     }
  426.     fclose(fi);
  427.     if (cmp_file(tmp, dir) == 0) {  /*  update only if changed  */
  428.         DeleteFile(dir);
  429.         Rename(tmp, dir);
  430.     }
  431.     }
  432.     return(0);
  433. fail:
  434.     printf("Unable to open %s\n", dir);
  435.     return(-1);
  436. }
  437.  
  438. char *
  439. MToS(mask)
  440. register uword mask;
  441. {
  442.     register short i;
  443.     register short j = 0;
  444.     static char buf[64];
  445.  
  446.     for (i = 0; i < 8; ++i, mask >>= 1) {
  447.     if (mask & 1) {
  448.         if (j)
  449.         buf[j++] = '/';
  450.         buf[j++] = 'D';
  451.         buf[j++] = i + '0';
  452.     }
  453.     }
  454.     for (i = 0; i < 8; ++i, mask >>= 1) {
  455.     if (mask & 1) {
  456.         if (j)
  457.         buf[j++] = '/';
  458.         buf[j++] = 'A';
  459.         buf[j++] = i + '0';
  460.     }
  461.     }
  462.     buf[j++] = 0;
  463.     return(buf);
  464. }
  465.  
  466.  
  467. MoveToStack(fi, mask)
  468. FILE *fi;
  469. {
  470.     char *str = MToS(mask);
  471.     if (!str[0])
  472.     return(0);
  473.     if (!str[2]) {
  474.     fprintf(fi, "\t\tmove.l\t%s,-(sp)\n", str);
  475.     } else {
  476.     fprintf(fi, "\t\tmovem.l\t%s,-(sp)\n", str);
  477.     }
  478. }
  479.  
  480. MoveFromStack(fi, mask)
  481. FILE *fi;
  482. uword mask;
  483. {
  484.     char *str = MToS(mask);
  485.  
  486.     if (!str[0])
  487.     return(0);
  488.     if (!str[2])
  489.     fprintf(fi, "\t\tmove.l\t(sp)+,%s\n", str);
  490.     else
  491.     fprintf(fi, "\t\tmovem.l\t(sp)+,%s\n", str);
  492. }
  493.  
  494. LoadFromStack(fi, mask, offset)
  495. {
  496.     char *str = MToS(mask);
  497.  
  498.     if (!str[0])
  499.     return(0);
  500.     if (!str[2])
  501.     fprintf(fi, "\t\tmove.l\t%d(sp),%s\n", offset, str);
  502.     else
  503.     fprintf(fi, "\t\tmovem.l\t%d(sp),%s\n", offset, str);
  504. }
  505.  
  506.  
  507. PopStack(fi, mask)
  508. FILE *fi;
  509. uword mask;
  510. {
  511.     register short j;
  512.     if (j = Offset(mask)) {
  513.     if (j > 8)
  514.         fprintf(fi,"\t\tadd.w\t#%d,A7\n", j);
  515.     else
  516.         fprintf(fi,"\t\taddq.l\t#%d,A7\n", j);
  517.     }
  518. }
  519.  
  520. Offset(mask)
  521. uword mask;
  522. {
  523.     register short i, j;
  524.     for (i = j = 0; i < 16; ++i) {
  525.     if (mask & (1 << i))
  526.         ++j;
  527.     }
  528.     return(j*4);
  529. }
  530.  
  531. cmp_file(name1, name2)
  532. char *name1;
  533. char *name2;
  534. {
  535.     short i, fd1, fd2;
  536.     static char buf1[1024];
  537.     static char buf2[1024];
  538.  
  539.     fd1 = open(name1, O_RDONLY);
  540.     if (fd1 < 0)
  541.     return(0);
  542.     fd2 = open(name2, O_RDONLY);
  543.     if (fd2 < 0) {
  544.     close(fd1);
  545.     return(0);
  546.     }
  547.     while ((i = read(fd1, buf1, sizeof(buf1))) > 0) {
  548.     if (read(fd2, buf2, i) != i)
  549.         goto fail;
  550.     if (bcmp(buf1, buf2, i) == 0)
  551.         goto fail;
  552.     }
  553.     if (read(fd2, buf2, 1) != 0)
  554.     goto fail;
  555.     close(fd1);
  556.     close(fd2);
  557.     return(1);
  558. fail:
  559.     close(fd1);
  560.     close(fd2);
  561.     return(0);
  562. }
  563.  
  564.