home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / dev / fd2pragma-2.0.lha / fd2pragma / fd2pragma.c next >
Encoding:
C/C++ Source or Header  |  1994-03-12  |  24.9 KB  |  1,122 lines

  1. /*
  2.     fd2pragma.c
  3.  
  4.     This is a small little hack which converts fd-files to either
  5.     pragmas readable by a C-Compiler of LVO files readable by an
  6.     assembler. Use it as you want, but WITHOUT ANY WARRANTY!
  7.  
  8.     V1.2:   Added pragmas for the Dice compiler. Available via switch "Dice".
  9.         Added switches "Aztec", "SAS" and "Maxon": Maxon and Aztec just
  10.         turn on the default (except that Maxon expects pragma files to be
  11.         called "xxx_pragmas.h" instead of "xxx_lib.h"), SAS is equal to
  12.         Dice, except that SAS supports the pragma tagcall.
  13.  
  14.     V2.0:   Added support for tag functions. See the docs for details.
  15.  
  16.     Computer: Amiga 1200            Compiler: Aztec-C V5.0a
  17.                               Dice 2.07.54 (3.0)
  18.  
  19.     Author:    Jochen Wiedmann
  20.         Am Eisteich 9
  21.       72555 Metzingen (Germany)
  22.         Tel. 07123 / 14881
  23.         Internet: wiedmann@mailserv.zdv.uni-tuebingen.de
  24. */
  25.  
  26.  
  27.  
  28.  
  29.  
  30. /*
  31.     Include files
  32. */
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include <ctype.h>
  37. #include <exec/nodes.h>
  38. #include <exec/lists.h>
  39. #include <exec/libraries.h>
  40. #include <clib/exec_protos.h>
  41. #include <clib/alib_protos.h>
  42. #include <clib/dos_protos.h>
  43.  
  44. #ifdef AZTEC_C
  45. #include <pragmas/exec_lib.h>
  46. #include <pragmas/dos_lib.h>
  47. #endif
  48.  
  49. #if defined(_DCC)  ||  defined(__SASC)  ||  defined(__MAXON)
  50. #include <pragmas/exec_pragmas.h>
  51. #include <pragmas/dos_pragmas.h>
  52. #endif
  53.  
  54. #ifdef __GNUC__
  55. #include <inline/exec.h>
  56. #include <inline/dos.h>
  57. #endif
  58.  
  59.  
  60.  
  61.  
  62.  
  63. /*
  64.     Constants
  65. */
  66. #define MAXNAMELEN 128
  67.  
  68. const UBYTE VERSION[] = "$VER: fd2pragma 2.0 (11.03.94)   by  Jochen Wiedmann";
  69. const UBYTE TEMPLATE[] =
  70.     "FDFILE/A,AZTEC/K,AS/K,SAS/K,DICE/K,MAXON/K,TAGDIR/K,HELP/S";
  71.  
  72. const STRPTR RegNames[16] =
  73. { (STRPTR) "d0", (STRPTR) "d1", (STRPTR) "d2", (STRPTR) "d3",
  74.   (STRPTR) "d4", (STRPTR) "d5", (STRPTR) "d6", (STRPTR) "d7",
  75.   (STRPTR) "a0", (STRPTR) "a1", (STRPTR) "a2", (STRPTR) "a3",
  76.   (STRPTR) "a4", (STRPTR) "a5", (STRPTR) "a6", (STRPTR) "a7"
  77. };
  78.  
  79. const UBYTE HexDigits[16] = "0123456789ABCDEF";
  80.  
  81.  
  82.  
  83. /*
  84.     This structure is used to represent the pragmas that are read.
  85. */
  86. struct AmiPragma
  87. { struct MinNode Node;
  88.   LONG Bias;
  89.   LONG Public;
  90.   STRPTR FuncName;
  91.   STRPTR TagName;
  92.   ULONG NumArgs;
  93.   struct
  94.   { STRPTR ArgName;
  95.     ULONG ArgReg;
  96.   } Args[14];    /*  a6 and a7 must not be used for function arguments    */
  97. };
  98.  
  99.  
  100.  
  101.  
  102.  
  103. /*
  104.     Global variables
  105. */
  106. struct MinList AmiPragmaList;
  107. STRPTR BaseName;
  108. STRPTR ShortBaseName;
  109.  
  110.  
  111.  
  112.  
  113.  
  114. /*
  115.     This function works similar to strdup, but doesn't duplicate the
  116.     whole string.
  117.  
  118.     Inputs: Str - the string to be duplicated
  119.         Len - the number of bytes to be duplicated
  120.  
  121.     Result: Pointer to the copy of the string or NULL.
  122. */
  123. STRPTR strndup(const STRPTR Str, ULONG Len)
  124.  
  125. { STRPTR result;
  126.  
  127.   if ((result = malloc(Len+1)))
  128.   { memcpy(result, Str, Len);
  129.     result[Len] = '\0';
  130.   }
  131.   return(result);
  132. }
  133.  
  134.  
  135.  
  136.  
  137.  
  138. /*
  139.     This function prints help information.
  140. */
  141. void Usage(void)
  142.  
  143. { fprintf(stderr, "\nUsage: fd2pragma %s\n\n", TEMPLATE);
  144.  
  145.   fprintf(stderr, "This program reads the given FDFILE and converts it ");
  146.   fprintf(stderr, "into pragmas for\n");
  147.   fprintf(stderr, "a C-Compiler (SAS, Dice, Aztec or Maxon) or LVO files ");
  148.   fprintf(stderr, "for an\n");
  149.   fprintf(stderr, "Assembler (Aztec-As).\n\n");
  150.   fprintf(stderr, "TAGDIR is the name of a directory where to store stub ");
  151.   fprintf(stderr, "routines for\n");
  152.   fprintf(stderr, "pragma functions, if any are found. \"\" is the current ");
  153.   fprintf(stderr, "directory.\n\n\n");
  154.   fprintf(stderr, "%s\n\n", VERSION+6);
  155.   fprintf(stderr,
  156.       "This is public domain, use it as you want, but WITHOUT ANY WARRANTY!\n");
  157.   fprintf(stderr,
  158.       "Bugs and suggestions to wiedmann@mailserv.zdv.uni-tuebingen.de.\n\n");
  159.  
  160.   exit (1);
  161. }
  162.  
  163.  
  164.  
  165.  
  166.  
  167. /*
  168.     This function is used to skip over blanks.
  169.  
  170.     Inputs: OldPtr  - pointer to the beginning of a string.
  171.  
  172.     Result: Pointer to the first nonblank character of the string.
  173. */
  174. STRPTR SkipBlanks(const STRPTR OldPtr)
  175.  
  176. { STRPTR oldptr = OldPtr;
  177.  
  178.   while (*oldptr == ' '  ||  *oldptr == '\t')
  179.   { ++oldptr;
  180.   }
  181.   return(oldptr);
  182. }
  183.  
  184.  
  185.  
  186.  
  187.  
  188. /*
  189.     This function is used to skip over vvariable names.
  190.  
  191.     Inputs: OldPtr  - pointer to the beginning of a string.
  192.  
  193.     Result: Pointer to the first character of the string, that is not one
  194.         of a-z, A-Z, 0-9 or the underscore.
  195. */
  196. STRPTR SkipName(const STRPTR OldPtr)
  197.  
  198. { STRPTR oldptr;
  199.   UBYTE c;
  200.  
  201.   oldptr = OldPtr;
  202.   while((c = *oldptr) == '_'  ||
  203.     (c >= '0'  &&  c <= '9')  ||
  204.     (c >= 'a'  &&  c <= 'z')  ||
  205.     (c >= 'A'  &&  c <= 'Z'))
  206.   { ++oldptr;
  207.   }
  208.   return(oldptr);
  209. }
  210.  
  211.  
  212.  
  213.  
  214.  
  215. /*
  216.     This function tells, that we ran out of memory.
  217. */
  218. void MemError(void)
  219.  
  220. { fprintf(stderr, "Fatal: Out of memory!\n");
  221. }
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228. /*
  229.     This function is called to scan the FD file.
  230.  
  231.     Inputs: FDFile  - the name of the file to scan
  232.  
  233.     Result: TRUE, if successful, FALSE otherwise
  234. */
  235. ULONG ScanFDFile(const STRPTR FDFile)
  236.  
  237. { FILE *fp;
  238.   ULONG public = TRUE;
  239.   ULONG bias = -1;
  240.   ULONG linenum = 0;
  241.   ULONG result = FALSE;
  242.   UBYTE line[512];
  243.  
  244.   if (!(fp = fopen((char *) FDFile, "r")))
  245.   { fprintf(stderr, "Fatal: Cannot open FD file %s.\n", FDFile);
  246.     return(FALSE);
  247.   }
  248.  
  249.   NewList((struct List *) &AmiPragmaList);
  250.  
  251.   while(fgets((char *) line, sizeof(line), fp)  !=  NULL)
  252.   { ULONG len;
  253.  
  254.     ++linenum;
  255.  
  256.     for (len = 0;  len < sizeof(line);  ++len)
  257.     { if (line[len] == '\n')
  258.       { break;
  259.       }
  260.     }
  261.     if (len == sizeof(line))
  262.     { int c;
  263.  
  264.       fprintf(stderr, "Error: Line %ld too long.\n", linenum);
  265.       while((c = getc(fp)) != EOF  &&  c != '\n')
  266.       {
  267.       }
  268.       continue;
  269.     }
  270.     line[len] = '\0';   /*  Remove Line Feed    */
  271.  
  272.     if (line[0] == '*')
  273.     { /*  Comment   */
  274.       STRPTR ptr;
  275.  
  276.       ptr = SkipBlanks(line+1);
  277.       if(strnicmp((char *) ptr, "tagcall", 7) == 0)  /*  Tag to create?  */
  278.       { struct AmiPragma *prevpragma;
  279.  
  280.     ptr = SkipBlanks(ptr+7);
  281.  
  282.     prevpragma = (struct AmiPragma *) AmiPragmaList.mlh_TailPred;
  283.     if (!prevpragma->Node.mln_Pred)
  284.     { fprintf(stderr,
  285.           "Line %ld, Error: Tag definition without preceding Pragma.\n",
  286.           linenum);
  287.       continue;
  288.     }
  289.  
  290.     if (prevpragma->TagName)
  291.     { fprintf(stderr, "Line %ld, Error: Tag function declared twice.\n",
  292.           linenum);
  293.       continue;
  294.     }
  295.  
  296.     if (!prevpragma->NumArgs)
  297.     { fprintf(stderr,
  298.           "Line %ld, Error: Tag function must have arguments.\n",
  299.           linenum);
  300.     }
  301.  
  302.     /*
  303.         Get the tag functions name.
  304.     */
  305.     len = strlen((char *) prevpragma->FuncName)+strlen((char *) ptr)+1;
  306.  
  307.     if (!(prevpragma->TagName = strndup(prevpragma->FuncName, len)))
  308.     { MemError();
  309.       goto exit_ScanFDFile;
  310.     }
  311.  
  312.     if (!*ptr)
  313.     { len = strlen((char *) prevpragma->TagName);
  314.       if (prevpragma->TagName[len-1] == 'A')
  315.       { prevpragma->TagName[len-1] = '\0';
  316.       }
  317.     }
  318.     else
  319.     { STRPTR nextptr;
  320.  
  321.       if (*ptr == '-')
  322.       { STRPTR removeptr;
  323.  
  324.         ptr = SkipBlanks(ptr+1);
  325.         nextptr = SkipName(ptr);
  326.         if ((len = nextptr-ptr))
  327.         { removeptr = prevpragma->TagName+strlen((char *) prevpragma->TagName)-len;
  328.           if (!strncmp((char *) removeptr, (char *) ptr, len))
  329.           { fprintf(stderr,
  330.             "Line %ld, Error: Cannot convert pragma name into tag name.\n",
  331.             linenum);
  332.         continue;
  333.           }
  334.           *removeptr = '\0';
  335.         }
  336.         ptr = SkipBlanks(nextptr);
  337.       }
  338.       if (*ptr == '+')
  339.       { ptr = SkipBlanks(ptr+1);
  340.       }
  341.       else
  342.       { *ptr = toupper((int) *ptr);
  343.       }
  344.  
  345.       nextptr = SkipName(ptr);
  346.       len = nextptr-ptr;
  347.       if (len)
  348.       { strncat((char *) prevpragma->TagName, (char *) ptr, len);
  349.         ptr += len;
  350.       }
  351.  
  352.       if (*SkipBlanks(nextptr))
  353.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  354.       }
  355.     }
  356.       }
  357.     }
  358.     else if (strnicmp((char *) line, "##base", 6) == 0)
  359.     { STRPTR ptr, nextptr;
  360.       LONG len;
  361.  
  362.       if (BaseName)
  363.       { fprintf(stderr, "Line %ld, Error: Basename declared twice.\n",
  364.         linenum);
  365.       }
  366.  
  367.       ptr = SkipBlanks(line+6);
  368.       if (*ptr != '_')
  369.       { fprintf(stderr, "Line %ld, Warning: Expected preceding _ in Basename.\n",
  370.         linenum);
  371.       }
  372.       else
  373.       { ++ptr;
  374.       }
  375.       nextptr = SkipName(ptr);
  376.       if ((len = nextptr-ptr))
  377.       { if (!(BaseName = strndup(ptr, len)))
  378.     { MemError();
  379.       goto exit_ScanFDFile;
  380.     }
  381.  
  382.     ptr = FilePart(FDFile);
  383.     len = strlen((char *) ptr)-7;
  384.     if (len >= 0  &&  stricmp((char *) ptr+len, "_lib.fd") == 0)
  385.     { if (!(ShortBaseName = (STRPTR) strdup((char *) ptr)))
  386.       { MemError();
  387.         goto exit_ScanFDFile;
  388.       }
  389.       ShortBaseName[len] = '\0';
  390.     }
  391.     else
  392.     { if (!(ShortBaseName = (STRPTR) strdup((char *) BaseName)))
  393.       { MemError();
  394.         goto exit_ScanFDFile;
  395.       }
  396.       len = strlen((char *) ShortBaseName)-4;
  397.       if (len >= 0  &&  stricmp((char *) ShortBaseName+len, "base") == 0)
  398.       { ShortBaseName[len] = '\0';
  399.       }
  400.     }
  401.  
  402.     if (*SkipBlanks(nextptr))
  403.     { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  404.     }
  405.       }
  406.       else
  407.       { fprintf(stderr, "Line %ld, Error: Expected Basename.\n", linenum);
  408.       }
  409.     }
  410.     else if (strnicmp((char *) line, "##bias", 6) == 0)
  411.     { STRPTR ptr;
  412.       LONG newbias;
  413.  
  414.       newbias = strtol((char *) line+6, (char **) &ptr, 0);
  415.       if (ptr == line+6)
  416.       { fprintf(stderr, "Line %ld, Error: Expected Bias value.\n", linenum);
  417.       }
  418.       else
  419.       { if (newbias < 0)
  420.     { fprintf(stderr, "Line %ld, warning: Assuming positive value.\n",
  421.           linenum);
  422.       bias = -newbias;
  423.     }
  424.     else
  425.     { bias = newbias;
  426.     }
  427.       }
  428.       if (*SkipBlanks(ptr))
  429.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  430.       }
  431.     }
  432.     else if (strnicmp((char *) line, "##end", 5) == 0)
  433.     { if (*SkipBlanks(line+5))
  434.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  435.       }
  436.       break;
  437.     }
  438.     else if (strnicmp((char *) line, "##public", 8) == 0)
  439.     { if (*SkipBlanks(line+8))
  440.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  441.       }
  442.       public = TRUE;
  443.     }
  444.     else if (strnicmp((char *) line, "##private", 9) == 0)
  445.     { if (*SkipBlanks(line+9))
  446.       { fprintf(stderr, "Line %ld, warning: Extra characters\n", linenum);
  447.       }
  448.       public = FALSE;
  449.     }
  450.     else
  451.     { STRPTR ptr, nextptr;
  452.       struct AmiPragma *newpragma;
  453.       ULONG len, numargs;
  454.  
  455.       ptr = SkipBlanks(line);
  456.       nextptr = SkipName(ptr);
  457.       if (!(len = nextptr-ptr))
  458.       { fprintf(stderr, "Line %ld, Error: Missing function name\n", linenum);
  459.     continue;
  460.       }
  461.  
  462.       if (!(newpragma = calloc(sizeof(*newpragma), 1))  ||
  463.       !(newpragma->FuncName = strndup(ptr, len)))
  464.       { MemError();
  465.     goto exit_ScanFDFile;
  466.       }
  467.  
  468.       if (*(ptr = SkipBlanks(nextptr)) != '(')
  469.       { fprintf(stderr, "Line %ld, Error: Expected '('.\n", linenum);
  470.     continue;
  471.       }
  472.  
  473.       do
  474.       { ptr = SkipBlanks(ptr+1);
  475.  
  476.     if (*ptr == ')' && newpragma->NumArgs == 0)
  477.     { break;
  478.     }
  479.  
  480.     if (newpragma->NumArgs == 14)
  481.     { fprintf(stderr, "Line %ld, Error: Too much arguments.\n", linenum);
  482.     }
  483.  
  484.     nextptr = SkipName(ptr);
  485.     if (!(len = nextptr-ptr))
  486.     { fprintf(stderr, "Line %ld, Error: Expected argument name.\n",
  487.           linenum);
  488.       goto continue_loop;
  489.     }
  490.  
  491.     if (!(ptr = strndup(ptr, len)))
  492.     { MemError();
  493.       goto exit_ScanFDFile;
  494.     }
  495.     newpragma->Args[newpragma->NumArgs++].ArgName = ptr;
  496.  
  497.     ptr = SkipBlanks(nextptr);
  498.     if (*ptr != ','  &&  *ptr != '/'  &&  *ptr != ')')
  499.     { fprintf(stderr, "Line %ld, Error: Expected ')'.\n", linenum);
  500.       goto continue_loop;
  501.     }
  502.       }
  503.       while (*ptr != ')');
  504.  
  505.       if (*(ptr = SkipBlanks(ptr+1)) != '(')
  506.       { fprintf(stderr, "Line %ld, Error: Expected '('.\n", linenum);
  507.     continue;
  508.       }
  509.  
  510.       numargs = 0;
  511.       do
  512.       { ULONG i;
  513.  
  514.     ptr = SkipBlanks(ptr+1);
  515.  
  516.     if (*ptr == ')'  &&  numargs == 0)
  517.     { break;
  518.     }
  519.  
  520.     if (numargs > newpragma->NumArgs)
  521.     { fprintf(stderr,
  522.           "Line %ld, Error: Number of arguments != number of registers.\n",
  523.           linenum);
  524.       goto continue_loop;
  525.     }
  526.  
  527.     nextptr = SkipName(ptr);
  528.     if (!(len = nextptr-ptr))
  529.     { fprintf(stderr, "Line %ld, Error: Expected register name.\n",
  530.           linenum);
  531.       goto continue_loop;
  532.     }
  533.  
  534.     for (i = 0;  i < 16;  i++)
  535.     { if (strnicmp((char *) RegNames[i], (char *) ptr, len) == 0)
  536.       { break;
  537.       }
  538.     }
  539.  
  540.     if (i > 16)
  541.     { fprintf(stderr, "Line %ld, Error: Expected register name.\n",
  542.           linenum);
  543.       goto continue_loop;
  544.     }
  545.     if (i > 14)
  546.     { fprintf(stderr,
  547.           "Line %ld, Error: %s not allowed as argument register.\n",
  548.           linenum, RegNames[i]);
  549.       goto continue_loop;
  550.     }
  551.  
  552.     newpragma->Args[numargs].ArgReg = i;
  553.  
  554.     for (i = 0;  i < numargs;  i++)
  555.     { if (newpragma->Args[numargs].ArgReg == newpragma->Args[i].ArgReg)
  556.       { fprintf(stderr, "Line %ld, Error: Register %s used twice.\n",
  557.             linenum, RegNames[newpragma->Args[numargs].ArgReg]);
  558.         goto continue_loop;
  559.       }
  560.     }
  561.     ++numargs;
  562.  
  563.     ptr = SkipBlanks(nextptr);
  564.     if (*ptr != ','  &&  *ptr != '/'  &&  *ptr != ')')
  565.     { fprintf(stderr, "Line %ld, Error: Expected ')'.\n", linenum);
  566.       goto continue_loop;
  567.     }
  568.       }
  569.       while (*ptr != ')');
  570.  
  571.       if (numargs < newpragma->NumArgs)
  572.       { fprintf(stderr,
  573.         "Line %ld, Error: Number of arguments != number of registers.\n",
  574.         linenum);
  575.     goto continue_loop;
  576.       }
  577.  
  578.       if (bias == -1)
  579.       { fprintf(stderr, "Line %ld, warning: Assuming bias of 30.\n",
  580.          linenum);
  581.     bias = 30;
  582.       }
  583.       newpragma->Bias = bias;
  584.       bias += 6;
  585.  
  586.       newpragma->Public = public;
  587.  
  588.       AddTail((struct List *) &AmiPragmaList, (struct Node *) newpragma);
  589.  
  590.       if (*SkipBlanks(ptr+1))
  591.       { fprintf(stderr, "Line %ld, warning: Extra characters.\n", linenum);
  592.       }
  593.     }
  594.  
  595. continue_loop:
  596.   ;
  597.   }
  598.  
  599.   if (!BaseName)
  600.   { fprintf(stderr, "Error: Missing Basename.\n");
  601.   }
  602.   else
  603.   { result = TRUE;
  604.   }
  605.  
  606. exit_ScanFDFile:
  607.   fclose(fp);
  608.   return(result);
  609. }
  610.  
  611.  
  612.  
  613.  
  614.  
  615. /*
  616.     This function is similar to puts, but converts the string to lowercase.
  617.  
  618.     Inputs: Str - the string to write
  619.         Fp    - the file where to write to
  620.  
  621.     Result: TRUE, if successful, FALSE otherwise
  622. */
  623. ULONG fputslower(const STRPTR Str, FILE *Fp)
  624.  
  625. { STRPTR str = Str;
  626.  
  627.   while(*str)
  628.   { if (putc(tolower((int) *str++), Fp) == EOF)
  629.     { return(FALSE);
  630.     }
  631.   }
  632.   return(TRUE);
  633. }
  634.  
  635.  
  636.  
  637.  
  638.  
  639. /*
  640.     This function is similar to puts, but converts the string to uppercase.
  641.  
  642.     Inputs: Str - the string to write
  643.         Fp    - the file where to write to
  644.  
  645.     Result: TRUE, if successful, FALSE otherwise
  646. */
  647. ULONG fputsupper(const STRPTR Str, FILE *Fp)
  648.  
  649. { STRPTR str = Str;
  650.  
  651.   while(*str)
  652.   { if (putc(toupper((int) *str++), Fp) == EOF)
  653.     { return(FALSE);
  654.     }
  655.   }
  656.   return(TRUE);
  657. }
  658.  
  659.  
  660.  
  661.  
  662.  
  663. /*
  664.     This function writes the header of a pragma file.
  665.  
  666.     Inputs: Fp        - the file to write to.
  667.         Type    - Either "pragmas" or "lib", depending on the
  668.               typical pragma name. (Aztec uses something
  669.               like "pragmas/exec_pragmas.h" while SAS, Dice
  670.               and MAXON prefer "pragmas/exec_lib.h".)
  671.  
  672.     Result: TRUE, if successful, FALSE otherwise
  673. */
  674. ULONG WriteHeader(FILE *Fp, const STRPTR Type)
  675.  
  676. {
  677.   if (fputs("#ifndef PRAGMAS_", Fp) < 0             ||
  678.       !fputsupper(ShortBaseName, Fp)                ||
  679.       (putc('_', Fp) == EOF)                        ||
  680.       !fputsupper(Type, Fp)                         ||
  681.       fputs("_H\n#define PRAGMAS_", Fp) < 0         ||
  682.       !fputsupper(ShortBaseName, Fp)                ||
  683.       (putc('_', Fp) == EOF)                        ||
  684.       !fputsupper(Type, Fp)                         ||
  685.       fputs("_H\n\n#ifndef CLIB_", Fp) < 0          ||
  686.       !fputsupper(ShortBaseName, Fp)                ||
  687.       fputs("_PROTOS_H\n#include <clib/", Fp) < 0   ||
  688.       !fputslower(ShortBaseName, Fp)                ||
  689.       fputs("_protos.h>\n#endif\n\n", Fp) < 0)
  690.   { return(FALSE);
  691.   }
  692.  
  693.   return(TRUE);
  694. }
  695.  
  696.  
  697.  
  698.  
  699.  
  700. /*
  701.     This function writes the footer of a pragma file.
  702.  
  703.     Inputs: Fp        - the file to write to.
  704.         Type    - Either "pragmas" or "lib", depending on the
  705.               typical pragma name. (Aztec uses something
  706.               like "pragmas/exec_pragmas.h" while SAS, Dice
  707.               and MAXON prefer "pragmas/exec_lib.h".)
  708.  
  709.     Result: TRUE, if successful, FALSE otherwise
  710. */
  711. ULONG WriteFooter(FILE *Fp, const STRPTR Type)
  712.  
  713. {
  714.   if (fputs("\n#endif\t/*  PRAGMAS_", Fp) < 0   ||
  715.       !fputsupper(ShortBaseName, Fp)            ||
  716.       (putc('_', Fp) == EOF)                    ||
  717.       !fputsupper(Type, Fp)                     ||
  718.       fputs("_H  */\n", Fp) < 0)
  719.   { return(FALSE);
  720.   }
  721.  
  722.   return(TRUE);
  723. }
  724.  
  725.  
  726.  
  727.  
  728.  
  729. /*
  730.     This function writes one pragma for Aztec-C.
  731.  
  732.     Inputs: Ap    - a pointer to the pragma which should be written.
  733.         Fp    - the file to write to
  734.  
  735.     Result: TRUE, if successful, FALSE otherwise
  736. */
  737. ULONG WriteAztecPragma(struct AmiPragma *Ap, FILE *Fp)
  738.  
  739. { int i;
  740.  
  741.   if (!Ap->Public)
  742.   { return(TRUE);
  743.   }
  744.  
  745.   if (fprintf(Fp, "#pragma amicall(%s,0x%lx,%s(",
  746.           BaseName, Ap->Bias, Ap->FuncName) < 0)
  747.   { return(FALSE);
  748.   }
  749.  
  750.   for (i = 0;  i < Ap->NumArgs;  ++i)
  751.   { if (!fputslower(RegNames[Ap->Args[i].ArgReg], Fp))
  752.     { return(FALSE);
  753.     }
  754.     if (i+1 < Ap->NumArgs  &&  putc(',', Fp) == EOF)
  755.     { return(FALSE);
  756.     }
  757.   }
  758.  
  759.   if (fputs("))\n", Fp) < 0)
  760.   { return(FALSE);
  761.   }
  762.  
  763.   return(TRUE);
  764. }
  765.  
  766.  
  767.  
  768.  
  769.  
  770. /*
  771.     This function writes one pragma for SAS-C.
  772.  
  773.     Inputs: Ap        - a pointer to the pragma which should be written.
  774.         Fp        - the file to write to
  775.         TagCall - TRUE for a tagcall pragma, FALSE for a libcall pragma
  776.  
  777.     Result: TRUE, if successful, FALSE otherwise
  778. */
  779. ULONG WriteSASPragma(struct AmiPragma *Ap, FILE *Fp, ULONG TagCall)
  780.  
  781. { int i;
  782.  
  783.   if (!Ap->Public)
  784.   { return(TRUE);
  785.   }
  786.  
  787.   if (fprintf(Fp, "#pragma %s %s %s %lx ",
  788.           TagCall ? "tagcall" : "libcall",
  789.           BaseName,
  790.           TagCall ? Ap->TagName : Ap->FuncName,
  791.           Ap->Bias) < 0)
  792.   { return(FALSE);
  793.   }
  794.  
  795.   for (i = Ap->NumArgs-1;  i >= 0;  --i)
  796.   { if ((fputc((int) HexDigits[Ap->Args[i].ArgReg], Fp) == EOF))
  797.     { return(FALSE);
  798.     }
  799.   }
  800.  
  801.   if (fprintf(Fp, "0%lc\n", HexDigits[Ap->NumArgs]) < 0)
  802.   { return(FALSE);
  803.   }
  804.  
  805.   return(TRUE);
  806. }
  807.  
  808.  
  809.  
  810.  
  811.  
  812. /*
  813.     This function creates a pragmas file.
  814.  
  815.     Inputs: PragmaFile    - name of the file to be created.
  816.         PragmaExt    - TRUE, if the typical pragma filename is similar to
  817.               clib/exec_pragmas.h, FALSE for clib/exec_lib.h
  818.         SASPragmas    - TRUE for SAS-like pragmas, FALSE for Aztec
  819.         UseTags    - TRUE, if tagcall pragmas should be created.
  820.         Prototype    - TRUE, if a prototype for the library basepointer
  821.               should be created. (Dice seems to need this.)
  822.  
  823.     Result: TRUE, if successful, FALSE otherwise
  824. */
  825. ULONG CreatePragmaFile(const STRPTR PragmaFile, ULONG PragmaExt,
  826.                ULONG SASPragmas, ULONG UseTags, ULONG Prototype)
  827.  
  828. { FILE *fp;
  829.   struct AmiPragma *ap;
  830.   ULONG result = FALSE;
  831.   ULONG tagcall_seen = FALSE;
  832.  
  833.   if (!(fp = fopen((char *) PragmaFile, "w")))
  834.   { fprintf(stderr, "Error: Cannot open %s for writing.\n", PragmaFile);
  835.     return(FALSE);
  836.   }
  837.  
  838.   if (!WriteHeader(fp, (STRPTR) (PragmaExt ? "pragmas" : "lib")))
  839.   { goto exit_CreatePragmaFile;
  840.   }
  841.  
  842.   if (Prototype  &&
  843.       fprintf(fp, "extern struct Library *%s;\n\n", BaseName) < 0)
  844.   { goto exit_CreatePragmaFile;
  845.   }
  846.  
  847.   /*
  848.       Write the pragmas.
  849.   */
  850.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  851.        ap->Node.mln_Succ;
  852.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  853.   { if ((SASPragmas  &&  !WriteSASPragma(ap, fp, FALSE))  ||
  854.     (!SASPragmas  &&  !WriteAztecPragma(ap, fp)))
  855.     { goto exit_CreatePragmaFile;
  856.     }
  857.     if (ap->TagName  &&  ap->Public)
  858.     { tagcall_seen = TRUE;
  859.     }
  860.   }
  861.   if (tagcall_seen  &&  UseTags)
  862.   { if (fputs("\n#ifdef __SASC_60\n", fp) < 0)
  863.     { goto exit_CreatePragmaFile;
  864.     }
  865.  
  866.     for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  867.      ap->Node.mln_Succ;
  868.      ap = (struct AmiPragma *) ap->Node.mln_Succ)
  869.      { if (ap->TagName  &&  !WriteSASPragma(ap, fp, TRUE))
  870.        { goto exit_CreatePragmaFile;
  871.        }
  872.      }
  873.  
  874.     if (fputs("#endif\t/*  __SASC_60  */\n", fp) < 0)
  875.     { goto exit_CreatePragmaFile;
  876.     }
  877.    }
  878.  
  879.   /*
  880.       Write the footer.
  881.   */
  882.   if (!WriteFooter(fp, (STRPTR) (PragmaExt ? "pragmas" : "lib")))
  883.   { goto exit_CreatePragmaFile;
  884.   }
  885.  
  886.   result = TRUE;
  887.  
  888. exit_CreatePragmaFile:
  889.   if (!result)
  890.   { fprintf(stderr, "Error while writing %s.\n", PragmaFile);
  891.   }
  892.   fclose(fp);
  893.   return(result);
  894. }
  895.  
  896.  
  897.  
  898.  
  899.  
  900. /*
  901.     This function creates a LVO file.
  902.  
  903.     Inputs: LVOFile - the name of the file
  904.  
  905.     Result: TRUE, if successful, FALSE otherwise
  906. */
  907. ULONG CreateLVOFile(const STRPTR LVOFile)
  908.  
  909. { FILE *fp;
  910.   struct AmiPragma *ap;
  911.   ULONG result;
  912.  
  913.   if (!(fp = fopen((char *) LVOFile, "w")))
  914.   { fprintf(stderr, "Error: Cannot open %s for writing.\n", LVOFile);
  915.     return(FALSE);
  916.   }
  917.  
  918.   if (fputs("\t\tIFND ", fp) < 0            ||
  919.       !fputsupper(ShortBaseName, fp)        ||
  920.       fputs("_LIB_I\n", fp) < 0             ||
  921.       !fputsupper(ShortBaseName, fp)        ||
  922.       fputs("_LIB_I\tSET\t1\n\n", fp) > 0)
  923.   { goto exit_CreateLVOFile;
  924.   }
  925.  
  926.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  927.        ap->Node.mln_Succ;
  928.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  929.   { if (ap->Public  &&
  930.     fprintf(fp, "\t\tXDEF\t_LVO%s\n", ap->FuncName) < 0)
  931.     { goto exit_CreateLVOFile;
  932.     }
  933.   }
  934.  
  935.   if (fputs("\n\n", fp) < 0)
  936.   { goto exit_CreateLVOFile;
  937.   }
  938.  
  939.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  940.        ap->Node.mln_Succ;
  941.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  942.   { if (ap->Public  &&
  943.     fprintf(fp, "_LVO%s\tEQU\t-%ld\n", ap->FuncName, ap->Bias) < 0)
  944.     { goto exit_CreateLVOFile;
  945.     }
  946.   }
  947.  
  948.   if (fputs("\n\t\tEND", fp) < 0)
  949.   { goto exit_CreateLVOFile;
  950.   }
  951.  
  952.   result = TRUE;
  953.  
  954. exit_CreateLVOFile:
  955.   if (!result)
  956.   { fprintf(stderr, "Error while writing %s.\n", LVOFile);
  957.   }
  958.   fclose(fp);
  959.   return(result);
  960. }
  961.  
  962.  
  963.  
  964.  
  965.  
  966. /*
  967.     This function creates stub routines for the tag functions.
  968.  
  969.     Inputs: TagDir  - a pointer to the directory, where to store the created
  970.               sources.
  971.  
  972.     Result: TRUE, if successful, FALSE otherwise
  973. */
  974. ULONG CreateTagFuncs(const STRPTR TagDir)
  975.  
  976. { FILE *fp;
  977.   struct AmiPragma *ap;
  978.  
  979.   for (ap = (struct AmiPragma *) AmiPragmaList.mlh_Head;
  980.        ap->Node.mln_Succ;
  981.        ap = (struct AmiPragma *) ap->Node.mln_Succ)
  982.   { if (ap->TagName  &&  ap->Public)
  983.     { STRPTR sourcename;
  984.       ULONG size = strlen((char *) TagDir) +
  985.            strlen((char *) ap->TagName) + 128;
  986.       ULONG i;
  987.       ULONG result = FALSE;
  988.  
  989.       /*
  990.       Get name of sourcefile to create.
  991.       */
  992.       if (!(sourcename = strndup(TagDir, size)))
  993.       { MemError();
  994.     return(FALSE);
  995.       }
  996.       AddPart(sourcename, ap->TagName, size);
  997.       strcat((char *) sourcename, ".c");
  998.  
  999.       /*
  1000.       Open sourcefile.
  1001.       */
  1002.       if (!(fp = fopen((char *) sourcename, "w")))
  1003.       { fprintf(stderr, "Error: Cannot open %s for writing.\n", sourcename);
  1004.     return(FALSE);
  1005.       }
  1006.  
  1007.       if (fputs("typedef unsigned long ULONG;\n", fp) < 0               ||
  1008.       fprintf(fp, "extern struct Library *%s;\n", BaseName) < 0     ||
  1009.       fprintf(fp, "extern ULONG %s(", ap->FuncName) < 0)
  1010.       { goto exit_CreateTagFuncs;
  1011.       }
  1012.       for(i = 0;  i < ap->NumArgs;  i++)
  1013.       { if (fputs("ULONG", fp) < 0)
  1014.     { goto exit_CreateTagFuncs;
  1015.     }
  1016.     if (i+1 < ap->NumArgs  &&  fputs(", ", fp) < 0)
  1017.     { goto exit_CreateTagFuncs;
  1018.     }
  1019.       }
  1020.       if (fputs(");\n\n", fp) < 0                                           ||
  1021.       fputs("#if defined(AZTEC_C)  ||  defined(__MAXON__)\n", fp) < 0   ||
  1022.       !WriteAztecPragma(ap, fp)                                         ||
  1023.       fputs("#endif\n\n", fp) < 0                                       ||
  1024.       fputs("#if defined(_DCC)  ||  defined(__SASC)\n", fp) < 0         ||
  1025.       !WriteSASPragma(ap, fp, FALSE)                                    ||
  1026.       fputs("#endif\n\n\n", fp) < 0                                     ||
  1027.       fprintf(fp, "ULONG %s(", ap->TagName) < 0)
  1028.       { goto exit_CreateTagFuncs;
  1029.       }
  1030.       for (i = 0;  i < ap->NumArgs;  i++)
  1031.       { if (fprintf(fp, "ULONG %s, ", ap->Args[i].ArgName) < 0)
  1032.     { goto exit_CreateTagFuncs;
  1033.     }
  1034.       }
  1035.       if (fputs("...)\n\n", fp) < 0                         ||
  1036.       fprintf(fp, "{ return(%s(", ap->FuncName) < 0)
  1037.       { goto exit_CreateTagFuncs;
  1038.       }
  1039.       for (i = 0;  i < ap->NumArgs-1;  i++)
  1040.       { if (fprintf(fp, "%s, ", ap->Args[i].ArgName) < 0)
  1041.     { goto exit_CreateTagFuncs;
  1042.     }
  1043.       }
  1044.       if (fprintf(fp, "(ULONG) &%s));\n}\n", ap->Args[ap->NumArgs-1].ArgName) < 0)
  1045.       { goto exit_CreateTagFuncs;
  1046.       }
  1047.  
  1048.       result = TRUE;
  1049.  
  1050. exit_CreateTagFuncs:
  1051.       if (!result)
  1052.       { fprintf(stderr, "Error while writing %s.\n", sourcename);
  1053.       }
  1054.       fclose(fp);
  1055.       free(sourcename);
  1056.       if (!result)
  1057.       { return(FALSE);
  1058.       }
  1059.     }
  1060.   }
  1061.  
  1062.   return(TRUE);
  1063. }
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069. /*
  1070.     This is main().
  1071. */
  1072. void main (int argc, char *argv[])
  1073.  
  1074. { struct RDArgs *rdargs;
  1075.   struct
  1076.   { STRPTR FDFILE;
  1077.     STRPTR AZTEC;
  1078.     STRPTR AS;
  1079.     STRPTR SAS;
  1080.     STRPTR DICE;
  1081.     STRPTR MAXON;
  1082.     STRPTR TAGDIR;
  1083.     ULONG HELP;
  1084.   } args = {NULL, NULL, NULL, NULL, NULL, NULL, FALSE};
  1085.   extern struct Library *SysBase;
  1086.  
  1087.   if (!argc)        /*  Prevent calling from Workbench.     */
  1088.   { exit(-1);
  1089.   }
  1090.  
  1091.   if (SysBase->lib_Version < 36)
  1092.   { fprintf(stderr, "Need at least Kickstart 2.0.\n");
  1093.     exit(20);
  1094.   }
  1095.  
  1096.   if (!(rdargs = ReadArgs((STRPTR) TEMPLATE, (LONG *) &args, NULL)))
  1097.   { Usage();
  1098.   }
  1099.  
  1100.   if(args.HELP)
  1101.   { Usage();
  1102.   }
  1103.  
  1104.   if (ScanFDFile(args.FDFILE))
  1105.   { if ((args.AZTEC  &&
  1106.      !CreatePragmaFile(args.AZTEC, FALSE, FALSE, FALSE, FALSE))         ||
  1107.     (args.AS  &&
  1108.      !CreateLVOFile(args.AS))                                           ||
  1109.     (args.SAS  &&
  1110.      !CreatePragmaFile(args.SAS, TRUE, TRUE, TRUE, FALSE))              ||
  1111.     (args.MAXON  &&
  1112.      !CreatePragmaFile(args.MAXON, TRUE, FALSE, FALSE, FALSE))          ||
  1113.     (args.DICE  &&
  1114.      !CreatePragmaFile(args.DICE, TRUE, TRUE, FALSE, TRUE))             ||
  1115.     (args.TAGDIR  &&
  1116.      !CreateTagFuncs(args.TAGDIR)))
  1117.     { exit(5);
  1118.     }
  1119.   }
  1120.   exit(0);
  1121. }
  1122.