home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / fd2inl_src.lha / fd2inline-1.11 / fd2inline.c < prev    next >
C/C++ Source or Header  |  1997-01-31  |  47KB  |  2,090 lines

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