home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / fd2inline-1.0-src.tgz / tar.out / contrib / fd2inline / fd2inline.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  44KB  |  1,941 lines

  1. /******************************************************************************
  2.  *
  3.  * fd2inline
  4.  *
  5.  * Should be able to parse AmigaOS fd files and generate vanilla inline calls
  6.  * for gcc. Works as a filter. This is a 0.9 evaluation version.
  7.  * Don't expect miracles (yet...).
  8.  *
  9.  * by Wolfgang Baron, all rights reserved.
  10.  *
  11.  * improved, updated, simply made workable by Rainer F. Trunz 1/95
  12.  *
  13.  * Completely reworked Version, cleaned up and removed a whole lot of bugs
  14.  * found by Kamil Iskra.
  15.  *
  16.  * Expect miracles now (hopefully...). Ok, I am just kidding :)
  17.  *
  18.  * Version 0.99a by Rainer F. Trunz 6/95
  19.  *
  20.  * Version 0.99b by Kamil Iskra 10/95 - removed all serious limitations,
  21.  *   added support for new "inline" format.
  22.  *
  23.  * Version 0.99c by Kamil Iskra 11/95 - added support for "library stubs",
  24.  *   slightly modified "old" output, fixed bug in DateStamp() parsing.
  25.  *
  26.  * Version 0.99d by Kamil Iskra 12/95 - changed output of "new" inlines to
  27.  *   support their enhanced version.
  28.  *
  29.  ******************************************************************************/
  30.  
  31. #include <ctype.h>
  32. #include <stddef.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36.  
  37. /******************************************************************************
  38.  * The program has a few sort of class definitions, which are the result of
  39.  * object oriented thinking, to be imlemented in plain C. I just haven't
  40.  * had the time to learn C++ or install the compiler. The design does however
  41.  * improve robustness, which allows the source to be used over and over again.
  42.  * if you use this code, please leave a little origin note.
  43.  ******************************************************************************/
  44.  
  45. const static char version_str[]="$VER: fd2inline " VERSION " (14.07.96)";
  46.  
  47. /******************************************************************************
  48.  * These are general definitions including types for defining registers etc.
  49.  ******************************************************************************/
  50.  
  51. #ifdef DEBUG
  52. #define DBP(a) a
  53. #else /* !DEBUG */
  54. #define DBP(a)
  55. #endif /* !DEBUG */
  56.  
  57. #if (defined(__GNUC__) || defined(__SASC)) && 0
  58. #define INLINE __inline /* Gives 20% *larger* executable with GCC?! */
  59. #else
  60. #define INLINE
  61. #endif
  62.  
  63. #define REGS 16  /* d0=0,...,a7=15 */
  64. #define FDS 1000
  65.  
  66. typedef enum
  67. {
  68.     d0, d1, d2, d3, d4, d5, d6, d7, a0, a1, a2, a3, a4, a5, a6, a7, illegal
  69. } regs;
  70.  
  71. typedef unsigned char uchar, shortcard;
  72. typedef unsigned long ulong;
  73.  
  74. typedef enum { false, nodef, real_error } Error;
  75.  
  76. enum {NEW, OLD, STUBS} output_mode=NEW;
  77.  
  78. char BaseName[32];
  79. char BaseNamU[32];
  80.  
  81. const static char *LibExcTable[]=
  82. {
  83.     "BattClockBase",            "Node",
  84.     "BattMemBase",                "Node",
  85.     "ConsoleDevice",            "Device",
  86.     "DiskBase",                    "DiskResource",
  87.     "DOSBase",                    "DosLibrary",
  88.     "SysBase",                    "ExecBase",
  89.     "ExpansionBase",            "ExpansionBase",
  90.     "GfxBase",                    "GfxBase",
  91.     "InputBase",                "Device",
  92.     "IntuitionBase",            "IntuitionBase",
  93.     "LocaleBase",                "LocaleBase",
  94.     "MathIeeeDoubBasBase",    "MathIEEEBase",
  95.     "MathIeeeDoubTransBase","MathIEEEBase",
  96.     "MathIeeeSingBasBase",    "MathIEEEBase",
  97.     "MathIeeeSingTransBase","MathIEEEBase",
  98.     "MiscBase",                    "Node",
  99.     "PotgoBase",                "Node",
  100.     "RamdriveDevice",            "Device",
  101.     "RealTimeBase",            "RealTimeBase",
  102.     "RexxSysBase",                "RxsLib",
  103.     "TimerBase",                "Device",
  104.     "UtilityBase",                "UtilityBase"
  105. };
  106. const char * StdLib;    /* global lib-name ptr */
  107.  
  108. /*******************************************
  109.  * just some support functions, no checking
  110.  *******************************************/
  111.  
  112. char *
  113. NewString(char **new, const char *old)
  114. {
  115.     const char *high;
  116.     ulong len;
  117.  
  118.     while (*old && (*old==' ' || *old=='\t'))
  119.         old++;
  120.     len=strlen(old);
  121.     for (high=old+len-1; high>=old && (*high==' ' || *high=='\t'); high--);
  122.     high++;
  123.     len=high-old;
  124.     *new=malloc(1+len);
  125.     if (*new)
  126.     {
  127.         strncpy(*new, old, len);
  128.         (*new)[len]='\0';
  129.     }
  130.     else
  131.         fprintf(stderr, "no mem for string\n");
  132.     return *new;
  133. }
  134.  
  135. static INLINE void
  136. illparams(const char *funcname)
  137. {
  138.     fprintf(stderr, "%s: illegal Parameters\n", funcname);
  139. }
  140.  
  141. static INLINE const char*
  142. RegStr(regs reg)
  143. {
  144.     const static char *myregs[]=
  145.     {
  146.         "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  147.         "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "illegal"
  148.     };
  149.  
  150.     if (reg>illegal)
  151.         reg=illegal;
  152.     if (reg<d0)
  153.         reg=d0;
  154.     return myregs[reg];
  155. }
  156.  
  157. /******************************************************************************
  158.  *    StrNRBrk
  159.  *
  160.  * searches string in from position at downwards, as long as in does not
  161.  * contain any character in not.
  162.  *
  163.  ******************************************************************************/
  164.  
  165. const char *
  166. StrNRBrk(const char *in, const char *not, const char *at)
  167. {
  168.     const char *chcheck;
  169.     Error ready;
  170.  
  171.     chcheck=""; /* if at<in, the result will be NULL */
  172.     for (ready=false; ready==false && at>=in;)
  173.     {
  174.         for (chcheck=not; *chcheck && *chcheck != *at; chcheck++);
  175.         if (*chcheck)
  176.             ready=real_error;
  177.         else
  178.             at--;
  179.     }
  180.     DBP(fprintf(stderr, "{%c}", *chcheck));
  181.     return *chcheck ? at : NULL;
  182. }
  183.  
  184. /*
  185.   Our own "strupr", since it is a non-standard function.
  186. */
  187. void
  188. StrUpr(char *str)
  189. {
  190.     while (*str)
  191.     {
  192.         *str=toupper(*str);
  193.         str++;
  194.     }
  195. }
  196.  
  197. /******************************************************************************
  198.  *    binSearch
  199.  *
  200.  * A binary search routine, wich operates on an array like you would use
  201.  * for qsort. The prototype does not contain the (*) bug...
  202.  *
  203.  * returns the address of the (a?) fitting object, or NULL;
  204.  *
  205.  * the binary intersection is (low+high)/2, so the highest value will never
  206.  * be reached, but the lowest value will. In the while condition, the diff
  207.  * has to be called last in case we got an empty array.
  208.  *
  209.  ******************************************************************************/
  210.  
  211. void*
  212. binSearch(void ** array, size_t elements, const void *lookfor,
  213.              int cmpfunc(const void **, const void **))
  214. {
  215.     size_t low, high, index;
  216.     int diff;
  217.  
  218.     DBP(fprintf(stderr, "bs(%ld): ", (long)elements));
  219.  
  220.     diff=1; /* this needs to be so in case we got an empty array... */
  221.  
  222.     low=0;
  223.     high=elements; /* our algorithm never reaches elements */
  224.  
  225.     while (index=(high+low)/2,  /* somewhere inbetween */
  226.     high!=low && (diff=cmpfunc((const void **)array+index,
  227.     &lookfor)))
  228.     {
  229.         if (diff>0)
  230.         {
  231.             high=index; /* our value was too big, so grow downwards */
  232.             DBP(fprintf(stderr, "<"));
  233.         }
  234.         else
  235.         {
  236.             low=index+1; /* the low value will be reached */
  237.             DBP(fprintf(stderr, ">"));
  238.         }
  239.         DBP(fprintf(stderr, "%ld ", (long)index));
  240.     }
  241.     DBP(fprintf(stderr, "->%ld\n", diff ? -1L : (long)index));
  242.     return diff ? NULL : array[index]; /* bingo */
  243. }
  244.  
  245. /******************************************************************************
  246.  *    CLASS fdFile
  247.  *
  248.  * stores a file with a temporary buffer (static length, sorry), a line number,
  249.  * an offset (used for library offsets and an error field.
  250.  * When there's no error, line will contain line #lineno and offset will be
  251.  * the last offset set by the interpretation of the last line. If there's been
  252.  * no ##bias line, this field assumes a bias of 30, which is the standard bias.
  253.  * It is assumed offsets are always negative.
  254.  ******************************************************************************/
  255.  
  256. #define fF_BUFSIZE 1024
  257.  
  258. /* all you need to know about an fdFile you parse */
  259.  
  260. typedef struct
  261. {
  262.     FILE*    file;                    /* the file we're reading from        */
  263.     char    line[fF_BUFSIZE];    /* the current line                        */
  264.     ulong    lineno;                /* current line number                    */
  265.     long    offset;                /* current fd offset (-bias)            */
  266.     Error    error;                /* is everything o.k.                    */
  267.     char    private;                /* are we in ##public or ##private    */
  268. } fdFile;
  269.  
  270. fdFile*    fF_ctor            (const char *fname);
  271. static
  272. void        fF_dtor            (fdFile *obj);
  273. static
  274. void        fF_SetError        (fdFile *obj, Error error);
  275. static
  276. void        fF_SetOffset    (fdFile *obj, long at);
  277. Error        fF_readln        (fdFile *obj);
  278. static
  279. Error        fF_GetError        (const fdFile *obj);
  280. static
  281. long        fF_GetOffset    (const fdFile *obj);
  282. char*        fF_FuncName        (fdFile *obj); /* return name or null */
  283. static
  284. void        fF_SetPrivate    (fdFile *obj, char priv);
  285. static
  286. char        fF_GetPrivate    (const fdFile *obj);
  287.  
  288. static INLINE void
  289. fF_dtor(fdFile *obj)
  290. {
  291.   fclose(obj->file);
  292.   free(obj);
  293. }
  294.  
  295. static INLINE void
  296. fF_SetError(fdFile *obj, Error error)
  297. {
  298.     if (obj)
  299.         obj->error=error;
  300.     else
  301.         illparams("fF_SetError");
  302. }
  303.  
  304. static INLINE void
  305. fF_SetOffset(fdFile *obj, long at)
  306. {
  307.     if (obj)
  308.         obj->offset= at;
  309.     else
  310.         illparams("fFSetOffset");
  311. }
  312.  
  313. static INLINE void
  314. fF_SetPrivate(fdFile *obj, char priv)
  315. {
  316.   if (obj)
  317.     obj->private=priv;
  318.   else
  319.     illparams("fF_SetPrivate");
  320. }
  321.  
  322. fdFile *
  323. fF_ctor(const char *fname)
  324. {
  325.     fdFile *result;
  326.  
  327.     if (fname)
  328.     {
  329.         result=malloc(sizeof(fdFile));
  330.         if (result)
  331.         {
  332.             result->file=fopen(fname, "r");
  333.             if (result->file)
  334.             {
  335.                 result->lineno=0;
  336.                 fF_SetOffset(result, -30);
  337.                 fF_SetError(result, false);
  338.                 fF_SetPrivate(result, 0);
  339.                 result->line[0]='\0';
  340.             }
  341.             else
  342.             {
  343.                 free(result);
  344.                 result=NULL;
  345.             }
  346.         }
  347.     }
  348.     else
  349.     {
  350.         result=NULL;
  351.         illparams("fF_ctor");
  352.     }
  353.     return result;
  354. }
  355.  
  356. Error
  357. fF_readln(fdFile *obj)
  358. {
  359.     char *low, *bpoint;
  360.     long glen,    /* the length we read until now */
  361.     len;            /* the length of the last segment */
  362.  
  363.     if (obj)
  364.     {
  365.         low=obj->line;
  366.         glen=0;
  367.  
  368.         for (;;)
  369.         {
  370.             obj->lineno++;
  371.             if (!fgets(low, fF_BUFSIZE-1-glen, obj->file))
  372.             {
  373.                 fF_SetError(obj, real_error);
  374.                 obj->line[0]='\0';
  375.                 return real_error;
  376.             }
  377.             if (low==strpbrk(low, "*#/"))
  378.             {
  379.                 DBP(fprintf(stderr, "in# %s\n", obj->line));
  380.                 return false;
  381.             }
  382.             len=strlen(low);
  383.             bpoint=low+len-1;
  384.             while (len && isspace(*bpoint))
  385.             {
  386.                 bpoint--;
  387.                 len--;
  388.             }
  389.             if (*bpoint==';' || *bpoint==')')
  390.             {
  391.                 DBP(fprintf(stderr, "\nin: %s\n", obj->line));
  392.                 return false;
  393.             }
  394.             glen+=len;
  395.             low+=len;
  396.             if (glen>=fF_BUFSIZE-10) /* somewhat pessimistic? */
  397.             {
  398.                 fF_SetError(obj, real_error);
  399.                 fprintf(stderr, "line %lu too long.\n", obj->lineno);
  400.                 return real_error;
  401.             }
  402.             DBP(fprintf(stderr, "+"));
  403.         }
  404.     }
  405.     illparams("fF_readln");
  406.     return real_error;
  407. }
  408.  
  409. static INLINE Error
  410. fF_GetError(const fdFile *obj)
  411. {
  412.     if (obj)
  413.         return obj->error;
  414.     illparams("fF_GetError");
  415.     return real_error;
  416. }
  417.  
  418. static INLINE long
  419. fF_GetOffset(const fdFile *obj)
  420. {
  421.     if (obj)
  422.         return obj->offset;
  423.     illparams("fF_GetOffset");
  424.     return -1;
  425. }
  426.  
  427. /******************************************************************************
  428.  * fF_FuncName
  429.  *
  430.  * checks if it can find a function-name and return it's address, or NULL
  431.  * if the current line does not seem to contain one. The return value will
  432.  * be a pointer into a malloced buffer, thus the caller will have to free().
  433.  ******************************************************************************/
  434.  
  435. char *
  436. fF_FuncName(fdFile *obj)
  437. {
  438.     const char *lower;
  439.     const char *upper;
  440.     char *buf;
  441.     long obraces;    /* count of open braces */
  442.     Error ready;    /* ready with searching */
  443.  
  444.     if (!obj || fF_GetError(obj)==real_error)
  445.     {
  446.         illparams("fF_FuncName");
  447.         return NULL;
  448.     }
  449.     if (obj->line==strpbrk(obj->line, "#*/"))
  450.     {
  451.         fF_SetError(obj, nodef);
  452.         return NULL;
  453.     }
  454.  
  455.     lower=NULL;
  456.     buf=NULL;
  457.  
  458.     if (obj && fF_GetError(obj)==false)
  459.     {
  460.         if ((upper=strrchr(obj->line, ')'))!=0)
  461.         {
  462.             DBP(fprintf(stderr, "end:%s:", upper));
  463.  
  464.             for (obraces=1, ready=false; ready==false; upper=lower)
  465.             {
  466.                 lower=StrNRBrk(obj->line, "()", --upper);
  467.                 if (lower)
  468.                 {
  469.                     switch (*lower)
  470.                     {
  471.                         case ')':
  472.                             obraces++;
  473.                             DBP(fprintf(stderr, " )%ld%s", obraces, lower));
  474.                             break;
  475.                         case '(':
  476.                             obraces--;
  477.                             DBP(fprintf(stderr, " (%ld%s", obraces, lower));
  478.                             if (!obraces)
  479.                                 ready=nodef;
  480.                             break;
  481.                         default:
  482.                             fprintf(stderr, "faulty StrNRBrk\n");
  483.                     }
  484.                 }
  485.                 else
  486.                 {
  487.                     fprintf(stderr, "'(' or ')' expected in line %lu.\n",
  488.                         obj->lineno);
  489.                     ready=real_error;
  490.                 }
  491.             }
  492.             if (ready==nodef) /* we found the matching '(' */
  493.             {
  494.                 long newlen;
  495.  
  496.                 upper--;
  497.  
  498.                 while (upper>=obj->line && (*upper==' ' || *upper=='\t'))
  499.                     upper--;
  500.  
  501.                 lower=StrNRBrk(obj->line, " \t*)", upper);
  502.  
  503.                 if (!lower)
  504.                     lower=obj->line;
  505.                 else
  506.                     lower++;
  507.  
  508.                 newlen=upper-lower+2;
  509.                 buf=malloc(newlen);
  510.  
  511.                 if (buf)
  512.                 {
  513.                     strncpy(buf, lower, --newlen);
  514.                     buf[newlen]='\0';
  515.                 }
  516.                 else
  517.                     fprintf(stderr, "no mem for fF_FuncName");
  518.             }
  519.         }
  520.     }
  521.     else
  522.         illparams("fF_FuncName");
  523.     return buf;
  524. }
  525.  
  526. static INLINE char
  527. fF_GetPrivate(const fdFile *obj)
  528. {
  529.     if (obj)
  530.         return obj->private;
  531.     illparams("fF_GetPrivate");
  532.     return 0;
  533. }
  534.  
  535. /*********************
  536.  *    CLASS fdDef    *
  537.  *********************/
  538.  
  539. typedef struct
  540. {
  541.     char*    name;
  542.     char*    type;
  543.     long    offset;
  544.     regs    reg[REGS];
  545.     char*    param[REGS];
  546.     char*    proto[REGS];
  547.     regs    funcpar; /* number of argument that has type "pointer to function" */
  548. } fdDef;
  549.  
  550. fdDef*        fD_ctor                (void);
  551. void            fD_dtor                (fdDef *obj);
  552. static
  553. void            fD_NewName            (fdDef *obj, const char *newname);
  554. void            fD_NewParam            (fdDef *obj, shortcard at, const char *newstr);
  555. void            fD_NewProto            (fdDef *obj, shortcard at, char *newstr);
  556. static
  557. void            fD_NewReg            (fdDef *obj, shortcard at, regs reg);
  558. static
  559. void            fD_NewType            (fdDef *obj, const char *newstr);
  560. static
  561. void            fD_SetOffset        (fdDef *obj, long off);
  562. Error            fD_parsefd            (fdDef *obj, fdFile *infile);
  563. Error            fD_parsepr            (fdDef *obj, fdFile *infile);
  564. static
  565. const char*    fD_GetName            (const fdDef *obj);
  566. static
  567. long            fD_GetOffset        (const fdDef *obj);
  568. static
  569. const char*    fD_GetParam            (const fdDef *obj, shortcard at);
  570. static
  571. regs            fD_GetReg            (const fdDef *obj, shortcard at);
  572. static
  573. const char*    fD_GetRegStr        (const fdDef *obj, shortcard at);
  574. static
  575. const char*    fD_GetType            (const fdDef *obj);
  576. static
  577. shortcard    fD_ParamNum            (const fdDef *obj);
  578. static
  579. shortcard    fD_ProtoNum            (const fdDef *obj);
  580. static
  581. shortcard    fD_RegNum            (const fdDef *obj);
  582. int            fD_cmpName            (const fdDef **big, const fdDef **small);
  583. void            fD_write                (FILE *outfile, const fdDef *obj);
  584. static
  585. shortcard    fD_GetFuncParNum    (const fdDef *obj);
  586. static
  587. void            fD_SetFuncParNum    (fdDef *obj, shortcard at);
  588.  
  589. char *fD_nostring = "";
  590.  
  591. fdDef*
  592. fD_ctor(void)
  593. {
  594.     fdDef *result;
  595.     regs count;
  596.  
  597.     result=malloc(sizeof(fdDef));
  598.  
  599.     if (result)
  600.     {
  601.         result->name=fD_nostring;
  602.         result->type=fD_nostring;
  603.         result->funcpar=illegal;
  604.  
  605.         for (count=d0; count<illegal; count++ )
  606.         {
  607.             result->reg[count]=illegal;
  608.             result->param[count]=fD_nostring; /* if (!strlen) dont't free() */
  609.             result->proto[count]=fD_nostring;
  610.         }
  611.     }
  612.     return result;
  613. }
  614.  
  615. /* free all resources and make the object as illegal as possible */
  616.  
  617. void
  618. fD_dtor(fdDef *obj)
  619. {
  620.     regs count;
  621.  
  622.     if (obj)
  623.     {
  624.         if (!obj->name)
  625.             fprintf(stderr, "fD_dtor: null name");
  626.         else
  627.             if (obj->name!=fD_nostring)
  628.                 free(obj->name);
  629.  
  630.         if (!obj->type)
  631.             fprintf(stderr, "fD_dtor: null type");
  632.         else
  633.             if (obj->type!=fD_nostring)
  634.                 free(obj->type);
  635.  
  636.         obj->name=obj->type=NULL;
  637.  
  638.         for (count=d0; count<illegal; count++)
  639.         {
  640.             obj->reg[count]=illegal;
  641.  
  642.             if (!obj->param[count])
  643.                 fprintf(stderr, "fD_dtor: null param");
  644.             else
  645.                 if (obj->param[count]!=fD_nostring)
  646.                     free(obj->param[count]);
  647.  
  648.             if (!obj->proto[count])
  649.                 fprintf(stderr, "fD_dtor: null proto");
  650.             else
  651.                 if (obj->proto[count]!=fD_nostring)
  652.                     free(obj->proto[count]);
  653.  
  654.             obj->param[count]=obj->proto[count]=NULL;
  655.         }
  656.  
  657.         free(obj);
  658.     }
  659.     else
  660.         fprintf(stderr, "fd_dtor(NULL)\n");
  661. }
  662.  
  663. static INLINE void
  664. fD_NewName(fdDef *obj, const char *newname)
  665. {
  666.     if (obj && newname)
  667.     {
  668.         if (obj->name && obj->name!=fD_nostring)
  669.             free(obj->name);
  670.         if (!NewString(&obj->name, newname))
  671.             obj->name=fD_nostring;
  672.     }
  673.     else
  674.         illparams("fD_NewName");
  675. }
  676.  
  677. void
  678. fD_NewParam(fdDef *obj, shortcard at, const char *newstr)
  679. {
  680.     char *pa;
  681.  
  682.     if (newstr && obj && at<illegal)
  683.     {
  684.         pa=obj->param[at];
  685.  
  686.         if (pa && pa!=fD_nostring)
  687.             free(pa);
  688.  
  689.         while (*newstr==' ' || *newstr=='\t')
  690.             newstr++;
  691.  
  692.         if (NewString(&pa, newstr))
  693.             obj->param[at]=pa;
  694.         else
  695.             obj->param[at]=fD_nostring;
  696.     }
  697.     else
  698.         illparams("fD_NewParam");
  699. }
  700.  
  701. /* get first free *reg or illegal */
  702.  
  703. static INLINE shortcard
  704. fD_RegNum(const fdDef *obj)
  705. {
  706.     shortcard count;
  707.  
  708.     if (obj)
  709.     {
  710.         for (count=d0; count<illegal && obj->reg[count]!=illegal; count++);
  711.         return count;
  712.     }
  713.     else
  714.     {
  715.         illparams("fD_RegNum");
  716.         return illegal;
  717.     }
  718. }
  719.  
  720. static INLINE void
  721. fD_NewReg(fdDef *obj, shortcard at, regs reg)
  722. {
  723.     if (obj && at<illegal && reg>=d0 && reg<=illegal)
  724.         obj->reg[at]=reg;
  725.     else
  726.         illparams("fD_NewReg");
  727. }
  728.  
  729. static INLINE regs
  730. fD_GetReg(const fdDef *obj, shortcard at)
  731. {
  732.     if (obj && at<illegal)
  733.         return obj->reg[at];
  734.     else
  735.     {
  736.         illparams("fD_GetReg");
  737.         return illegal;
  738.     }
  739. }
  740.  
  741. static INLINE shortcard
  742. fD_GetFuncParNum(const fdDef *obj)
  743. {
  744.     if (obj)
  745.         return (shortcard)obj->funcpar;
  746.     else
  747.     {
  748.         illparams("fD_GetFuncParNum");
  749.         return illegal;
  750.     }
  751. }
  752.  
  753. static INLINE void
  754. fD_SetFuncParNum(fdDef *obj, shortcard at)
  755. {
  756.     if (obj && at<illegal)
  757.         obj->funcpar=at;
  758.     else
  759.         illparams("fD_SetFuncParNum");
  760. }
  761.  
  762. void
  763. fD_NewProto(fdDef *obj, shortcard at, char *newstr)
  764. {
  765.     char *pr;
  766.  
  767.     if (newstr && obj && at<illegal)
  768.     {
  769.         char *t, arr[200]; /* I hope 200 will be enough... */
  770.         int numwords=1;
  771.         pr=obj->proto[at];
  772.  
  773.         if (pr && pr!=fD_nostring)
  774.             free(pr);
  775.  
  776.         while (*newstr==' ' || *newstr=='\t')
  777.             newstr++; /* Skip leading spaces */
  778.  
  779.         t=arr;
  780.         while ((*t++=*newstr)!=0)
  781.         {
  782.             /* Copy the rest, counting number of words */
  783.             if ((*newstr==' ' || *newstr=='\t') && newstr[1] && newstr[1]!=' ' &&
  784.             newstr[1]!='\t')
  785.                 numwords++;
  786.             newstr++;
  787.         }
  788.  
  789.         t=arr+strlen(arr)-1;
  790.         while (*t==' ' || *t=='\t')
  791.             t--;
  792.         t[1]='\0'; /* Get rid of tailing spaces */
  793.         if (at!=fD_GetFuncParNum(obj))
  794.         {
  795.             if (numwords>1) /* One word - must be type */
  796.                 if (*t!='*')
  797.                 {
  798.                     /* '*' on the end - no parameter name used */
  799.                     while (*t!=' ' && *t!='\t' && *t!='*')
  800.                         t--;
  801.                     t++;
  802.                     if (strcmp(t, "char") && strcmp(t, "short") && strcmp(t, "int")
  803.                     && strcmp(t, "long"))
  804.                     {
  805.                         /* Not one of applicable keywords - must be parameter name.
  806.                             Get rid of it. */
  807.                         t--;
  808.                         while (*t==' ' || *t=='\t')
  809.                             t--;
  810.                         t[1]='\0';
  811.                     }
  812.                 }
  813.         }
  814.         else
  815.         {
  816.             /* Parameter of type "pointer to function". */
  817.             char *end;
  818.             t=strchr(arr, '(');
  819.             while (*t++!='*');
  820.             end=strchr(t, ')');
  821.             memmove(t+2, end, strlen(end)+1);
  822.             *t='%';
  823.             t[1]='s';
  824.         }
  825.  
  826.         if (NewString(&pr, arr))
  827.         {
  828.             obj->proto[at]=pr;
  829.             while (*pr==' ' || *pr=='\t')
  830.                 pr++;
  831.             if (!stricmp(pr, "double"))
  832.             {
  833.                 /* "double" needs two data registers */
  834.                 int count, regs=fD_RegNum(obj);
  835.                 for (count=at+1; count<regs; count++)
  836.                     fD_NewReg(obj, count, fD_GetReg(obj, count+1));
  837.             }
  838.         }
  839.         else
  840.             obj->proto[at]=fD_nostring;
  841.     }
  842.     else
  843.         illparams("fD_NewProto");
  844. }
  845.  
  846. static INLINE void
  847. fD_NewType(fdDef *obj, const char *newtype)
  848. {
  849.     if (obj && newtype)
  850.     {
  851.         if (obj->type && obj->type!=fD_nostring)
  852.             free(obj->type);
  853.         if (!NewString(&obj->type, newtype))
  854.             obj->type=fD_nostring;
  855.     }
  856.     else
  857.         illparams("fD_NewType");
  858. }
  859.  
  860. static INLINE void
  861. fD_SetOffset(fdDef *obj, long off)
  862. {
  863.     if (obj)
  864.         obj->offset=off;
  865.     else
  866.         illparams("fD_SetOffset");
  867. }
  868.  
  869. static INLINE const char*
  870. fD_GetName(const fdDef *obj)
  871. {
  872.     if (obj && obj->name)
  873.         return obj->name;
  874.     else
  875.     {
  876.         illparams("fD_GetName");
  877.         return fD_nostring;
  878.     }
  879. }
  880.  
  881. static INLINE long
  882. fD_GetOffset(const fdDef *obj)
  883. {
  884.     if (obj)
  885.         return obj->offset;
  886.     else
  887.     {
  888.         illparams("fD_GetOffset");
  889.         return 0;
  890.     }
  891. }
  892.  
  893. static INLINE const char*
  894. fD_GetProto(const fdDef *obj, shortcard at)
  895. {
  896.     if (obj && at<illegal && obj->proto[at])
  897.         return obj->proto[at];
  898.     else
  899.     {
  900.         illparams("fD_GetProto");
  901.         return fD_nostring;
  902.     }
  903. }
  904.  
  905. static INLINE const char*
  906. fD_GetParam(const fdDef *obj, shortcard at)
  907. {
  908.     if (obj && at<illegal && obj->param[at])
  909.         return obj->param[at];
  910.     else
  911.     {
  912.         illparams("fD_GetParam");
  913.         return fD_nostring;
  914.     }
  915. }
  916.  
  917. static INLINE const char*
  918. fD_GetRegStr(const fdDef *obj, shortcard at)
  919. {
  920.     if (obj && at<illegal)
  921.         return RegStr(obj->reg[at]);
  922.     else
  923.     {
  924.         illparams("fD_GetReg");
  925.         return RegStr(illegal);
  926.     }
  927. }
  928.  
  929. static INLINE const char*
  930. fD_GetType(const fdDef *obj)
  931. {
  932.     if (obj && obj->type)
  933.         return obj->type;
  934.     else
  935.     {
  936.         illparams("fD_GetType");
  937.         return fD_nostring;
  938.     }
  939. }
  940.  
  941. /* get first free param or illegal */
  942.  
  943. static INLINE shortcard
  944. fD_ParamNum(const fdDef *obj)
  945. {
  946.     shortcard count;
  947.  
  948.     if (obj)
  949.     {
  950.         for (count=d0; count<illegal && obj->param[count]!=fD_nostring;
  951.         count++);
  952.         return count;
  953.     }
  954.     else
  955.     {
  956.         illparams("fD_ParamNum");
  957.         return illegal;
  958.     }
  959. }
  960.  
  961. static INLINE shortcard
  962. fD_ProtoNum(const fdDef *obj)
  963. {
  964.     shortcard count;
  965.  
  966.     if (obj)
  967.     {
  968.         for (count=d0; count<illegal && obj->proto[count]!=fD_nostring;
  969.         count++);
  970.         return count;
  971.     }
  972.     else
  973.     {
  974.         illparams("fD_ProtoNum");
  975.         return illegal;
  976.     }
  977. }
  978.  
  979. /******************************************************************************
  980.  *    fD_parsefd
  981.  *
  982.  *  parse the current line. Needs to copy input, in order to insert \0's
  983.  *  RETURN
  984.  *    fF_GetError(infile):
  985.  *    false = read a definition.
  986.  *    nodef = not a definition on line (so try again)
  987.  *    error = real error
  988.  ******************************************************************************/
  989.  
  990. Error
  991. fD_parsefd(fdDef *obj, fdFile *infile)
  992. {
  993.     enum parse_info { name, params, regs, ready } parsing;
  994.     char *buf, *bpoint, *bnext;
  995.     ulong index;
  996.  
  997.     if (obj && infile && fF_GetError(infile)==false)
  998.     {
  999.         parsing=name;
  1000.  
  1001.         if (!NewString(&buf, infile->line))
  1002.         {
  1003.             fprintf(stderr, "no mem for line %lu\n", infile->lineno);
  1004.             fF_SetError(infile, real_error);
  1005.         }
  1006.         bpoint=buf; /* so -Wall keeps quiet */
  1007.  
  1008.         /* try to parse the line until there's an error or we are done */
  1009.  
  1010.         while (parsing!=ready && fF_GetError(infile)==false)
  1011.         {
  1012.             switch (parsing)
  1013.             {
  1014.                 case name:
  1015.                     switch (buf[0])
  1016.                     {
  1017.                         case '#':
  1018.                             if (strncmp("##base", buf, 6)==0)
  1019.                             {
  1020.                                 bnext=buf+6;
  1021.                                 while (*bnext==' ' || *bnext=='\t' || *bnext=='_')
  1022.                                     bnext++;
  1023.                                 strcpy(BaseName, bnext);
  1024.                                 BaseName[strlen(BaseName)-1]='\0';
  1025.                             }
  1026.                             else
  1027.                                 if (strncmp("##bias", buf, 6)==0)
  1028.                                 {
  1029.                                     if (!sscanf(buf+6, "%ld", &infile->offset))
  1030.                                     {
  1031.                                         fprintf(stderr, "illegal ##bias in line %lu: %s\n",
  1032.                                             infile->lineno, infile->line);
  1033.                                         fF_SetError(infile, real_error);
  1034.                                         break; /* avoid nodef */
  1035.                                     }
  1036.                                     else
  1037.                                     {
  1038.                                         if (fF_GetOffset(infile)>0)
  1039.                                             fF_SetOffset(infile, -fF_GetOffset(infile));
  1040.                                         DBP(fprintf(stderr, "set offset to %ld\n",
  1041.                                             fFGetOffset(infile)));
  1042.                                     }
  1043.                                 }
  1044.                                 else
  1045.                                 {
  1046.                                     if (strncmp("##private", buf, 9)==0)
  1047.                                         fF_SetPrivate(infile, 1);
  1048.                                     else
  1049.                                         if (strncmp("##public", buf, 8)==0)
  1050.                                             fF_SetPrivate(infile, 0);
  1051.                                 }
  1052.                             /* drop through for error comment */
  1053.  
  1054.                         case '*':
  1055.                             /* try again somewhere else */
  1056.                             fF_SetError(infile, nodef);
  1057.                                 break;
  1058.  
  1059.                         default:
  1060.                             /* assume a regular line here */
  1061.                             if (fF_GetPrivate(infile))
  1062.                             {
  1063.                                 /* don't store names of privates */
  1064.                                 fF_SetError(infile, nodef);
  1065.                                 fF_SetOffset(infile, fF_GetOffset(infile)-6);
  1066.                                 break;
  1067.                             }
  1068.                             parsing=name; /* switch (parsing) */
  1069.                             for (index=0; buf[index] && buf[index]!='('; index++);
  1070.  
  1071.                             if (!buf[index])
  1072.                             {
  1073.                                 /* oops, no fd ? */
  1074.                                 fprintf(stderr, "not an fd, line %lu: %s\n",
  1075.                                     infile->lineno, buf /* infile->line */);
  1076.                                 fF_SetError(infile, nodef);
  1077.                             } /* maybe next time */
  1078.                             else
  1079.                             {
  1080.                                 buf[index]=0;
  1081.  
  1082.                                 fD_NewName(obj, buf);
  1083.                                 fD_SetOffset(obj, fF_GetOffset(infile));
  1084.  
  1085.                                 bpoint=buf+index+1;
  1086.                                 parsing=params; /* continue the loop */
  1087.                             }
  1088.                     }
  1089.                     break;
  1090.  
  1091.                 case params:
  1092.                 {
  1093.                     char *bptmp; /* needed for fD_NewParam */
  1094.  
  1095.                     /* look for parameters now */
  1096.  
  1097.                     for (bnext = bpoint; *bnext && *bnext!=',' && *bnext!=')';
  1098.                     bnext++);
  1099.  
  1100.                     if (*bnext)
  1101.                     {
  1102.                         bptmp=bpoint;
  1103.  
  1104.                         if (*bnext == ')')
  1105.                         {
  1106.                             if (bnext[1] != '(')
  1107.                             {
  1108.                                 fprintf(stderr, "registers expected in line %lu: %s\n",
  1109.                                     infile->lineno, infile->line);
  1110.                                 fF_SetError(infile, nodef);
  1111.                             }
  1112.                             else
  1113.                             {
  1114.                                 parsing=regs;
  1115.                                 bpoint=bnext+2;
  1116.                             }
  1117.                         }
  1118.                         else
  1119.                             bpoint = bnext+1;
  1120.  
  1121.                         /* terminate string and advance to next item */
  1122.  
  1123.                         *bnext='\0';
  1124.                         fD_NewParam(obj, fD_ParamNum(obj), bptmp);
  1125.                     }
  1126.                     else
  1127.                     {
  1128.                         fF_SetError(infile, nodef);
  1129.                         fprintf(stderr, "param expected in line %lu: %s\n",
  1130.                             infile->lineno, infile->line);
  1131.                     }
  1132.                     break;  /* switch parsing */
  1133.                 }
  1134.  
  1135.                 case regs:
  1136.                     /* look for parameters now */
  1137.  
  1138.                     for (bnext=bpoint; *bnext && *bnext!='/' && *bnext!=',' &&
  1139.                     *bnext!=')'; bnext++);
  1140.  
  1141.                     if (*bnext)
  1142.                     {
  1143.                         if (')'==*bnext)
  1144.                         {
  1145.                             /* wow, we've finished */
  1146.                             fF_SetOffset(infile, fF_GetOffset(infile)-6);
  1147.                             parsing=ready;
  1148.                         }
  1149.                         *bnext = '\0';
  1150.  
  1151.                         bpoint[0]=tolower(bpoint[0]);
  1152.  
  1153.                         if ((bpoint[0]=='d' || bpoint[0]=='a') && bpoint[1]>='0' &&
  1154.                         bpoint[1]<='8' && bnext==bpoint+2)
  1155.                             fD_NewReg(obj, fD_RegNum(obj),
  1156.                                 bpoint[1]-'0'+(bpoint[0]=='a'? 8 : 0));
  1157.                         else
  1158.                             if (bnext!=bpoint)
  1159.                             {
  1160.                                 /* it is when our function is void */
  1161.                                 fprintf(stderr, "illegal register %s in line %ld\n",
  1162.                                     bpoint, infile->lineno);
  1163.                                 fF_SetError(infile, nodef);
  1164.                             }
  1165.                         bpoint = bnext+1;
  1166.                     }
  1167.                     else
  1168.                     {
  1169.                         fF_SetError(infile, nodef);
  1170.                         fprintf(stderr, "reg expected in line %lu\n",
  1171.                             infile->lineno);
  1172.                     }
  1173.                     break; /* switch parsing */
  1174.  
  1175.                 case ready:
  1176.                     fprintf(stderr, "internal error, use another compiler.\n");
  1177.                     break;
  1178.             }
  1179.         }
  1180.  
  1181.         free(buf);
  1182.         return fF_GetError(infile);
  1183.     }
  1184.     else
  1185.     {
  1186.         illparams("fD_parsefd");
  1187.         return real_error;
  1188.     }
  1189. }
  1190.  
  1191. Error
  1192. fD_parsepr(fdDef *obj, fdFile *infile)
  1193. {
  1194.     char    *buf;        /* a copy of infile->line                            */
  1195.     char    *bpoint,    /* cursor in buf                                        */
  1196.             *bnext,    /* looking for the end                                */
  1197.             *lowarg;    /* beginning of this argument                        */
  1198.     long    obraces;    /* count of open braces                                */
  1199.     regs    count,    /* count parameter number                            */
  1200.             args;        /* the number of arguments for this function */
  1201.  
  1202.     if (!(obj && infile && fF_GetError(infile)==false))
  1203.     {
  1204.         illparams("fD_parsepr");
  1205.         fF_SetError(infile, real_error);
  1206.         return real_error;
  1207.     }
  1208.     if (!NewString(&buf, infile->line))
  1209.     {
  1210.         fprintf(stderr, "no mem for fD_parsepr\n");
  1211.         fF_SetError(infile, real_error);
  1212.         return real_error;
  1213.     }
  1214.     fF_SetError(infile, false);
  1215.  
  1216.     bpoint=strchr(buf, '(');
  1217.     while (--bpoint>=buf && strstr(bpoint, fD_GetName(obj))!=bpoint);
  1218.     if (bpoint>=buf)
  1219.     {
  1220.         while (--bpoint >= buf && (*bpoint==' ' || *bpoint=='\t'));
  1221.         *++bpoint='\0';
  1222.  
  1223.         fD_NewType(obj, buf);
  1224.  
  1225.         while (bpoint && *bpoint++!='('); /* one beyond '(' */
  1226.  
  1227.         lowarg=bpoint;
  1228.         obraces=0;
  1229.  
  1230.         for (count=0, args=fD_RegNum(obj); count<args; bpoint=bnext+1)
  1231.         {
  1232.             while (*bpoint && (*bpoint==' ' || *bpoint=='\t')) /* ignore spaces */
  1233.                 bpoint++;
  1234.  
  1235.             bnext=strpbrk(bpoint, "(),");
  1236.  
  1237.             if (bnext)
  1238.             {
  1239.                 switch (*bnext)
  1240.                 {
  1241.                     case '(':
  1242.                         if (!obraces)
  1243.                         {
  1244.                             if (fD_GetFuncParNum(obj)!=illegal &&
  1245.                             fD_GetFuncParNum(obj)!=count)
  1246.                                 fprintf(stderr, "Warning: two parameters of type "
  1247.                                     "pointer to function are used.\nThis is not "
  1248.                                     "supported!\n");
  1249.                             fD_SetFuncParNum(obj, count);
  1250.                         }
  1251.                         obraces++;
  1252.                         DBP(fprintf(stderr, "< (%ld%s >", obraces, bnext));
  1253.                         break;
  1254.  
  1255.                     case ')':
  1256.                         if (obraces)
  1257.                         {
  1258.                             DBP(fprintf(stderr, "< )%ld%s >", obraces, bnext));
  1259.                             obraces--;
  1260.                         }
  1261.                         else
  1262.                         {
  1263.                             *bnext='\0';
  1264.                             DBP(fprintf(stderr, "< )0> [LAST PROTO=%s]", lowarg));
  1265.                             fD_NewProto(obj, count, lowarg);
  1266.                             lowarg=bnext+1;
  1267.  
  1268.                             if (count!=args-1)
  1269.                             {
  1270.                                 DBP(fprintf(stderr, "%s needs %u arguments and got %u.\n",
  1271.                                     fD_GetName(obj), args, count+1));
  1272.                                 fF_SetError(infile, nodef);
  1273.                             }
  1274.                             count++;
  1275.                         }
  1276.                         break;
  1277.  
  1278.                     case ',':
  1279.                         if (!obraces)
  1280.                         {
  1281.                             *bnext='\0';
  1282.                             DBP(fprintf(stderr, " [PROTO=%s] ", lowarg));
  1283.                             fD_NewProto(obj, count, lowarg);
  1284.                             lowarg=bnext+1;
  1285.                             count++;
  1286.                         }
  1287.                         break;
  1288.  
  1289.                     default:
  1290.                         fprintf(stderr, "faulty strpbrk in line %lu.\n",
  1291.                             infile->lineno);
  1292.                 }
  1293.             }
  1294.             else
  1295.             {
  1296.                 DBP(fprintf(stderr, "faulty argument %u in line %lu.\n", count+1,
  1297.                     infile->lineno));
  1298.                 count=args; /* this will effectively quit the for loop */
  1299.                 fF_SetError(infile, nodef);
  1300.             }
  1301.         }
  1302.         if (fD_ProtoNum(obj)!=fD_RegNum(obj))
  1303.             fF_SetError(infile, nodef);
  1304.     }
  1305.     else
  1306.     {
  1307.         fprintf(stderr, "fD_parsepr was fooled in line %lu\n", infile->lineno);
  1308.         fprintf(stderr, "function , definition %s.\n",
  1309.             /* fD_GetName(obj),*/ infile->line);
  1310.         fF_SetError(infile, nodef);
  1311.     }
  1312.  
  1313.     free(buf);
  1314.     return fF_GetError(infile);
  1315. }
  1316.  
  1317. int
  1318. fD_cmpName(const fdDef **big, const fdDef **small) /* for qsort */
  1319. {
  1320.     return strcmp(fD_GetName(*big), fD_GetName(*small));
  1321. }
  1322.  
  1323. const char*
  1324. taggedfunction(const fdDef *obj)
  1325. {
  1326.     shortcard numregs=fD_RegNum(obj);
  1327.     int count;
  1328.     const char *name=fD_GetName(obj);
  1329.     static char newname[200];    /* Hope will be enough... static because used
  1330.                                             out of the function. */
  1331.     const char *lastarg;
  1332.     const static char *FuncExcTable[]=
  1333.     {
  1334.         "BuildEasyRequestArgs",    "BuildEasyRequest",
  1335.         "DoDTMethodA",                "DoDTMethod",
  1336.         "DoGadgetMethodA",        "DoGadgetMethod",
  1337.         "EasyRequestArgs",        "EasyRequest",
  1338.         "PrintDTObjectA",            "PrintDTObject",
  1339.         "VFWritef",                    "FWritef",
  1340.         "VFPrintf",                    "FPrintf",
  1341.         "VPrintf",                    "Printf",
  1342.         "MUI_MakeObjectA",        "MUI_MakeObject",
  1343.         "MUI_RequestA",            "MUI_Request",
  1344.     },
  1345.     *FuncExcTable2[]=
  1346.     {
  1347.         "ApplyTagChanges",
  1348.         "CloneTagItems",
  1349.         "FindTagItem",
  1350.         "FreeTagItems",
  1351.         "GetTagData",
  1352.         "PackBoolTags",
  1353.         "PackStructureTags",
  1354.         "RefreshTagItemClones",
  1355.         "UnpackStructureTags",
  1356.     };
  1357.     if (!numregs)
  1358.         return NULL;
  1359.  
  1360.     for (count=0; count<sizeof FuncExcTable/sizeof(char*); count+=2)
  1361.         if (strcmp(name, FuncExcTable[count])==0)
  1362.             return FuncExcTable[count+1];
  1363.  
  1364.     for (count=0; count<sizeof FuncExcTable2/sizeof(char*); count++)
  1365.         if (strcmp(name, FuncExcTable2[count])==0)
  1366.             return NULL;
  1367.  
  1368.     lastarg=fD_GetProto(obj, numregs-1);
  1369.     if (strncmp(lastarg, "struct", 6))
  1370.         return NULL;
  1371.     lastarg+=6;
  1372.     while (*lastarg==' ' || *lastarg=='\t')
  1373.         lastarg++;
  1374.     if (strncmp(lastarg, "TagItem", 7))
  1375.         return NULL;
  1376.     lastarg+=7;
  1377.     while (*lastarg==' ' || *lastarg=='\t')
  1378.         lastarg++;
  1379.     if (strcmp(lastarg, "*"))
  1380.         return NULL;
  1381.  
  1382.     strcpy(newname, name);
  1383.     if (newname[strlen(newname)-1]=='A')
  1384.         newname[strlen(newname)-1]='\0';
  1385.     else
  1386.         if (strlen(newname)>7 && !strcmp(newname+strlen(newname)-7, "TagList"))
  1387.             strcpy(newname+strlen(newname)-4, "s");
  1388.         else
  1389.             strcat(newname, "Tags");
  1390.     return newname;
  1391. }
  1392.  
  1393. const char*
  1394. aliasfunction(const char *name)
  1395. {
  1396.     const static char *AliasTable[]=
  1397.     {
  1398.         "AllocDosObject",    "AllocDosObjectTagList",
  1399.         "CreateNewProc",    "CreateNewProcTagList",
  1400.         "NewLoadSeg",        "NewLoadSegTagList",
  1401.         "System",            "SystemTagList",
  1402.     };
  1403.     int count;
  1404.     for (count=0; count<sizeof AliasTable/sizeof(char*); count++)
  1405.         if (strcmp(name, AliasTable[count])==0)
  1406.             return AliasTable[count+(count%2 ? -1 : 1)];
  1407.     return NULL;
  1408. }
  1409.  
  1410. void
  1411. fD_write(FILE *outfile, const fdDef *obj)
  1412. {
  1413.     shortcard count, numregs;
  1414.     const char *chtmp, *tagname, *name, *rettype;
  1415.     int vd=0, a45=0, d7=0;
  1416.  
  1417.     DBP(fprintf(stderr, "func %s\n", fD_GetName(obj)));
  1418.  
  1419.     numregs=fD_RegNum(obj);
  1420.  
  1421.     if ((rettype=fD_GetType(obj))==fD_nostring)
  1422.     {
  1423.         fprintf(stderr, "%s has no prototype.\n", fD_GetName(obj));
  1424.         return;
  1425.     }
  1426.     if (!stricmp(rettype, "void"))
  1427.         vd = 1; /* set flag */
  1428.     for (count=d0; count<numregs; count++)
  1429.     {
  1430.         const char *reg=fD_GetRegStr(obj, count);
  1431.         if (strcmp(reg, "a4")==0 || strcmp(reg, "a5")==0)
  1432.             if (!a45)
  1433.                 a45=(strcmp(reg, "a4") ? 5 : 4); /* set flag */
  1434.             else /* Security check */
  1435.                 fprintf(stderr, "Warning: both a4 and a5 are used. This is not "
  1436.                     "supported!\n");
  1437.         if (strcmp(reg, "d7")==0) /* Used only when a45!=0 */
  1438.             d7=1;
  1439.     }
  1440.     if (a45 && d7) /* Security check */
  1441.         fprintf(stderr, "Warning: d7 and a4 or a5 are used. This is not "
  1442.             "supported!\n");
  1443.  
  1444.     name=fD_GetName(obj);
  1445.  
  1446.     if (fD_ProtoNum(obj)!=numregs)
  1447.     {
  1448.         fprintf(stderr, "%s gets %d fd args and %d proto%s.\n", name, numregs,
  1449.             fD_ProtoNum(obj), fD_ProtoNum(obj)!= 1 ? "s" : "");
  1450.         return;
  1451.     }
  1452.  
  1453.     if (output_mode==NEW)
  1454.     {
  1455.         fprintf(outfile, "#define %s(", name);
  1456.  
  1457.         if (numregs>0)
  1458.         {
  1459.             for (count=d0; count<numregs-1; count++)
  1460.                 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1461.             fprintf(outfile, "%s", fD_GetParam(obj, count));
  1462.         }
  1463.  
  1464.         fprintf(outfile, ") \\\n\tLP%d%s%s%s%s(0x%lx, ", numregs,
  1465.             (vd ? "NR" : ""), (a45 ? (a45==4 ? "A4" : "A5") : ""),
  1466.             (BaseName[0] ? "" : "UB"),
  1467.             (fD_GetFuncParNum(obj)==illegal ? "" : "FP"), -fD_GetOffset(obj));
  1468.         if (!vd)
  1469.             fprintf(outfile, "%s, ", rettype);
  1470.         fprintf(outfile, "%s, ", name);
  1471.  
  1472.         for (count=d0; count<numregs; count++)
  1473.         {
  1474.             chtmp=fD_GetRegStr(obj, count);
  1475.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1476.                 chtmp="d7";
  1477.             fprintf(outfile, "%s, %s, %s%s", (fD_GetFuncParNum(obj)==count ?
  1478.                 "__fpt" : fD_GetProto(obj, count)), fD_GetParam(obj, count),
  1479.                 chtmp, (count==numregs-1 && !BaseName[0] ? "" : ", "));
  1480.         }
  1481.  
  1482.         if (BaseName[0]) /* was "##base" used? */
  1483.             fprintf(outfile, "\\\n\t, %s_BASE_NAME", BaseNamU);
  1484.         if (fD_GetFuncParNum(obj)!=illegal)
  1485.         {
  1486.             fprintf(outfile, ", ");
  1487.             fprintf(outfile, fD_GetProto(obj, fD_GetFuncParNum(obj)), "__fpt");
  1488.         }
  1489.         fprintf(outfile, ")\n\n");
  1490.     }
  1491.     else
  1492.     {
  1493.         fprintf(outfile, "%s__inline %s\n%s(%s",
  1494.             (output_mode==STUBS ? "" : "extern "), rettype, name,
  1495.             (BaseName[0] ? (numregs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
  1496.  
  1497.         for (count=d0; count<numregs; count++)
  1498.         {
  1499.             chtmp=fD_GetProto(obj, count);
  1500.             if (fD_GetFuncParNum(obj)==count)
  1501.                 fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1502.             else
  1503.                 fprintf(outfile, "%s%s%s", chtmp, (*(chtmp+strlen(chtmp)-1)=='*' ?
  1504.                     "" : " "), fD_GetParam(obj, count));
  1505.             if (count<numregs-1)
  1506.                 fprintf(outfile, ", ");
  1507.         }
  1508.  
  1509.         fprintf(outfile, ")\n{\n%s", (BaseName[0] ? "   BASE_EXT_DECL\n" : ""));
  1510.         if (!vd)
  1511.             fprintf(outfile, "   register %s%sres __asm(\"d0\");\n", rettype,
  1512.                 (*(rettype+strlen(rettype)-1)=='*' ? "" : " "));
  1513.  
  1514.         if (BaseName[0])
  1515.             fprintf(outfile, "   register struct %s *a6 __asm(\"a6\") = BASE_NAME;\n",
  1516.                 StdLib);
  1517.  
  1518.         for (count=d0; count<numregs; count++)
  1519.         {
  1520.             chtmp=fD_GetRegStr(obj, count);
  1521.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1522.                 chtmp="d7";
  1523.             if (fD_GetFuncParNum(obj)==count)
  1524.             {
  1525.                 fprintf(outfile, "   register ");
  1526.                 fprintf(outfile, fD_GetProto(obj, count), chtmp);
  1527.                 fprintf(outfile, " __asm(\"%s\") = %s;\n", chtmp, fD_GetParam(obj,
  1528.                     count));
  1529.             }
  1530.             else
  1531.             {
  1532.                 const char *proto=fD_GetProto(obj, count);
  1533.                 fprintf(outfile, "   register %s%s%s __asm(\"%s\") = %s;\n",
  1534.                     proto, (*(proto+strlen(proto)-1)=='*' ? "" : " "), chtmp,
  1535.                     chtmp, fD_GetParam(obj, count));
  1536.             }
  1537.         }
  1538.         if (a45)
  1539.             fprintf(outfile, "   __asm volatile (\"exg d7,%s\\n\\t"
  1540.                 "jsr a6@(-0x%lx:W)\\n\\texg d7,%s\"\n", (a45==4 ? "a4" : "a5"),
  1541.                 -fD_GetOffset(obj), (a45==4 ? "a4" : "a5"));
  1542.         else
  1543.             fprintf(outfile, "   __asm volatile (\"jsr a6@(-0x%lx:W)\"\n",
  1544.                 -fD_GetOffset(obj));
  1545.  
  1546.         fprintf(outfile, (vd ? "   : /* No Output */\n" : "   : \"=r\" (res)\n"));
  1547.  
  1548.         fprintf(outfile, "   : ");
  1549.         if (BaseName[0])
  1550.             fprintf(outfile, "\"r\" (a6)%s", (numregs ? ", ": ""));
  1551.  
  1552.         for (count=d0; count<numregs; count++)
  1553.         {
  1554.             chtmp=fD_GetRegStr(obj, count);
  1555.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1556.                 chtmp="d7";
  1557.             fprintf(outfile, "\"r\" (%s)%s", chtmp, (count<numregs-1 ? ", " : ""));
  1558.         }
  1559.         fprintf(outfile, "\n   : \"d0\", \"d1\", \"a0\", \"a1\"");
  1560.  
  1561.         if (vd)
  1562.             fprintf(outfile, ", \"cc\", \"memory\");\n}\n\n");
  1563.         else
  1564.             fprintf(outfile, ", \"cc\", \"memory\");\n   return res;\n}\n\n");
  1565.     }
  1566.  
  1567.     if ((tagname=aliasfunction(fD_GetName(obj)))!=0)
  1568.     {
  1569.         fprintf(outfile, "#define %s(", tagname);
  1570.         for (count=d0; count<numregs-1; count++)
  1571.             fprintf(outfile, "a%d, ", count);
  1572.         fprintf(outfile, "a%d) %s (", count, name);
  1573.         for (count=d0; count<numregs-1; count++)
  1574.             fprintf(outfile, "(a%d), ", count);
  1575.         fprintf(outfile, "(a%d))\n\n", count);
  1576.     }
  1577.  
  1578.     if ((tagname=taggedfunction(obj))!=0)
  1579.     {
  1580.         if (output_mode!=STUBS)
  1581.         {
  1582.             fprintf(outfile, "#ifndef NO_INLINE_STDARG\n#define %s(", tagname);
  1583.  
  1584.             for (count=d0; count<numregs-1; count++)
  1585.                 fprintf(outfile, "a%d, ", count);
  1586.  
  1587.             fprintf(outfile, "tags...) \\\n\t({ULONG _tags[] = { tags }; %s(",
  1588.                 name);
  1589.  
  1590.             for (count=d0; count<numregs-1; count++)
  1591.                 fprintf(outfile, "(a%d), ", count);
  1592.  
  1593.             fprintf(outfile, "(%s)_tags);})\n#endif /* !NO_INLINE_STDARG */\n\n",
  1594.                 fD_GetProto(obj, fD_RegNum(obj)-1));
  1595.         }
  1596.         else
  1597.         {
  1598.             fprintf(outfile, "%s %s(", rettype, tagname);
  1599.  
  1600.             for (count=d0; count<numregs-1; count++)
  1601.             {
  1602.                 chtmp=fD_GetProto(obj, count);
  1603.                 if (count==fD_GetFuncParNum(obj))
  1604.                     fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1605.                 else
  1606.                     fprintf(outfile, "%s%s%s", chtmp,
  1607.                         (*(chtmp+strlen(chtmp)-1)=='*' ? "" : " "),
  1608.                         fD_GetParam(obj, count));
  1609.                 fprintf(outfile, ", ");
  1610.             }
  1611.  
  1612.             fprintf(outfile, "int tag, ...)\n{\n   ");
  1613.             if (!vd)
  1614.                 fprintf(outfile, "return ");
  1615.  
  1616.             fprintf(outfile, "%s(", name);
  1617.             for (count=d0; count<numregs-1; count++)
  1618.                 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1619.  
  1620.             fprintf(outfile, "(%s)&tag);\n}\n\n", fD_GetProto(obj, fD_RegNum(obj)-1));
  1621.         }
  1622.     }
  1623.  
  1624.     if (strcmp(name, "DoPkt")==0)
  1625.     {
  1626.         fdDef *objnc=(fdDef*)obj;
  1627.         char newname[7]="DoPkt0";
  1628.         objnc->name=newname;
  1629.         for (count=2; count<7; count++)
  1630.         {
  1631.             regs reg=objnc->reg[count];
  1632.             char *proto=objnc->proto[count];
  1633.             objnc->reg[count]=illegal;
  1634.             objnc->proto[count]=fD_nostring;
  1635.             fD_write(outfile, objnc);
  1636.             objnc->reg[count]=reg;
  1637.             objnc->proto[count]=proto;
  1638.             newname[5]++;
  1639.         }
  1640.         objnc->name=(char*)name;
  1641.     }
  1642. }
  1643.  
  1644. int
  1645. ishandleddifferently(const char *proto, const char *funcname)
  1646. {
  1647.     /* First check if this is a vararg call? */
  1648.     const char *end=proto+strlen(proto)-1;
  1649.     while (isspace(*end))
  1650.         end--;
  1651.     if (*end--==';')
  1652.     {
  1653.         while (isspace(*end))
  1654.             end--;
  1655.         if (*end--==')')
  1656.         {
  1657.             while (isspace(*end))
  1658.                 end--;
  1659.             if (!strncmp(end-2, "...", 3))
  1660.                 return 1;
  1661.         }
  1662.     }
  1663.     /* It might be a dos.library "alias" name. */
  1664.     if (aliasfunction(funcname))
  1665.         return 1;
  1666.     /* It might be one from dos.library/DoPkt() family. */
  1667.     if (strlen(funcname)==6 && !strncmp(funcname, "DoPkt", 5) &&
  1668.     funcname[5]>='0' && funcname[6]<='4')
  1669.         return 1;
  1670.     /* Finally, it can be intuition.library/ReportMouse1(). */
  1671.     return !strcmp(funcname, "ReportMouse1");
  1672. }
  1673.  
  1674. void
  1675. printusage(const char* exename)
  1676. {
  1677.     fprintf(stderr,
  1678.         "Usage: %s [options] fd-file clib-file [[-o] output-file]\n"
  1679.         "Options:\n"
  1680.         "--new\t\tpreprocessor based (default)\n"
  1681.         "--old\t\tinline based\n"
  1682.         "--stubs\t\tlibrary stubs\n", exename);
  1683. }
  1684.  
  1685. /******************************************************************************/
  1686.  
  1687. int
  1688. main(int argc, char **argv)
  1689. {
  1690.     fdDef **mydef;
  1691.     fdDef *tmpdef,            /* a dummy to contain the name to look for */
  1692.             *founddef;        /* the fdDef for which we found a prototype */
  1693.     fdFile *myfile;
  1694.     char *tmpstr;
  1695.     FILE *outfile;
  1696.     char *fdfilename=0, *protofilename=0, *outfilename=0;
  1697.  
  1698.     long count, fds;
  1699.     Error lerror;
  1700.  
  1701.     for (count=1; count<argc; count++)
  1702.     {
  1703.         char *option=argv[count];
  1704.         if (*option=='-')
  1705.         {
  1706.             option++;
  1707.             if (strcmp(option, "o")==0)
  1708.             {
  1709.                 if (count==argc-1 || outfilename)
  1710.                 {
  1711.                     printusage(argv[0]);
  1712.                     return EXIT_FAILURE;
  1713.                 }
  1714.                 if (strcmp(argv[++count], "-"))
  1715.                     outfilename=argv[count];
  1716.             }
  1717.             else
  1718.             {
  1719.                 if (*option=='-') /* Accept GNU-style '--' options */
  1720.                     option++;
  1721.                 if (strcmp(option, "new")==0)
  1722.                     output_mode=NEW;
  1723.                 else if (strcmp(option, "old")==0)
  1724.                     output_mode=OLD;
  1725.                 else if (strcmp(option, "stubs")==0)
  1726.                     output_mode=STUBS;
  1727.                 else
  1728.                 {
  1729.                     printusage(argv[0]);
  1730.                     return EXIT_FAILURE;
  1731.                 }
  1732.             }
  1733.         }
  1734.         else
  1735.         {
  1736.             /* One of the filenames */
  1737.             if (!fdfilename)
  1738.                 fdfilename=option;
  1739.             else if (!protofilename)
  1740.                 protofilename=option;
  1741.             else if (!outfilename)
  1742.                 outfilename=option;
  1743.             else
  1744.             {
  1745.                 printusage(argv[0]);
  1746.                 return EXIT_FAILURE;
  1747.             }
  1748.         }
  1749.     }
  1750.  
  1751.     if (!fdfilename || !protofilename)
  1752.     {
  1753.         printusage(argv[0]);
  1754.         return EXIT_FAILURE;
  1755.     }
  1756.  
  1757.     if (!(mydef=malloc(FDS*sizeof(fdDef*))))
  1758.     {
  1759.         fprintf(stderr, "No mem for FDs\n");
  1760.         return EXIT_FAILURE;
  1761.     }
  1762.     for (count=0; count<FDS; count++)
  1763.         mydef[count]=NULL;
  1764.  
  1765.     if (!(myfile=fF_ctor(fdfilename)))
  1766.     {
  1767.         fprintf(stderr, "Couldn't open file '%s'.\n", fdfilename);
  1768.         return EXIT_FAILURE;
  1769.     }
  1770.  
  1771.     lerror=false;
  1772.  
  1773.     for (count=0; count<FDS && lerror==false; count++)
  1774.     {
  1775.         if (!(mydef[count]=fD_ctor()))
  1776.         {
  1777.             fprintf(stderr, "No mem for FDs\n" );
  1778.             return EXIT_FAILURE;
  1779.         }
  1780.         do
  1781.         {
  1782.             if ((lerror=fF_readln(myfile))==false)
  1783.             {
  1784.                 fF_SetError(myfile, false);
  1785.                 lerror=fD_parsefd(mydef[count], myfile);
  1786.             }
  1787.         }
  1788.         while (lerror==nodef);
  1789.     }
  1790.     if (count<FDS)
  1791.     {
  1792.         count--;
  1793.         fD_dtor(mydef[count]);
  1794.         mydef[count]=NULL;
  1795.     }
  1796.     fds=count;
  1797.  
  1798.     /* the gnu stdlib.h seems to have a bug for qsort: int (*)(etc.) */
  1799.  
  1800.     qsort(mydef, count, sizeof(fdDef*), (void*)fD_cmpName);
  1801.  
  1802.     if (output_mode==OLD || output_mode==STUBS)
  1803.     {
  1804.         StdLib="Library";
  1805.  
  1806.         for (count=0; count<(sizeof LibExcTable)/sizeof(char*); count+=2)
  1807.             if (strcmp(BaseName, LibExcTable[count])==0)
  1808.             {
  1809.                 StdLib=LibExcTable[count+1];
  1810.                 break;
  1811.             }
  1812.     }
  1813.  
  1814.     fF_dtor(myfile);
  1815.  
  1816.     if (!(myfile=fF_ctor(protofilename)))
  1817.     {
  1818.         fprintf(stderr, "Couldn't open file '%s'.\n", protofilename);
  1819.         return EXIT_FAILURE;
  1820.     }
  1821.  
  1822.     if (!(tmpdef=fD_ctor()))
  1823.     {
  1824.         fprintf(stderr, "No mem for FDs\n");
  1825.         return EXIT_FAILURE;
  1826.     }
  1827.  
  1828.     for (lerror=false; lerror==false || lerror==nodef;)
  1829.         if ((lerror=fF_readln(myfile))==false)
  1830.         {
  1831.             fF_SetError(myfile, false); /* continue even on errors */
  1832.             tmpstr=fF_FuncName(myfile);
  1833.  
  1834.             if (tmpstr)
  1835.             {
  1836.                 fD_NewName(tmpdef, tmpstr);
  1837.                 founddef=binSearch((void**)mydef, fds, tmpdef, (void*)fD_cmpName);
  1838.  
  1839.                 if (founddef)
  1840.                 {
  1841.                     DBP(fprintf(stderr, "found (%s).\n", fD_GetName(founddef)));
  1842.                     fF_SetError(myfile, false);
  1843.                     lerror=fD_parsepr(founddef, myfile);
  1844.                 }
  1845.                 else
  1846.                     if (!ishandleddifferently(myfile->line, tmpstr))
  1847.                         fprintf(stderr, "did not find <%s> in line %lu.\n",
  1848.                             tmpstr, myfile->lineno);
  1849.                 free(tmpstr);
  1850.             }
  1851.         }
  1852.  
  1853.     fD_dtor(tmpdef);
  1854.  
  1855.     fF_dtor(myfile);
  1856.  
  1857.     if (strlen(fdfilename)>7 &&
  1858.     !strcmp(fdfilename+strlen(fdfilename)-7, "_lib.fd"))
  1859.     {
  1860.         char *str=fdfilename+strlen(fdfilename)-8;
  1861.         while (str!=fdfilename && str[-1]!='/' && str[-1]!=':')
  1862.             str--;
  1863.         strncpy(BaseNamU, str, strlen(str)-7);
  1864.         BaseNamU[strlen(str)-7]='\0';
  1865.     }
  1866.     else
  1867.     {
  1868.         /* Shouldn't really happen, but... */
  1869.         strcpy(BaseNamU, BaseName);
  1870.         if (strlen(BaseNamU)>4 && strcmp(BaseNamU+strlen(BaseNamU)-4, "Base")==0)
  1871.             BaseNamU[strlen(BaseNamU)-4]='\0';
  1872.     }
  1873.     StrUpr(BaseNamU);
  1874.  
  1875.     if (outfilename)
  1876.     {
  1877.         if (!(outfile=fopen(outfilename, "w")))
  1878.         {
  1879.             fprintf(stderr, "Couldn't open output file.\n");
  1880.             return EXIT_FAILURE;
  1881.         }
  1882.     }
  1883.     else
  1884.         outfile=stdout;
  1885.  
  1886.     fprintf(outfile,
  1887.         "#ifndef _INLINE_%s_H\n"
  1888.         "#define _INLINE_%s_H\n\n"
  1889.         "%s\n"
  1890.         "#endif\n\n", BaseNamU, BaseNamU, (output_mode==NEW ?
  1891.             "#ifndef __INLINE_MACROS_H\n"
  1892.             "#include <inline/macros.h>" :
  1893.             "#ifndef __INLINE_STUB_H\n"
  1894.             "#include <inline/stubs.h>"));
  1895.     if (BaseName[0])
  1896.     {
  1897.         if (output_mode==NEW)
  1898.             fprintf(outfile,
  1899.                 "#ifndef %s_BASE_NAME\n"
  1900.                 "#define %s_BASE_NAME %s\n"
  1901.                 "#endif\n\n", BaseNamU, BaseNamU, BaseName);
  1902.         else
  1903.             fprintf(outfile,
  1904.                 "#ifndef BASE_EXT_DECL\n"
  1905.                 "#define BASE_EXT_DECL\n"
  1906.                 "#define BASE_EXT_DECL0 extern struct %s *%s;\n"
  1907.                 "#endif\n"
  1908.                 "#ifndef BASE_PAR_DECL\n"
  1909.                 "#define BASE_PAR_DECL\n"
  1910.                 "#define BASE_PAR_DECL0 void\n"
  1911.                 "#endif\n"
  1912.                 "#ifndef BASE_NAME\n"
  1913.                 "#define BASE_NAME %s\n"
  1914.                 "#endif\n\n"
  1915.                 "BASE_EXT_DECL0\n\n", StdLib, BaseName, BaseName);
  1916.     }
  1917.  
  1918.     for (count=0; count<FDS && mydef[count]; count++)
  1919.     {
  1920.         DBP(fprintf(stderr, "outputting %ld...\n", count));
  1921.  
  1922.         fD_write(outfile, mydef[count]);
  1923.         fD_dtor(mydef[count]);
  1924.         mydef[count]=NULL;
  1925.     }
  1926.  
  1927.     if (output_mode==OLD || output_mode==STUBS)
  1928.         if (BaseName[0])
  1929.             fprintf(outfile,
  1930.                 "#undef BASE_EXT_DECL\n"
  1931.                 "#undef BASE_EXT_DECL0\n"
  1932.                 "#undef BASE_PAR_DECL\n"
  1933.                 "#undef BASE_PAR_DECL0\n"
  1934.                 "#undef BASE_NAME\n\n");
  1935.     fprintf(outfile, "#endif /* _INLINE_%s_H */\n", BaseNamU);
  1936.  
  1937.     free(mydef);
  1938.  
  1939.     return EXIT_SUCCESS;
  1940. }
  1941.