Removed extraneous file description.
[cake.git] / tools / fd2inline / fd2inline.c
blobe4c08d8846cc1b7eb703150d018d8d0cb3c2388c
1 /******************************************************************************
3 * fd2inline
5 * Should be able to parse CBM fd files and generate vanilla inline calls
6 * for gcc. Works as a filter.
8 * by Wolfgang Baron, all rights reserved.
10 * improved, updated, simply made workable by Rainer F. Trunz 1/95
12 * Completely reworked Version, cleaned up and removed a whole lot of bugs
13 * found by Kamil Iskra.
15 * Expect miracles now (hopefully...). Ok, I am just kidding :)
17 * Version 0.99a by Rainer F. Trunz 6/95
19 * Version 0.99b and later by Kamil Iskra.
21 * Version 1.3x by Martin Blom
22 * See fd2inline.guide/fd2inline.info for details.
24 *****************************************************************************/
26 #include <ctype.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
32 /******************************************************************************
33 * The program has a few sort of class definitions, which are the result of
34 * object oriented thinking, to be imlemented in plain C. I just haven't
35 * had the time to learn C++ or install the compiler. The design does however
36 * improve robustness, which allows the source to be used over and over again.
37 * if you use this code, please leave a little origin note.
38 ******************************************************************************/
40 const static char version_str[]="$VER: fd2inline " VERSION " (24.2.2002)";
42 /******************************************************************************
43 * These are general definitions including types for defining registers etc.
44 ******************************************************************************/
46 #ifdef DEBUG
47 #define DBP(a) a
48 #else /* !DEBUG */
49 #define DBP(a)
50 #endif /* !DEBUG */
52 #if (defined(__GNUC__) || defined(__SASC)) && 0
53 #define INLINE __inline /* Gives 20% *larger* executable with GCC?! */
54 #else
55 #define INLINE
56 #endif
58 #define REGS 16 /* d0=0,...,a7=15 */
59 #define FDS 1000
61 /* To prevent the enum below from getting broken when building on AROS */
62 #undef AROS
64 typedef enum
66 d0, d1, d2, d3, d4, d5, d6, d7, a0, a1, a2, a3, a4, a5, a6, a7, illegal
67 } regs;
69 typedef unsigned char shortcard;
71 typedef enum { false, nodef, real_error } Error;
73 enum { NEW, OLD, STUBS, PROTO, GATESTUBS, GATEPROTO } output_mode=NEW;
74 enum { IX86BE_AMITHLON, AROS, M68K_AMIGAOS, M68K_POS, PPC_POWERUP, PPC_MORPHOS } target = M68K_AMIGAOS;
76 int Quiet = 0;
77 int DirectVarargsCalls = 0;
78 int RegLibFlag = 0;
79 int PreLibFlag = 0;
80 int PostLibFlag = 0;
81 char *gateprefix = "";
82 char *libprefix = "";
84 char BaseName[64], BaseNamU[64], BaseNamL[64], BaseNamC[64];
85 char Buffer[512];
87 const static char *LibExcTable[]=
89 "BattClockBase", "Node",
90 "BattMemBase", "Node",
91 "ConsoleDevice", "Device",
92 "DiskBase", "DiskResource",
93 "DOSBase", "DosLibrary",
94 "SysBase", "ExecBase",
95 "ExpansionBase", "ExpansionBase",
96 "GfxBase", "GfxBase",
97 "InputBase", "Device",
98 "IntuitionBase", "IntuitionBase",
99 "LocaleBase", "LocaleBase",
100 "MathIeeeDoubBasBase", "MathIEEEBase",
101 "MathIeeeDoubTransBase","MathIEEEBase",
102 "MathIeeeSingBasBase", "MathIEEEBase",
103 "MathIeeeSingTransBase","MathIEEEBase",
104 "MiscBase", "Node",
105 "PotgoBase", "Node",
106 "RamdriveDevice", "Device",
107 "RealTimeBase", "RealTimeBase",
108 "RexxSysBase", "RxsLib",
109 "TimerBase", "Device",
110 "UtilityBase", "UtilityBase"
112 const char *StdLib; /* global lib-name ptr */
114 /*******************************************
115 * just some support functions, no checking
116 *******************************************/
118 char*
119 NewString(char** new, const char* old)
121 const char *high;
122 unsigned long len;
124 while (*old && (*old==' ' || *old=='\t'))
125 old++;
126 len=strlen(old);
127 for (high=old+len-1; high>=old && (*high==' ' || *high=='\t'); high--);
128 high++;
129 len=high-old;
130 *new=malloc(1+len);
131 if (*new)
133 strncpy(*new, old, len);
134 (*new)[len]='\0';
136 else
137 fprintf(stderr, "No mem for string\n");
138 return *new;
141 static INLINE void
142 illparams(const char* funcname)
144 fprintf(stderr, "%s: illegal Parameters\n", funcname);
147 static INLINE const char*
148 RegStr(regs reg)
150 const static char *aosregs[]=
152 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
153 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "illegal"
155 *posregs[]=
157 "__INLINE_REG_D0",
158 "__INLINE_REG_D1",
159 "__INLINE_REG_D2",
160 "__INLINE_REG_D3",
161 "__INLINE_REG_D4",
162 "__INLINE_REG_D5",
163 "__INLINE_REG_D6",
164 "__INLINE_REG_D7",
165 "__INLINE_REG_A0",
166 "__INLINE_REG_A1",
167 "__INLINE_REG_A2",
168 "__INLINE_REG_A3",
169 "__INLINE_REG_A4",
170 "__INLINE_REG_A5",
171 "__INLINE_REG_A6",
172 "__INLINE_REG_A7",
173 "illegal"
176 if (reg>illegal)
177 reg=illegal;
178 if (reg<d0)
179 reg=d0;
180 return (target!=M68K_POS ? aosregs[reg] : posregs[reg]);
183 static INLINE const char*
184 RegStrU(regs reg)
186 const static char *aosregs[]=
188 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
189 "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "illegal"
192 if (reg>illegal)
193 reg=illegal;
194 if (reg<d0)
195 reg=d0;
196 return (target!=M68K_POS ? aosregs[reg] : RegStr(reg));
199 static INLINE
201 /******************************************************************************
202 * StrNRBrk
204 * searches string in from position at downwards, as long as in does not
205 * contain any character in not.
207 ******************************************************************************/
209 const char*
210 StrNRBrk(const char* in, const char* not, const char* at)
212 const char *chcheck;
213 Error ready;
215 chcheck=""; /* if at<in, the result will be NULL */
216 for (ready=false; ready==false && at>=in;)
218 for (chcheck=not; *chcheck && *chcheck != *at; chcheck++);
219 if (*chcheck)
220 ready=real_error;
221 else
222 at--;
224 DBP(fprintf(stderr, "{%c}", *chcheck));
225 return *chcheck ? at : NULL;
229 Our own "strupr", since it is a non-standard function.
231 void
232 StrUpr(char* str)
234 while (*str)
236 *str=toupper(*str);
237 str++;
242 MatchGlob( char* glob, char* str )
244 while( *glob )
246 char c = *glob++;
248 switch( c )
250 case '?':
251 if( *str == 0 )
253 return 0;
255 break;
257 case '\\':
258 c = *glob++;
259 if( c == 0 || *str != c )
261 return 0;
263 break;
265 case '*':
266 if( *glob == 0 )
268 return 1;
271 while( *str )
273 if( MatchGlob( glob, str ) )
275 return 1;
277 ++str;
279 return 0;
281 default:
282 if( *str != c )
284 return 0;
286 break;
289 ++str;
292 return *str == 0;
296 /******************************************************************************
297 * CLASS fdFile
299 * stores a file with a temporary buffer (static length, sorry), a line number,
300 * an offset (used for library offsets and an error field.
301 * When there's no error, line will contain line #lineno and offset will be
302 * the last offset set by the interpretation of the last line. If there's been
303 * no ##bias line, this field assumes a bias of 30, which is the standard bias.
304 * It is assumed offsets are always negative.
305 ******************************************************************************/
307 #define fF_BUFSIZE 1024
309 /* all you need to know about an fdFile you parse */
311 typedef enum {FD_PRIVATE=1, FD_SHADOW=2} fdflags;
313 typedef struct
315 FILE* file; /* the file we're reading from */
316 char line[fF_BUFSIZE]; /* the current line */
317 unsigned long lineno; /* current line number */
318 long offset; /* current fd offset (-bias) */
319 Error error; /* is everything o.k. */
320 fdflags flags; /* for ##private, ##shadow (p.OS) */
321 } fdFile;
323 fdFile*
324 fF_ctor (const char* fname);
325 static void
326 fF_dtor (fdFile* obj);
327 static void
328 fF_SetError (fdFile* obj, Error error);
329 static void
330 fF_SetOffset (fdFile* obj, long at);
331 Error
332 fF_readln (fdFile* obj);
333 static Error
334 fF_GetError (const fdFile* obj);
335 static long
336 fF_GetOffset (const fdFile* obj);
337 char*
338 fF_FuncName (fdFile* obj); /* return name or null */
339 static void
340 fF_SetFlags (fdFile* obj, fdflags flags);
341 static fdflags
342 fF_GetFlags (const fdFile* obj);
344 static INLINE void
345 fF_dtor(fdFile* obj)
347 fclose(obj->file);
348 free(obj);
351 static INLINE void
352 fF_SetError(fdFile* obj, Error error)
354 if (obj)
355 obj->error=error;
356 else
357 illparams("fF_SetError");
360 #define FUNCTION_GAP (target!=M68K_POS ? 6 : 12)
362 static INLINE void
363 fF_SetOffset(fdFile* obj, long at)
365 if (obj)
366 obj->offset= at;
367 else
368 illparams("fFSetOffset");
371 static INLINE void
372 fF_SetFlags(fdFile* obj, fdflags flags)
374 if (obj)
375 obj->flags=flags;
376 else
377 illparams("fF_SetFlags");
380 fdFile*
381 fF_ctor(const char* fname)
383 fdFile *result;
385 if (fname)
387 result=malloc(sizeof(fdFile));
388 if (result)
390 result->file=fopen(fname, "r");
391 if (result->file)
393 result->lineno=0;
394 fF_SetOffset(result, -30);
395 fF_SetError(result, false);
396 fF_SetFlags(result, 0);
397 result->line[0]='\0';
399 else
401 free(result);
402 result=NULL;
406 else
408 result=NULL;
409 illparams("fF_ctor");
411 return result;
414 Error
415 fF_readln(fdFile* obj)
417 char *low, *bpoint;
418 long glen, /* the length we read until now */
419 len; /* the length of the last segment */
421 if (obj)
423 low=obj->line;
424 glen=0;
426 for (;;)
428 obj->lineno++;
429 if (!fgets(low, fF_BUFSIZE-1-glen, obj->file))
431 fF_SetError(obj, real_error);
432 obj->line[0]='\0';
433 return real_error;
435 if (low==strpbrk(low, "*#/"))
437 DBP(fprintf(stderr, "in# %s\n", obj->line));
438 return false;
440 len=strlen(low);
441 bpoint=low+len-1;
442 while (len && isspace(*bpoint))
444 bpoint--;
445 len--;
447 if (*bpoint==';' || *bpoint==')')
449 DBP(fprintf(stderr, "\nin: %s\n", obj->line));
450 return false;
452 glen+=len;
453 low+=len;
454 if (glen>=fF_BUFSIZE-10) /* somewhat pessimistic? */
456 fF_SetError(obj, real_error);
457 fprintf(stderr, "Line %lu too long.\n", obj->lineno);
458 return real_error;
460 DBP(fprintf(stderr, "+"));
463 illparams("fF_readln");
464 return real_error;
467 static INLINE Error
468 fF_GetError(const fdFile* obj)
470 if (obj)
471 return obj->error;
472 illparams("fF_GetError");
473 return real_error;
476 static INLINE long
477 fF_GetOffset(const fdFile* obj)
479 if (obj)
480 return obj->offset;
481 illparams("fF_GetOffset");
482 return -1;
485 /******************************************************************************
486 * fF_FuncName
488 * checks if it can find a function-name and return it's address, or NULL
489 * if the current line does not seem to contain one. The return value will
490 * be a pointer into a malloced buffer, thus the caller will have to free().
491 ******************************************************************************/
493 char*
494 fF_FuncName(fdFile* obj)
496 const char *lower;
497 const char *upper;
498 char *buf;
499 long obraces; /* count of open braces */
500 Error ready; /* ready with searching */
502 if (!obj || fF_GetError(obj)==real_error)
504 illparams("fF_FuncName");
505 return NULL;
508 lower=obj->line;
509 while (*lower && (*lower==' ' || *lower=='\t'))
510 lower++;
512 if (!*lower || (!isalpha(*lower) && *lower!='_'))
514 fF_SetError(obj, nodef);
515 return NULL;
518 while (*lower)
520 if (!isalnum(*lower) && !isspace(*lower) && *lower!='*' && *lower!=','
521 && *lower!='.' && *lower!=';' && *lower!='(' && *lower!=')' &&
522 *lower!='[' && *lower!=']' && *lower!='_' && *lower!='\\')
524 fF_SetError(obj, nodef);
525 return NULL;
527 lower++;
530 lower=NULL;
531 buf=NULL;
533 if (obj && fF_GetError(obj)==false)
535 if ((upper=strrchr(obj->line, ')'))!=0)
537 DBP(fprintf(stderr, "end:%s:", upper));
539 for (obraces=1, ready=false; ready==false; upper=lower)
541 lower=StrNRBrk(obj->line, "()", --upper);
542 if (lower)
544 switch (*lower)
546 case ')':
547 obraces++;
548 DBP(fprintf(stderr, " )%ld%s", obraces, lower));
549 break;
550 case '(':
551 obraces--;
552 DBP(fprintf(stderr, " (%ld%s", obraces, lower));
553 if (!obraces)
554 ready=nodef;
555 break;
556 default:
557 fprintf(stderr, "Faulty StrNRBrk\n");
560 else
562 fprintf(stderr, "'(' or ')' expected in line %lu.\n",
563 obj->lineno);
564 ready=real_error;
567 if (ready==nodef) /* we found the matching '(' */
569 long newlen;
570 const char* name;
572 upper--;
574 while (upper>=obj->line && (*upper==' ' || *upper=='\t'))
575 upper--;
577 lower=StrNRBrk(obj->line, " \t*)", upper);
579 if (!lower)
580 lower=obj->line;
581 else
582 lower++;
584 for (name=lower; name<=upper; name++)
585 if (!isalnum(*name) && *name!='_')
587 fF_SetError(obj, nodef);
588 return NULL;
591 newlen=upper-lower+1;
592 buf=malloc(newlen+1);
594 if (buf)
596 strncpy(buf, lower, newlen);
597 buf[newlen]='\0';
599 else
600 fprintf(stderr, "No mem for fF_FuncName");
604 else
605 illparams("fF_FuncName");
606 return buf;
609 static INLINE fdflags
610 fF_GetFlags(const fdFile* obj)
612 if (obj)
613 return obj->flags;
614 illparams("fF_GetFlags");
615 return 0;
618 /*********************
619 * CLASS fdDef *
620 *********************/
622 typedef struct
624 char* name;
625 char* type;
626 long offset;
627 regs reg[REGS];
628 char* param[REGS];
629 char* proto[REGS];
630 regs funcpar; /* number of argument that has type "pointer to function" */
631 } fdDef;
633 fdDef*
634 fD_ctor (void);
635 void
636 fD_dtor (fdDef* obj);
637 static void
638 fD_NewName (fdDef* obj, const char* newname);
639 void
640 fD_NewParam (fdDef* obj, shortcard at, const char* newstr);
642 fD_NewProto (fdDef* obj, shortcard at, char* newstr);
643 static void
644 fD_NewReg (fdDef* obj, shortcard at, regs reg);
645 static void
646 fD_NewType (fdDef* obj, const char* newstr);
647 static void
648 fD_SetOffset (fdDef* obj, long off);
649 Error
650 fD_parsefd (fdDef* obj, fdFile* infile);
651 Error
652 fD_parsepr (fdDef* obj, fdFile* infile);
653 static const char*
654 fD_GetName (const fdDef* obj);
655 static long
656 fD_GetOffset (const fdDef* obj);
657 static const char*
658 fD_GetParam (const fdDef* obj, shortcard at);
659 static regs
660 fD_GetReg (const fdDef* obj, shortcard at);
661 static const char*
662 fD_GetRegStr (const fdDef* obj, shortcard at);
663 static const char*
664 fD_GetRegStrU (const fdDef* obj, shortcard at);
665 static const char*
666 fD_GetType (const fdDef* obj);
667 static shortcard
668 fD_ParamNum (const fdDef* obj);
669 static shortcard
670 fD_ProtoNum (const fdDef* obj);
671 static shortcard
672 fD_RegNum (const fdDef* obj);
674 fD_cmpName (const void* big, const void* small);
675 void
676 fD_write (FILE* outfile, const fdDef* obj);
677 static shortcard
678 fD_GetFuncParNum (const fdDef* obj);
679 static void
680 fD_SetFuncParNum (fdDef* obj, shortcard at);
681 static void
682 fD_adjustargnames(fdDef *obj);
684 fdDef **arrdefs;
685 long fds;
687 char *fD_nostring="";
689 fdDef*
690 fD_ctor(void)
692 fdDef *result;
693 regs count;
695 result=malloc(sizeof(fdDef));
697 if (result)
699 result->name=fD_nostring;
700 result->type=fD_nostring;
701 result->funcpar=illegal;
703 for (count=d0; count<illegal; count++ )
705 result->reg[count]=illegal;
706 result->param[count]=fD_nostring; /* if (!strlen) dont't free() */
707 result->proto[count]=fD_nostring;
710 return result;
713 /* free all resources and make the object as illegal as possible */
715 void
716 fD_dtor(fdDef* obj)
718 regs count;
720 if (obj)
722 if (!obj->name)
723 fprintf(stderr, "fD_dtor: null name");
724 else
725 if (obj->name!=fD_nostring)
726 free(obj->name);
728 if (!obj->type)
729 fprintf(stderr, "fD_dtor: null type");
730 else
731 if (obj->type!=fD_nostring)
732 free(obj->type);
734 obj->name=obj->type=NULL;
736 for (count=d0; count<illegal; count++)
738 obj->reg[count]=illegal;
740 if (!obj->param[count])
741 fprintf(stderr, "fD_dtor: null param");
742 else
743 if (obj->param[count]!=fD_nostring)
744 free(obj->param[count]);
746 if (!obj->proto[count])
747 fprintf(stderr, "fD_dtor: null proto");
748 else
749 if (obj->proto[count]!=fD_nostring)
750 free(obj->proto[count]);
752 obj->param[count]=obj->proto[count]=NULL;
755 free(obj);
757 else
758 fprintf(stderr, "fd_dtor(NULL)\n");
761 static INLINE void
762 fD_NewName(fdDef* obj, const char* newname)
764 if (obj && newname)
766 if (obj->name && obj->name!=fD_nostring)
767 free(obj->name);
768 if (!NewString(&obj->name, newname))
769 obj->name=fD_nostring;
771 else
772 illparams("fD_NewName");
775 void
776 fD_NewParam(fdDef* obj, shortcard at, const char* newstr)
778 char *pa;
780 if (newstr && obj && at<illegal)
782 pa=obj->param[at];
784 if (pa && pa!=fD_nostring)
785 free(pa);
787 while (*newstr==' ' || *newstr=='\t')
788 newstr++;
790 if (NewString(&pa, newstr))
792 char* prefix_pa;
794 prefix_pa = malloc( strlen( pa ) + 4 );
796 if( prefix_pa == NULL )
798 fprintf(stderr, "No mem for string\n");
800 else
802 sprintf( prefix_pa, "___%s", pa );
803 obj->param[at]=prefix_pa;
804 free( pa );
807 else
808 obj->param[at]=fD_nostring;
810 else
811 illparams("fD_NewParam");
814 /* get first free *reg or illegal */
816 static INLINE shortcard
817 fD_RegNum(const fdDef* obj)
819 shortcard count;
821 if (obj)
823 for (count=d0; count<illegal && obj->reg[count]!=illegal; count++);
824 return count;
826 else
828 illparams("fD_RegNum");
829 return illegal;
833 static INLINE void
834 fD_NewReg(fdDef* obj, shortcard at, regs reg)
836 if (obj && at<illegal && reg>=d0 && reg<=illegal)
837 obj->reg[at]=reg;
838 else
839 illparams("fD_NewReg");
842 static INLINE regs
843 fD_GetReg(const fdDef* obj, shortcard at)
845 if (obj && at<illegal)
846 return obj->reg[at];
847 else
849 illparams("fD_GetReg");
850 return illegal;
854 static INLINE shortcard
855 fD_GetFuncParNum(const fdDef* obj)
857 if (obj)
858 return (shortcard)obj->funcpar;
859 else
861 illparams("fD_GetFuncParNum");
862 return illegal;
866 static INLINE void
867 fD_SetFuncParNum(fdDef* obj, shortcard at)
869 if (obj && at<illegal)
870 obj->funcpar=at;
871 else
872 illparams("fD_SetFuncParNum");
876 fD_NewProto(fdDef* obj, shortcard at, char* newstr)
878 char *pr;
880 if (newstr && obj && at<illegal)
882 char *t, arr[200]; /* I hope 200 will be enough... */
883 int numwords=1;
884 pr=obj->proto[at];
886 if (pr && pr!=fD_nostring)
887 free(pr);
889 while (*newstr==' ' || *newstr=='\t')
890 newstr++; /* Skip leading spaces */
892 t=arr;
893 while ((*t++=*newstr)!=0)
895 /* Copy the rest, counting number of words */
896 if ((*newstr==' ' || *newstr=='\t') && newstr[1] && newstr[1]!=' ' &&
897 newstr[1]!='\t')
898 numwords++;
899 newstr++;
902 t=arr+strlen(arr)-1;
903 while (*t==' ' || *t=='\t')
904 t--;
905 t[1]='\0'; /* Get rid of tailing spaces */
907 if (at!=fD_GetFuncParNum(obj))
909 if (numwords>1) /* One word - must be type */
910 if (*t!='*')
912 /* '*' on the end - no parameter name used */
913 while (*t!=' ' && *t!='\t' && *t!='*')
914 t--;
915 t++;
916 if (strcmp(t, "char") && strcmp(t, "short") && strcmp(t, "int")
917 && strcmp(t, "long") && strcmp(t, "APTR"))
919 /* Not one of applicable keywords - must be parameter name.
920 Get rid of it. */
921 t--;
922 while (*t==' ' || *t=='\t')
923 t--;
924 t[1]='\0';
928 else
930 /* Parameter of type "pointer to function". */
931 char *end;
932 t=strchr(arr, '(');
933 t++;
934 while (*t==' ' || *t=='\t')
935 t++;
936 if (*t!='*')
937 return 1;
938 t++;
939 end=strchr(t, ')');
940 if (target!=M68K_POS)
942 memmove(t+2, end, strlen(end)+1);
943 *t='%';
944 t[1]='s';
946 else
947 memmove(t, end, strlen(end)+1);
950 if (NewString(&pr, arr))
952 obj->proto[at]=pr;
953 while (*pr==' ' || *pr=='\t')
954 pr++;
955 if (!strcasecmp(pr, "double"))
957 /* "double" needs two data registers */
958 int count, regs=fD_RegNum(obj);
959 for (count=at+1; count<regs; count++)
960 fD_NewReg(obj, count, fD_GetReg(obj, count+1));
963 else
964 obj->proto[at]=fD_nostring;
966 else
967 illparams("fD_NewProto");
969 return 0;
972 static INLINE void
973 fD_NewType(fdDef* obj, const char* newtype)
975 if (obj && newtype)
977 if (obj->type && obj->type!=fD_nostring)
978 free(obj->type);
979 if (!NewString(&obj->type, newtype))
980 obj->type=fD_nostring;
982 else
983 illparams("fD_NewType");
986 static INLINE void
987 fD_SetOffset(fdDef* obj, long off)
989 if (obj)
990 obj->offset=off;
991 else
992 illparams("fD_SetOffset");
995 static INLINE const char*
996 fD_GetName(const fdDef* obj)
998 if (obj && obj->name)
999 return obj->name;
1000 else
1002 illparams("fD_GetName");
1003 return fD_nostring;
1007 static INLINE long
1008 fD_GetOffset(const fdDef* obj)
1010 if (obj)
1011 return obj->offset;
1012 else
1014 illparams("fD_GetOffset");
1015 return 0;
1019 static INLINE const char*
1020 fD_GetProto(const fdDef* obj, shortcard at)
1022 if (obj && at<illegal && obj->proto[at])
1023 return obj->proto[at];
1024 else
1026 illparams("fD_GetProto");
1027 return fD_nostring;
1031 static INLINE const char*
1032 fD_GetParam(const fdDef* obj, shortcard at)
1034 if (obj && at<illegal && obj->param[at])
1035 return obj->param[at];
1036 else
1038 illparams("fD_GetParam");
1039 return fD_nostring;
1043 static INLINE const char*
1044 fD_GetRegStr(const fdDef* obj, shortcard at)
1046 if (obj && at<illegal)
1047 return RegStr(obj->reg[at]);
1048 else
1050 illparams("fD_GetReg");
1051 return RegStr(illegal);
1055 static INLINE const char*
1056 fD_GetRegStrU(const fdDef* obj, shortcard at)
1058 if (obj && at<illegal)
1059 return RegStrU(obj->reg[at]);
1060 else
1062 illparams("fD_GetReg");
1063 return RegStrU(illegal);
1067 static INLINE const char*
1068 fD_GetType(const fdDef* obj)
1070 if (obj && obj->type)
1071 return obj->type;
1072 else
1074 illparams("fD_GetType");
1075 return fD_nostring;
1079 /* get first free param or illegal */
1081 static INLINE shortcard
1082 fD_ParamNum(const fdDef* obj)
1084 shortcard count;
1086 if (obj)
1088 for (count=d0; count<illegal && obj->param[count]!=fD_nostring;
1089 count++);
1090 return count;
1092 else
1094 illparams("fD_ParamNum");
1095 return illegal;
1099 static INLINE shortcard
1100 fD_ProtoNum(const fdDef* obj)
1102 shortcard count;
1104 if (obj)
1106 for (count=d0; count<illegal && obj->proto[count]!=fD_nostring;
1107 count++);
1108 return count;
1110 else
1112 illparams("fD_ProtoNum");
1113 return illegal;
1117 /******************************************************************************
1118 * fD_parsefd
1120 * parse the current line. Needs to copy input, in order to insert \0's
1121 * RETURN
1122 * fF_GetError(infile):
1123 * false = read a definition.
1124 * nodef = not a definition on line (so try again)
1125 * error = real error
1126 ******************************************************************************/
1128 Error
1129 fD_parsefd(fdDef* obj, fdFile* infile)
1131 enum parse_info { name, params, regs, ready } parsing;
1132 char *buf, *bpoint, *bnext;
1133 unsigned long index;
1135 if (obj && infile && fF_GetError(infile)==false)
1137 parsing=name;
1139 if (!NewString(&buf, infile->line))
1141 fprintf(stderr, "No mem for line %lu\n", infile->lineno);
1142 fF_SetError(infile, real_error);
1144 bpoint=buf; /* so -Wall keeps quiet */
1146 /* try to parse the line until there's an error or we are done */
1148 while (parsing!=ready && fF_GetError(infile)==false)
1150 switch (parsing)
1152 case name:
1153 switch (buf[0])
1155 case '#':
1156 if (strncmp("##base", buf, 6)==0)
1158 bnext=buf+6;
1159 while (*bnext==' ' || *bnext=='\t' || *bnext=='_')
1160 bnext++;
1161 strcpy(BaseName, bnext);
1162 BaseName[strlen(BaseName)-1]='\0';
1164 else
1165 if (strncmp("##bias", buf, 6)==0)
1167 if (!sscanf(buf+6, "%ld", &infile->offset))
1169 fprintf(stderr, "Illegal ##bias in line %lu: %s\n",
1170 infile->lineno, infile->line);
1171 fF_SetError(infile, real_error);
1172 break; /* avoid nodef */
1174 else
1176 if (fF_GetOffset(infile)>0)
1177 fF_SetOffset(infile, -fF_GetOffset(infile));
1178 DBP(fprintf(stderr, "set offset to %ld\n",
1179 fF_GetOffset(infile)));
1182 else
1184 if (strncmp("##private", buf, 9)==0)
1185 fF_SetFlags(infile, fF_GetFlags(infile) |
1186 FD_PRIVATE);
1187 else if (strncmp("##public", buf, 8)==0)
1188 fF_SetFlags(infile, fF_GetFlags(infile) &
1189 ~FD_PRIVATE);
1190 else if (strncmp("##shadow", buf, 8)==0)
1191 fF_SetFlags(infile, fF_GetFlags(infile) |
1192 FD_SHADOW);
1194 /* drop through for error comment */
1196 case '*':
1197 /* try again somewhere else */
1198 fF_SetError(infile, nodef);
1199 break;
1201 default:
1202 /* assume a regular line here */
1203 if (fF_GetFlags(infile) & (FD_PRIVATE | FD_SHADOW))
1205 /* don't store names of privates */
1206 fF_SetError(infile, nodef);
1207 if (!(fF_GetFlags(infile) & FD_SHADOW))
1208 fF_SetOffset(infile,
1209 fF_GetOffset(infile)-FUNCTION_GAP);
1210 else
1211 /* Shadow is valid for one line only. */
1212 fF_SetFlags(infile, fF_GetFlags(infile) &
1213 ~FD_SHADOW);
1214 break;
1216 parsing=name; /* switch (parsing) */
1217 for (index=0; buf[index] && buf[index]!='('; index++);
1219 if (!buf[index])
1221 /* oops, no fd ? */
1222 fprintf(stderr, "Not an fd, line %lu: %s\n",
1223 infile->lineno, buf /* infile->line */);
1224 fF_SetError(infile, nodef);
1225 } /* maybe next time */
1226 else
1228 buf[index]=0;
1230 fD_NewName(obj, buf);
1231 fD_SetOffset(obj, fF_GetOffset(infile));
1233 bpoint=buf+index+1;
1234 parsing=params; /* continue the loop */
1237 break;
1239 case params:
1241 char *bptmp; /* needed for fD_NewParam */
1243 /* look for parameters now */
1245 for (bnext = bpoint; *bnext && *bnext!=',' && *bnext!=')';
1246 bnext++);
1248 if (*bnext)
1250 bptmp=bpoint;
1252 if (*bnext == ')')
1254 if (bnext[1] != '(')
1256 fprintf(stderr, "Registers expected in line %lu: %s\n",
1257 infile->lineno, infile->line);
1258 fF_SetError(infile, nodef);
1260 else
1262 parsing=regs;
1263 bpoint=bnext+2;
1266 else
1267 bpoint = bnext+1;
1269 /* terminate string and advance to next item */
1271 *bnext='\0';
1272 fD_NewParam(obj, fD_ParamNum(obj), bptmp);
1274 else
1276 fF_SetError(infile, nodef);
1277 fprintf(stderr, "Param expected in line %lu: %s\n",
1278 infile->lineno, infile->line);
1280 break; /* switch parsing */
1283 case regs:
1284 /* look for parameters now */
1286 for (bnext=bpoint; *bnext && *bnext!='/' && *bnext!=',' &&
1287 *bnext!=')'; bnext++);
1289 if (*bnext)
1291 if (')'==*bnext)
1293 /* wow, we've finished */
1294 fF_SetOffset(infile, fF_GetOffset(infile)-FUNCTION_GAP);
1295 parsing=ready;
1297 *bnext = '\0';
1299 bpoint[0]=tolower(bpoint[0]);
1301 if ((bpoint[0]=='d' || bpoint[0]=='a') && bpoint[1]>='0' &&
1302 bpoint[1]<='8' && bnext==bpoint+2)
1303 fD_NewReg(obj, fD_RegNum(obj),
1304 bpoint[1]-'0'+(bpoint[0]=='a'? 8 : 0));
1305 else
1306 if (bnext!=bpoint)
1308 /* it is when our function is void */
1309 fprintf(stderr, "Illegal register %s in line %ld\n",
1310 bpoint, infile->lineno);
1311 fF_SetError(infile, nodef);
1313 bpoint = bnext+1;
1315 else
1317 fF_SetError(infile, nodef);
1318 fprintf(stderr, "Reg expected in line %lu\n",
1319 infile->lineno);
1321 break; /* switch parsing */
1323 case ready:
1324 fprintf(stderr, "Internal error, use another compiler.\n");
1325 break;
1329 free(buf);
1330 return fF_GetError(infile);
1332 else
1334 illparams("fD_parsefd");
1335 return real_error;
1339 static void
1340 fD_adjustargnames(fdDef *obj)
1342 int parnum;
1344 if (output_mode!=NEW)
1345 return;
1347 /* For #define-base output mode, we have to check if argument names are not
1348 the same as some words in type names. We check from the first argument
1349 to the last, resolving conflicts by changing argument names, if
1350 necessary. */
1352 for (parnum=0; parnum<fD_ParamNum(obj); parnum++)
1354 const char *parname=fD_GetParam(obj, parnum);
1355 int finished;
1358 int num;
1359 const char *type=fD_GetType(obj);
1360 char *str;
1362 finished=1;
1364 if ((str=strstr(type, parname))!=0 && (str==type ||
1365 (!isalnum(str[-1]) && str[-1]!='_')) &&
1366 (!*(str+=strlen(parname)) || (!isalnum(*str) && *str!='_')))
1368 char buf[300]; /* Hope will be enough... */
1369 strcpy(buf, parname);
1370 strcat(buf, "_");
1371 fD_NewParam(obj, parnum, buf);
1372 parname=fD_GetParam(obj, parnum);
1373 finished=0;
1375 else
1376 for (num=0; num<fD_ParamNum(obj); num++)
1378 const char *name=fD_GetParam(obj, num);
1379 const char *proto=fD_GetProto(obj, num);
1380 if ((num<parnum && strcmp(name, parname)==0) ||
1381 ((str=strstr(proto, parname))!=0 && (str==proto ||
1382 (!isalnum(str[-1]) && str[-1]!='_')) &&
1383 (!*(str+=strlen(parname)) || (!isalnum(*str) && *str!='_'))))
1385 char buf[300]; /* Hope will be enough... */
1386 strcpy(buf, parname);
1387 strcat(buf, "_");
1388 fD_NewParam(obj, parnum, buf);
1389 parname=fD_GetParam(obj, parnum);
1390 // lcs finished=0;
1391 break;
1394 } while (!finished);
1398 Error
1399 fD_parsepr(fdDef* obj, fdFile* infile)
1401 char *buf; /* a copy of infile->line */
1402 char *bpoint, /* cursor in buf */
1403 *bnext, /* looking for the end */
1404 *lowarg; /* beginning of this argument */
1405 long obraces; /* count of open braces */
1406 regs count, /* count parameter number */
1407 args; /* the number of arguments for this function */
1409 if (!(obj && infile && fF_GetError(infile)==false))
1411 illparams("fD_parsepr");
1412 fF_SetError(infile, real_error);
1413 return real_error;
1415 if (!NewString(&buf, infile->line))
1417 fprintf(stderr, "No mem for fD_parsepr\n");
1418 fF_SetError(infile, real_error);
1419 return real_error;
1421 fF_SetError(infile, false);
1423 bpoint=strchr(buf, '(');
1424 while (--bpoint>=buf && strstr(bpoint, fD_GetName(obj))!=bpoint);
1425 if (bpoint>=buf)
1427 while (--bpoint >= buf && (*bpoint==' ' || *bpoint=='\t'));
1428 *++bpoint='\0';
1430 fD_NewType(obj, buf);
1432 while (bpoint && *bpoint++!='('); /* one beyond '(' */
1434 lowarg=bpoint;
1435 obraces=0;
1437 for (count=0, args=fD_RegNum(obj); count<args; bpoint=bnext+1)
1439 while (*bpoint && (*bpoint==' ' || *bpoint=='\t')) /* ignore spaces */
1440 bpoint++;
1442 if (!obraces && target==M68K_POS && strncmp(bpoint, "_R_", 3)==0 &&
1443 isalnum(bpoint[3]) && isalnum(bpoint[4]) && isspace(bpoint[5]))
1444 lowarg=bpoint+5;
1446 bnext=strpbrk(bpoint, "(),");
1448 if (bnext)
1450 switch (*bnext)
1452 case '(':
1453 if (!obraces)
1455 if (target==M68K_AMIGAOS || target==M68K_POS)
1457 if (fD_GetFuncParNum(obj)!=illegal &&
1458 fD_GetFuncParNum(obj)!=count &&
1459 !Quiet)
1460 fprintf(stderr, "Warning: two parameters of type "
1461 "pointer to function are used.\n"
1462 "This is not supported!\n");
1465 fD_SetFuncParNum(obj, count);
1467 obraces++;
1468 DBP(fprintf(stderr, "< (%ld%s >", obraces, bnext));
1469 break;
1471 case ')':
1472 if (obraces)
1474 DBP(fprintf(stderr, "< )%ld%s >", obraces, bnext));
1475 obraces--;
1477 else
1479 *bnext='\0';
1480 DBP(fprintf(stderr, "< )0> [LAST PROTO=%s]", lowarg));
1481 if (fD_NewProto(obj, count, lowarg))
1482 fprintf(stderr, "Parser confused in line %ld\n",
1483 infile->lineno);
1484 lowarg=bnext+1;
1486 if (count!=args-1)
1488 DBP(fprintf(stderr, "%s needs %u arguments and got %u.\n",
1489 fD_GetName(obj), args, count+1));
1490 fF_SetError(infile, nodef);
1492 count++;
1494 break;
1496 case ',':
1497 if (!obraces)
1499 *bnext='\0';
1500 DBP(fprintf(stderr, " [PROTO=%s] ", lowarg));
1501 if (fD_NewProto(obj, count, lowarg))
1502 fprintf(stderr, "Parser confused in line %ld\n",
1503 infile->lineno);
1504 lowarg=bnext+1;
1505 count++;
1507 break;
1509 default:
1510 fprintf(stderr, "Faulty strpbrk in line %lu.\n",
1511 infile->lineno);
1514 else
1516 DBP(fprintf(stderr, "Faulty argument %u in line %lu.\n", count+1,
1517 infile->lineno));
1518 count=args; /* this will effectively quit the for loop */
1519 fF_SetError(infile, nodef);
1522 if (fD_ProtoNum(obj)!=fD_RegNum(obj))
1523 fF_SetError(infile, nodef);
1525 else
1527 fprintf(stderr, "fD_parsepr was fooled in line %lu\n", infile->lineno);
1528 fprintf(stderr, "function , definition %s.\n",
1529 /* fD_GetName(obj),*/ infile->line);
1530 fF_SetError(infile, nodef);
1533 free(buf);
1535 fD_adjustargnames(obj);
1537 return fF_GetError(infile);
1541 fD_cmpName(const void* big, const void* small) /* for qsort and bsearch */
1543 return strcmp(fD_GetName(*(fdDef**)big), fD_GetName(*(fdDef**)small));
1546 const static char *TagExcTable[]=
1548 "BuildEasyRequestArgs", "BuildEasyRequest",
1549 "DoDTMethodA", "DoDTMethod",
1550 "DoGadgetMethodA", "DoGadgetMethod",
1551 "EasyRequestArgs", "EasyRequest",
1552 "MUI_MakeObjectA", "MUI_MakeObject",
1553 "MUI_RequestA", "MUI_Request",
1554 "PrintDTObjectA", "PrintDTObject",
1555 "RefreshDTObjectA", "RefreshDTObjects",
1556 "UMSVLog", "UMSLog",
1557 "VFWritef", "FWritef",
1558 "VFPrintf", "FPrintf",
1559 "VPrintf", "Printf",
1562 const char*
1563 getvarargsfunction(const fdDef * obj)
1565 unsigned int count;
1566 const char *name = fD_GetName(obj);
1568 for (count=0; count<sizeof TagExcTable/sizeof TagExcTable[0]; count+=2)
1570 if (strcmp(name, TagExcTable[count])==0)
1572 return TagExcTable[count+1];
1575 return(NULL);
1578 const char*
1579 taggedfunction(const fdDef* obj)
1581 shortcard numregs=fD_RegNum(obj);
1582 unsigned int count;
1583 int aos_tagitem;
1584 const char *name=fD_GetName(obj);
1585 static char newname[200]; /* Hope will be enough... static because used
1586 out of the function. */
1587 const char *lastarg;
1588 const static char *TagExcTable2[]=
1590 "ApplyTagChanges",
1591 "CloneTagItems",
1592 "FindTagItem",
1593 "FreeTagItems",
1594 "GetTagData",
1595 "PackBoolTags",
1596 "PackStructureTags",
1597 "RefreshTagItemClones",
1598 "UnpackStructureTags",
1601 if (!numregs)
1602 return NULL;
1604 for (count=0; count<sizeof TagExcTable/sizeof TagExcTable[0]; count+=2)
1605 if (strcmp(name, TagExcTable[count])==0)
1606 return NULL;
1607 // lcs return TagExcTable[count+1];
1609 for (count=0; count<sizeof TagExcTable2/sizeof TagExcTable2[0]; count++)
1610 if (strcmp(name, TagExcTable2[count])==0)
1611 return NULL;
1613 lastarg=fD_GetProto(obj, numregs-1);
1614 if (strncmp(lastarg, "const", 5)==0 || strncmp(lastarg, "CONST", 5)==0)
1615 lastarg+=5;
1616 while (*lastarg==' ' || *lastarg=='\t')
1617 lastarg++;
1618 if (strncmp(lastarg, "struct", 6))
1619 return NULL;
1620 lastarg+=6;
1621 while (*lastarg==' ' || *lastarg=='\t')
1622 lastarg++;
1623 aos_tagitem=1;
1624 if (strncmp(lastarg, "TagItem", 7) &&
1625 (target!=M68K_POS || ((aos_tagitem=strncmp(lastarg, "pOS_TagItem", 11))!=0)))
1626 return NULL;
1627 lastarg+=(aos_tagitem ? 7 : 11);
1628 while (*lastarg==' ' || *lastarg=='\t')
1629 lastarg++;
1630 if (strcmp(lastarg, "*"))
1631 return NULL;
1633 strcpy(newname, name);
1634 if (newname[strlen(newname)-1]=='A')
1635 newname[strlen(newname)-1]='\0';
1636 else
1637 if (strlen(newname)>7 && !strcmp(newname+strlen(newname)-7, "TagList"))
1638 strcpy(newname+strlen(newname)-4, "s");
1639 else
1640 strcat(newname, "Tags");
1641 return newname;
1644 const char*
1645 aliasfunction(const char* name)
1647 const static char *AliasTable[]=
1649 "AllocDosObject", "AllocDosObjectTagList",
1650 "CreateNewProc", "CreateNewProcTagList",
1651 "NewLoadSeg", "NewLoadSegTagList",
1652 "System", "SystemTagList",
1654 unsigned int count;
1655 for (count=0; count<sizeof AliasTable/sizeof AliasTable[0]; count++)
1656 if (strcmp(name, AliasTable[count])==0)
1657 return AliasTable[count+(count%2 ? -1 : 1)];
1658 return NULL;
1661 void
1662 fD_write(FILE* outfile, const fdDef* obj)
1664 shortcard count, numregs;
1665 const char *chtmp, *tagname, *varname, *name, *rettype;
1666 int vd=0, a45=0, d7=0;
1668 DBP(fprintf(stderr, "func %s\n", fD_GetName(obj)));
1670 numregs=fD_RegNum(obj);
1672 if ((rettype=fD_GetType(obj))==fD_nostring)
1674 fprintf(stderr, "%s has no prototype.\n", fD_GetName(obj));
1675 return;
1677 if (!strcasecmp(rettype, "void"))
1678 vd = 1; /* set flag */
1679 for (count=d0; count<numregs; count++)
1681 const char *reg=fD_GetRegStr(obj, count);
1682 if (!((output_mode == NEW) && (target == PPC_POWERUP)))
1684 if (strcmp(reg, "a4")==0 || strcmp(reg, "a5")==0)
1686 if (!a45)
1687 a45=(strcmp(reg, "a4") ? 5 : 4); /* set flag */
1688 else /* Security check */
1689 if (!Quiet)
1690 fprintf(stderr, "Warning: both a4 and a5 are used. "
1691 "This is not supported!\n");
1694 if (strcmp(reg, "d7")==0) /* Used only when a45!=0 */
1695 d7=1;
1698 if (!((output_mode == NEW) && (target == PPC_POWERUP)))
1700 if (a45 && d7) /* Security check */
1701 if (!Quiet)
1702 fprintf(stderr, "Warning: d7 and a4 or a5 are used. This is not "
1703 "supported!\n");
1706 name=fD_GetName(obj);
1708 if (fD_ProtoNum(obj)!=numregs)
1710 fprintf(stderr, "%s gets %d fd args and %d proto%s.\n", name, numregs,
1711 fD_ProtoNum(obj), fD_ProtoNum(obj)!= 1 ? "s" : "");
1712 return;
1715 if (output_mode==NEW)
1717 fprintf(outfile, "#define %s(", name);
1719 if (numregs>0)
1721 for (count=d0; count<numregs-1; count++)
1722 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
1723 fprintf(outfile, "%s", fD_GetParam(obj, count));
1726 if (target==M68K_AMIGAOS)
1728 fprintf(outfile, ") \\\n\tLP%d%s%s%s%s(0x%lx, ", numregs,
1729 (vd ? "NR" : ""), (a45 ? (a45==4 ? "A4" : "A5") : ""),
1730 (BaseName[0] ? "" : "UB"),
1731 (fD_GetFuncParNum(obj)==illegal ? "" : "FP"), -fD_GetOffset(obj));
1732 if (!vd)
1733 fprintf(outfile, "%s, ", rettype);
1734 fprintf(outfile, "%s, ", name);
1736 for (count=d0; count<numregs; count++)
1738 chtmp=fD_GetRegStr(obj, count);
1739 if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
1740 chtmp="d7";
1741 fprintf(outfile, "%s, %s, %s%s", (fD_GetFuncParNum(obj)==count ?
1742 "__fpt" : fD_GetProto(obj, count)),
1743 fD_GetParam(obj, count),
1744 chtmp, (count==numregs-1 && !BaseName[0] ? "" : ", "));
1747 if (BaseName[0]) /* was "##base" used? */
1748 fprintf(outfile, "\\\n\t, %s_BASE_NAME", BaseNamU);
1749 if (fD_GetFuncParNum(obj)!=illegal)
1751 fprintf(outfile, ", ");
1752 fprintf(outfile, fD_GetProto(obj, fD_GetFuncParNum(obj)), "__fpt");
1754 fprintf(outfile, ")\n\n");
1756 else if(target==M68K_POS)
1758 fprintf(outfile, ") \\\n\t__INLINE_FUN_%d(", numregs);
1759 fprintf(outfile, "__%s_BASE_NAME, __%s_LIB_NAME, 0x%lx, %s, %s%s",
1760 BaseNamU, BaseNamU, -fD_GetOffset(obj), rettype, name,
1761 (numregs ? ", \\\n\t" : ""));
1763 for (count=d0; count<numregs; count++)
1764 fprintf(outfile, "%s, %s, %s%s", fD_GetProto(obj, count),
1765 fD_GetParam(obj, count), fD_GetRegStr(obj, count),
1766 (count==numregs-1 ? "" : ", "));
1767 fprintf(outfile, ")\n\n");
1769 else if (target==PPC_POWERUP || target==PPC_MORPHOS)
1771 fprintf(outfile, ") \\\n\tLP%d%s%s(0x%lx, ",
1772 numregs,
1773 (vd ? "NR" : ""),
1774 (BaseName[0] ? "" : "UB"),
1775 -fD_GetOffset(obj));
1777 if (!vd)
1778 fprintf(outfile, "%s, ", rettype);
1779 fprintf(outfile, "%s, ", name);
1781 for (count=d0; count<numregs; count++)
1783 chtmp=fD_GetRegStr(obj, count);
1785 if (strchr(fD_GetProto(obj, count),'%'))
1787 sprintf(Buffer,
1788 fD_GetProto(obj, count),
1789 "");
1791 fprintf(outfile, "%s, %s, %s%s",
1792 Buffer,
1793 fD_GetParam(obj, count),
1794 chtmp,
1795 (count == numregs - 1 && !BaseName[0] ? "" : ", "));
1797 else
1799 fprintf(outfile, "%s, %s, %s%s",
1800 fD_GetProto(obj, count),//(fD_GetFuncParNum(obj) == count ? "__fpt" : fD_GetProt\o(obj, count)),
1801 fD_GetParam(obj, count),
1802 chtmp,
1803 (count == numregs - 1 && !BaseName[0] ? "" : ", "));
1807 if (BaseName[0])
1808 fprintf(outfile, "\\\n\t, %s_BASE_NAME", BaseNamU);
1811 * Here it would make sense to create a database file to
1812 * integrate optimizations automaticly into every new
1813 * build. Not every function needs a complete flush. For
1814 * example functions with no parameter wouldn`t need a
1815 * PPC flush normally. Or Read(File,Addr,Size); would
1816 * only need a flush for Addr with the Size
1819 fprintf(outfile, ", IF_CACHEFLUSHALL, NULL, 0, IF_CACHEFLUSHALL, NULL, 0");
1820 fprintf(outfile, ")\n\n");
1822 else if (target==IX86BE_AMITHLON)
1824 fprintf(outfile, ") \\\n\tLP%d%s%s(0x%lx, ",
1825 numregs,
1826 (vd ? "NR" : ""),
1827 (BaseName[0] ? "" : "UB"),
1828 -fD_GetOffset(obj));
1830 if (!vd)
1831 fprintf(outfile, "%s, ", rettype);
1832 fprintf(outfile, "%s, ", name);
1834 for (count=d0; count<numregs; count++)
1836 chtmp=fD_GetRegStr(obj, count);
1838 if (strchr(fD_GetProto(obj, count),'%'))
1840 sprintf(Buffer,
1841 fD_GetProto(obj, count),
1842 "");
1844 fprintf(outfile, "%s, %s, %s%s",
1845 Buffer,
1846 fD_GetParam(obj, count),
1847 chtmp,
1848 (count == numregs - 1 && !BaseName[0] ? "" : ", "));
1850 else
1852 fprintf(outfile, "%s, %s, %s%s",
1853 fD_GetProto(obj, count),
1854 fD_GetParam(obj, count),
1855 chtmp,
1856 (count == numregs - 1 && !BaseName[0] ? "" : ", "));
1860 if (BaseName[0])
1861 fprintf(outfile, "\\\n\t, %s_BASE_NAME", BaseNamU);
1863 fprintf(outfile, ")\n\n");
1865 else if (target==AROS)
1867 fprintf(outfile, ") \\\n\tAROS_LC%d%s(%s, %s, \\\n",
1868 numregs,
1869 (BaseName[0] ? "" : "I"),
1870 (vd ? "void" : rettype),
1871 name);
1873 for (count=d0; count<numregs; count++)
1875 chtmp=fD_GetRegStrU(obj, count);
1876 fprintf(outfile, "\tAROS_LCA(%s, (%s), %s), \\\n",
1877 fD_GetProto(obj, count),
1878 fD_GetParam(obj, count),
1879 chtmp);
1882 if (BaseName[0]) /* was "##base" used? */
1884 fprintf(outfile, "\tstruct %s *, %s_BASE_NAME, ", StdLib, BaseNamU);
1886 else
1888 fprintf(outfile, "\t/* bt */, /* bn */, ");
1890 fprintf(outfile,
1891 "%ld, /* s */)\n\n",
1892 -fD_GetOffset(obj) / 6);
1894 else
1896 fprintf(stderr, "Internal error: Unknown target in fD_write().\n");
1897 return;
1900 else if (output_mode==OLD || output_mode==STUBS)
1902 fprintf(outfile, "%s__inline %s\n%s(%s",
1903 (output_mode==STUBS ? "" : "extern "), rettype, name,
1904 (BaseName[0] ? (numregs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
1906 if (target==M68K_AMIGAOS)
1908 for (count=d0; count<numregs; count++)
1910 chtmp=fD_GetProto(obj, count);
1911 if (fD_GetFuncParNum(obj)==count)
1912 fprintf(outfile, chtmp, fD_GetParam(obj, count));
1913 else
1914 fprintf(outfile, "%s%s%s", chtmp, (*(chtmp+strlen(chtmp)-1)=='*' ?
1915 "" : " "), fD_GetParam(obj, count));
1916 if (count<numregs-1)
1917 fprintf(outfile, ", ");
1920 fprintf(outfile, ")\n{\n%s", (BaseName[0] ? " BASE_EXT_DECL\n" : ""));
1921 if (!vd)
1922 fprintf(outfile, " register %s%sres __asm(\"d0\");\n", rettype,
1923 (*(rettype+strlen(rettype)-1)=='*' ? "" : " "));
1925 if (BaseName[0])
1926 fprintf(outfile, " register struct %s *a6 __asm(\"a6\") = BASE_NAME;\n",
1927 StdLib);
1929 for (count=d0; count<numregs; count++)
1931 chtmp=fD_GetRegStr(obj, count);
1932 if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
1933 chtmp="d7";
1934 if (fD_GetFuncParNum(obj)==count)
1936 fprintf(outfile, " register ");
1937 fprintf(outfile, fD_GetProto(obj, count), chtmp);
1938 fprintf(outfile, " __asm(\"%s\") = %s;\n", chtmp, fD_GetParam(obj,
1939 count));
1941 else
1943 const char *proto=fD_GetProto(obj, count);
1944 fprintf(outfile, " register %s%s%s __asm(\"%s\") = %s;\n",
1945 proto, (*(proto+strlen(proto)-1)=='*' ? "" : " "), chtmp,
1946 chtmp, fD_GetParam(obj, count));
1949 if (a45)
1950 fprintf(outfile, " __asm volatile (\"exg d7,%s\\n\\t"
1951 "jsr a6@(-0x%lx:W)\\n\\texg d7,%s\"\n", (a45==4 ? "a4" : "a5"),
1952 -fD_GetOffset(obj), (a45==4 ? "a4" : "a5"));
1953 else
1954 fprintf(outfile, " __asm volatile (\"jsr a6@(-0x%lx:W)\"\n",
1955 -fD_GetOffset(obj));
1957 fprintf(outfile, (vd ? " : /* No Output */\n" : " : \"=r\" (res)\n"));
1959 fprintf(outfile, " : ");
1960 if (BaseName[0])
1961 fprintf(outfile, "\"r\" (a6)%s", (numregs ? ", ": ""));
1963 for (count=d0; count<numregs; count++)
1965 chtmp=fD_GetRegStr(obj, count);
1966 if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
1967 chtmp="d7";
1968 fprintf(outfile, "\"r\" (%s)%s", chtmp, (count<numregs-1 ? ", " : ""));
1970 fprintf(outfile, "\n : \"d0\", \"d1\", \"a0\", \"a1\", \"fp0\", \"fp1\"");
1972 if (vd)
1973 fprintf(outfile, ", \"cc\", \"memory\");\n}\n\n"); /* { */
1974 else
1975 fprintf(outfile, ", \"cc\", \"memory\");\n return res;\n}\n\n");
1978 else if (target==PPC_POWERUP)
1980 for (count = d0; count < numregs; count++)
1982 chtmp = fD_GetProto(obj, count);
1983 if (fD_GetFuncParNum(obj) == count)
1984 fprintf(outfile, chtmp, fD_GetParam(obj, count));
1985 else
1986 fprintf(outfile, "%s%s%s", chtmp, (*(chtmp + strlen(chtmp) - 1) == '*' ?
1987 "" : " "), fD_GetParam(obj, count));
1988 if (count < numregs - 1)
1989 fprintf(outfile, ", ");
1992 fprintf(outfile, ")\t\n");
1993 fprintf(outfile, "{\t\n");
1994 fprintf(outfile, "struct Caos\tMyCaos;\n");
1995 fprintf(outfile, "\tMyCaos.M68kCacheMode\t=\tIF_CACHEFLUSHALL;\t\n");
1996 fprintf(outfile, "//\tMyCaos.M68kStart\t=\tNULL;\t\n");
1997 fprintf(outfile, "//\tMyCaos.M68kSize\t\t=\t0;\t\n");
1998 fprintf(outfile, "\tMyCaos.PPCCacheMode\t=\tIF_CACHEFLUSHALL;\t\n");
1999 fprintf(outfile, "//\tMyCaos.PPCStart\t\t=\tNULL;\t\n");
2000 fprintf(outfile, "//\tMyCaos.PPCSize\t\t=\t0;\t\n");
2002 if (numregs > 0)
2004 for (count = d0; count < numregs; count++)
2006 fprintf(outfile, "\tMyCaos.%s\t\t=(ULONG) %s;\t\n",
2007 fD_GetRegStr(obj, count),
2008 fD_GetParam(obj, count));
2012 fprintf(outfile, "\tMyCaos.caos_Un.Offset\t=\t(%ld);\t\n", fD_GetOffset(obj));
2013 if (BaseName[0]) /*
2014 * was "##base" used?
2017 fprintf(outfile, "\tMyCaos.a6\t\t=\t(ULONG) BASE_NAME;\t\n");
2019 if (vd)
2021 fprintf(outfile, "\tPPCCallOS(&MyCaos);\t\n}\n\n");
2023 else
2025 fprintf(outfile, "\treturn((%s)PPCCallOS(&MyCaos));\n}\n\n",
2026 rettype);
2029 else if (target==PPC_MORPHOS)
2031 for (count = d0; count < numregs; count++)
2033 chtmp = fD_GetProto(obj, count);
2034 if (fD_GetFuncParNum(obj) == count)
2035 fprintf(outfile, chtmp, fD_GetParam(obj, count));
2036 else
2037 fprintf(outfile, "%s%s%s", chtmp, (*(chtmp + strlen(chtmp) - 1) == '*' ?
2038 "" : " "), fD_GetParam(obj, count));
2039 if (count < numregs - 1)
2040 fprintf(outfile, ", ");
2043 fprintf(outfile, ")\t\n{\t\n");
2045 if (numregs > 0)
2047 for (count = d0; count < numregs; count++)
2049 fprintf(outfile, "\tREG_%s\t\t=\t(ULONG) %s;\n",
2050 fD_GetRegStrU(obj, count), fD_GetParam(obj, count));
2054 if (BaseName[0]) /*
2055 * was "##base" used?
2058 fprintf(outfile, "\tREG_A6\t\t=\t(ULONG) BASE_NAME;\n");
2060 if (vd)
2062 fprintf(outfile, "\t(*MyEmulHandle->EmulCallDirectOS)(%ld);\n}\n\n", fD_GetOffset(obj));
2064 else
2066 fprintf(outfile, "\treturn((%s)(*MyEmulHandle->EmulCallDirectOS)(%ld));\n}\n\n",
2067 rettype, fD_GetOffset(obj));
2070 else if (target==IX86BE_AMITHLON)
2072 #if 0
2073 for (count = d0; count < numregs; count++)
2075 chtmp = fD_GetProto(obj, count);
2076 if (fD_GetFuncParNum(obj) == count)
2077 fprintf(outfile, chtmp, fD_GetParam(obj, count));
2078 else
2079 fprintf(outfile, "%s%s%s", chtmp, (*(chtmp + strlen(chtmp) - 1) == '*' ?
2080 "" : " "), fD_GetParam(obj, count));
2081 if (count < numregs - 1)
2082 fprintf(outfile, ", ");
2085 fprintf(outfile, ")\n{\n");
2086 fprintf(outfile, "\tstruct _Regs _regs;\n");
2088 if (numregs > 0)
2090 for (count = d0; count < numregs; count++)
2092 fprintf(outfile, "\t_regs.reg_%s = (ULONG) (%s);\n",
2093 fD_GetRegStr(obj, count),
2094 fD_GetParam(obj, count));
2098 if (BaseName[0])
2100 fprintf(outfile, "\t_regs.reg_a6 = (ULONG) (BASE_NAME);\n");
2103 if (vd)
2105 fprintf(outfile, "\t_CallOS68k(%ld,&_regs);\n}\n\n",
2106 -fD_GetOffset(obj));
2108 else
2110 fprintf(outfile, "\treturn (%s) _CallOS68k(%ld,&_regs);\n}\n\n",
2111 rettype,-fD_GetOffset(obj));
2113 #else
2114 for (count = d0; count < numregs; count++)
2116 chtmp = fD_GetProto(obj, count);
2117 if (fD_GetFuncParNum(obj) == count)
2118 fprintf(outfile, chtmp, fD_GetParam(obj, count));
2119 else
2120 fprintf(outfile, "%s%s%s", chtmp, (*(chtmp + strlen(chtmp) - 1) == '*' ?
2121 "" : " "), fD_GetParam(obj, count));
2122 if (count < numregs - 1)
2123 fprintf(outfile, ", ");
2126 fprintf(outfile, ")\n{\n");
2127 fprintf(outfile, "\t%s LP%d%s%s(0x%lx, ",
2128 (vd ? "" : "return "),
2129 numregs,
2130 (vd ? "NR" : ""),
2131 (BaseName[0] ? "" : "UB"),
2132 -fD_GetOffset(obj));
2134 if (!vd)
2135 fprintf(outfile, "%s, ", rettype);
2136 fprintf(outfile, "%s, ", name);
2138 for (count=d0; count<numregs; count++)
2140 chtmp=fD_GetRegStr(obj, count);
2142 if (strchr(fD_GetProto(obj, count),'%'))
2144 sprintf(Buffer,
2145 fD_GetProto(obj, count),
2146 "");
2148 fprintf(outfile, "%s, %s, %s%s",
2149 Buffer,
2150 fD_GetParam(obj, count),
2151 chtmp,
2152 (count == numregs - 1 && !BaseName[0] ? "" : ", "));
2154 else
2156 fprintf(outfile, "%s, %s, %s%s",
2157 fD_GetProto(obj, count),
2158 fD_GetParam(obj, count),
2159 chtmp,
2160 (count == numregs - 1 && !BaseName[0] ? "" : ", "));
2164 if (BaseName[0])
2165 fprintf(outfile, "\\\n\t, BASE_NAME");
2167 fprintf(outfile, ");\n}\n\n");
2168 #endif
2170 else
2172 fprintf(stderr, "Internal error: Unknown target in fD_write().\n");
2173 return;
2176 else if (output_mode==GATESTUBS || output_mode==GATEPROTO)
2178 int has_base = (BaseName[0] && fD_GetOffset(obj) != 0);
2180 //lcs
2181 if (target==AROS)
2183 for (count=d0; count<numregs; count++)
2185 if (fD_GetFuncParNum(obj) == count)
2187 char funcproto[200]; /* Hope will be enough... */
2188 sprintf(funcproto, "%s_%s_funcproto_%d",
2189 BaseNamC, name, count );
2190 fprintf(outfile, "typedef ");
2191 fprintf(outfile, fD_GetProto(obj, count), funcproto);
2192 fprintf(outfile, ";\n");
2197 if (output_mode==GATESTUBS)
2199 fprintf(outfile, "%s %s%s(",
2200 rettype,
2201 libprefix,
2202 name);
2204 for (count=d0; count<numregs; count++)
2206 chtmp = fD_GetProto(obj, count);
2208 fprintf(outfile, chtmp, "");
2209 fprintf(outfile, "%s",
2210 (count == numregs - 1 && !has_base ? ");\n" : ", "));
2213 if (has_base)
2214 fprintf(outfile, "struct %s *);\n", StdLib);
2217 if (target==M68K_AMIGAOS)
2219 fprintf(outfile, "%s %s%s(\n",
2220 rettype,
2221 gateprefix,
2222 name);
2224 for (count=d0; count<numregs; count++)
2226 chtmp = fD_GetProto(obj, count);
2228 if (fD_GetFuncParNum(obj) == count)
2230 fprintf(outfile, "\t");
2231 fprintf(outfile, chtmp,
2232 fD_GetParam(obj, count));
2233 fprintf(outfile, " __asm(\"%s\")%s",
2234 fD_GetRegStr(obj, count),
2235 (count == numregs - 1 && !has_base ? ")\n" : ",\n"));
2237 else
2239 fprintf(outfile, "\t%s %s __asm(\"%s\")%s",
2240 chtmp,
2241 fD_GetParam(obj, count),
2242 fD_GetRegStr(obj, count),
2243 (count == numregs - 1 && !has_base ? ")\n" : ",\n"));
2247 if (has_base)
2248 fprintf(outfile, "\tstruct %s * BASE_NAME __asm(\"a6\") )\n", StdLib);
2250 if (output_mode==GATESTUBS)
2251 fprintf(outfile, "{\n");
2253 else if (target==AROS)
2255 fprintf(outfile, "AROS_LH%d%s(%s, %s%s,\n",
2256 numregs,
2257 has_base ? "" : "I",
2258 rettype,
2259 gateprefix,
2260 name);
2262 for (count=d0; count<numregs; count++)
2264 char funcproto[200]; /* Hope will be enough... */
2266 if (fD_GetFuncParNum(obj) == count)
2268 sprintf(funcproto, "%s_%s_funcproto_%d",
2269 BaseNamC, name, count );
2272 fprintf(outfile, "\tAROS_LHA(%s, %s, %s),\n",
2273 fD_GetFuncParNum(obj) == count ? funcproto : fD_GetProto(obj, count),
2274 fD_GetParam(obj, count),
2275 fD_GetRegStrU(obj, count));
2278 fprintf(outfile, "\tstruct %s *, BASE_NAME, %ld, %s)\n",
2279 StdLib,
2280 -fD_GetOffset(obj) / 6,
2281 BaseNamC);
2283 if (output_mode==GATESTUBS)
2284 fprintf(outfile, "{\n");
2286 else if (target==PPC_MORPHOS)
2288 fprintf(outfile, "%s %s%s(void)\n",
2289 rettype,
2290 gateprefix,
2291 name);
2293 if (output_mode==GATESTUBS)
2295 fprintf(outfile, "{\n");
2297 for (count=d0; count<numregs; count++)
2299 chtmp = fD_GetProto(obj, count);
2301 if (fD_GetFuncParNum(obj) == count)
2303 fprintf(outfile, "\t");
2304 fprintf(outfile, chtmp,
2305 fD_GetParam(obj, count));
2306 fprintf(outfile, " = (");
2307 fprintf(outfile, chtmp, "");
2308 fprintf(outfile, ") REG_%s;\n",
2309 fD_GetRegStrU(obj, count));
2311 else
2313 fprintf(outfile, "\t%s %s = (%s) REG_%s;\n",
2314 fD_GetProto(obj, count),
2315 fD_GetParam(obj, count),
2316 fD_GetProto(obj, count),
2317 fD_GetRegStrU(obj, count));
2321 if (has_base)
2322 fprintf(outfile,
2323 "\tstruct %s * BASE_NAME = (struct %s *) REG_A6;\n",
2324 StdLib, StdLib);
2326 fprintf(outfile, "\n");
2329 else if (target==IX86BE_AMITHLON)
2331 fprintf(outfile, "%s %s%s( struct _Regs _regs )\n",
2332 rettype,
2333 gateprefix,
2334 name);
2336 if (output_mode==GATESTUBS)
2338 fprintf(outfile, "{\n");
2340 for (count=d0; count<numregs; count++)
2342 chtmp = fD_GetProto(obj, count);
2344 if (fD_GetFuncParNum(obj) == count)
2346 fprintf(outfile, "\t");
2347 fprintf(outfile, chtmp,
2348 fD_GetParam(obj, count));
2349 fprintf(outfile, " = (");
2350 fprintf(outfile, chtmp, "");
2351 fprintf(outfile, ") _regs.%s;\n",
2352 fD_GetRegStr(obj, count));
2354 else
2356 fprintf(outfile, "\t%s %s = (%s) _regs.%s;\n",
2357 fD_GetProto(obj, count),
2358 fD_GetParam(obj, count),
2359 fD_GetProto(obj, count),
2360 fD_GetRegStr(obj, count));
2364 if (has_base)
2365 fprintf(outfile,
2366 "\tstruct %s * BASE_NAME = (struct %s *) _regs.a6;\n",
2367 StdLib, StdLib);
2369 fprintf(outfile, "\n");
2372 else
2374 fprintf(stderr, "Internal error: Unknown target in fD_write().\n");
2375 return;
2378 if (output_mode==GATESTUBS)
2380 fprintf(outfile,"\treturn %s%s(",
2381 libprefix,
2382 name);
2384 for (count=d0; count<numregs; count++)
2386 fprintf(outfile, "%s%s",
2387 fD_GetParam(obj, count),
2388 (count == numregs - 1 && !has_base ? ");" : ", "));
2391 if (has_base)
2392 fprintf(outfile, "BASE_NAME);");
2394 fprintf(outfile,"\n}\n\n");
2396 else
2398 fprintf(outfile,";\n");
2400 if (target==AROS)
2402 fprintf(outfile, "#define %s%s AROS_SLIB_ENTRY(%s%s,%s)\n",
2403 gateprefix, name,
2404 gateprefix, name,
2405 BaseNamC);
2408 fprintf(outfile,"\n");
2411 else
2413 fprintf(stderr, "Internal error: Unknown output mode in fD_write().\n");
2414 return;
2417 if ((tagname=aliasfunction(fD_GetName(obj)))!=0 &&
2418 output_mode!=GATESTUBS && output_mode!=GATEPROTO)
2420 fprintf(outfile, "#define %s(", tagname);
2421 for (count=d0; count<numregs-1; count++)
2422 fprintf(outfile, "a%d, ", count);
2423 fprintf(outfile, "a%d) %s (", count, name);
2424 for (count=d0; count<numregs-1; count++)
2425 fprintf(outfile, "(a%d), ", count);
2426 fprintf(outfile, "(a%d))\n\n", count);
2429 if ((tagname=taggedfunction(obj))!=0 &&
2430 output_mode!=GATESTUBS && output_mode!=GATEPROTO)
2432 if (output_mode!=STUBS)
2434 fprintf( outfile,
2435 "#ifndef %sNO_INLINE_STDARG\n"
2436 "#define %s(",
2437 (target==M68K_POS ? "__" : ""),
2438 tagname);
2440 for (count=d0; count<numregs-1; count++)
2441 fprintf(outfile, "a%d, ", count);
2443 fprintf(outfile, "...) \\\n\t({ULONG _tags[] = { __VA_ARGS__ }; %s(",
2444 name);
2446 for (count=d0; count<numregs-1; count++)
2447 fprintf(outfile, "(a%d), ", count);
2449 fprintf(outfile, "(%s)_tags);})\n#endif /* !%sNO_INLINE_STDARG */\n\n",
2450 fD_GetProto(obj, fD_RegNum(obj)-1),
2451 (target==M68K_POS ? "__" : ""));
2454 else
2456 if (target==M68K_AMIGAOS || target==IX86BE_AMITHLON)
2458 fprintf(outfile, "__inline %s\n%s(", rettype, tagname);
2460 for (count=d0; count<numregs-1; count++)
2462 chtmp=fD_GetProto(obj, count);
2463 if (count==fD_GetFuncParNum(obj))
2464 fprintf(outfile, chtmp, fD_GetParam(obj, count));
2465 else
2466 fprintf(outfile, "%s%s%s", chtmp,
2467 (*(chtmp+strlen(chtmp)-1)=='*' ? "" : " "),
2468 fD_GetParam(obj, count));
2469 fprintf(outfile, ", ");
2472 fprintf(outfile, "int tag, ...)\n{\n ");
2473 if (!vd)
2474 fprintf(outfile, "return ");
2476 fprintf(outfile, "%s(", name);
2477 for (count=d0; count<numregs-1; count++)
2478 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
2480 fprintf(outfile, "(%s)&tag);\n}\n\n", fD_GetProto(obj, fD_RegNum(obj)-1));
2482 else if (target==PPC_MORPHOS)
2484 int n = 9 - numregs; /* number of regs that contain varargs */
2485 int d = n & 1 ? 4 : 0; /* add 4 bytes if that's an odd number, to avoid splitting a tag */
2486 int taglist = 8; /* offset of the start of the taglist */
2487 int local = (taglist + n * 4 + d + 8 + 15) & ~15; /* size of the stack frame */
2490 * Stack frame:
2492 * 0 - 3: next frame ptr
2493 * 4 - 7: save lr
2494 * 8 - 8+n*4+d+8-1: tag list start
2495 * ? - local-1: padding
2498 fprintf(outfile,
2499 "asm(\"\n"
2500 " .align 2 \n"
2501 " .globl %s \n"
2502 " .type %s,@function\n"
2503 "%s: \n"
2504 " stwu 1,-%d(1) \n" /* create stack frame */
2505 " mflr 0 \n"
2506 " stw 0,%d(1) \n",
2507 tagname, tagname, tagname, local, local + 4);
2510 * If n is odd, one tag is split between regs and stack.
2511 * Copy its ti_Data together with the ti_Tag.
2513 if (d)
2514 fprintf(outfile, " lwz 0,%d(1)\n", local + 8); /* read ti_Data */
2516 * Save the registers
2518 for (count = numregs; count <= 8; count++)
2519 fprintf(outfile, " stw %d,%d(1)\n", count + 2, (count - numregs) * 4 + taglist);
2521 if (d)
2522 fprintf(outfile, " stw 0,%d(1)\n", taglist + n * 4); /* write ti_Data */
2525 * Add TAG_MORE
2527 fprintf(outfile, " li 11,2 \n"
2528 " addi 0,1,%d \n"
2529 " stw 11,%d(1) \n" /* add TAG_MORE */
2530 " stw 0,%d(1) \n", /* ti_Data = &stack_params */
2531 local + 8 + d,
2532 taglist + n * 4 + d,
2533 taglist + n * 4 + d + 4);
2536 if (DirectVarargsCalls)
2538 fprintf(outfile,
2539 " addi %d,1,%d \n" /* vararg_reg = &saved regs */
2540 " bl %s \n",
2541 numregs + 2, taglist, name);
2543 else
2546 * Save the non-varargs registers in the EmulHandle struct.
2548 for (count = 0; count < numregs - 1; count++)
2550 int r = fD_GetReg(obj, count);
2552 fprintf(outfile, " stw %d,%d(2)\n", count + 3, r * 4);
2555 fprintf(outfile,
2556 " lis 12,%s@ha \n"
2557 " addi 0,1,%d \n"
2558 " lwz 11,0x64(2)\n" /* r11 = EmulCallDirectOS */
2559 " stw 0,%d(2) \n" /* REG_?? = taglist */
2560 " mtctr 11 \n"
2561 " lwz 12,%s@l(12)\n"
2562 " li 3,%ld \n" /* r3 = lvo */
2563 " stw 12,56(2) \n" /* REG_A6 = libbase */
2564 " bctrl \n",/* EmulCallOS() */
2565 BaseName, taglist, 4 * fD_GetReg(obj, numregs - 1), BaseName,
2566 fD_GetOffset(obj));
2569 fprintf(outfile," lwz 0,%d(1) \n" /* clear stack frame & return */
2570 " mtlr 0 \n"
2571 " addi 1,1,%d \n"
2572 " blr \n"
2573 ".L%se1: \n"
2574 " .size\t%s,.L%se1-%s\n"
2575 "\");\n\n",
2576 local + 4, local,
2577 tagname, tagname, tagname, tagname);
2579 else
2581 fprintf(stderr, "Internal error: Unknown target in fD_write().\n");
2582 return;
2586 else if ((varname = getvarargsfunction(obj)) != 0 &&
2587 output_mode!=GATESTUBS && output_mode!=GATEPROTO)
2589 if (output_mode != STUBS)
2591 fprintf(outfile,
2592 "#ifndef NO_INLINE_VARARGS\n"
2593 "#define %s(", varname);
2595 for (count = d0; count < numregs - 1; count++)
2596 fprintf(outfile, "a%d, ", count);
2598 fprintf(outfile,
2599 "...) \\\n"
2600 "\t({ULONG _tags[] = { __VA_ARGS__ }; %s(",
2601 name);
2603 for (count = d0; count < numregs - 1; count++)
2604 fprintf(outfile, "(a%d), ", count);
2606 fprintf(outfile,
2607 "(%s)_tags);})\n"
2608 "#endif /* !NO_INLINE_VARARGS */\n\n",
2609 fD_GetProto(obj, fD_RegNum(obj) - 1));
2611 else
2613 fprintf(stderr, "can`t create a varargs stub function for %s\n",
2614 varname);
2618 if (strcmp(name, "DoPkt")==0 &&
2619 output_mode!=GATESTUBS && output_mode!=GATEPROTO)
2621 fdDef *objnc=(fdDef*)obj;
2622 char newname[7]="DoPkt0";
2623 objnc->name=newname;
2624 for (count=2; count<7; count++)
2626 regs reg=objnc->reg[count];
2627 char *proto=objnc->proto[count];
2628 objnc->reg[count]=illegal;
2629 objnc->proto[count]=fD_nostring;
2630 fD_write(outfile, objnc);
2631 objnc->reg[count]=reg;
2632 objnc->proto[count]=proto;
2633 newname[5]++;
2635 objnc->name=(char*)name;
2640 varargsfunction(const char* proto, const char* funcname)
2642 const char *end=proto+strlen(proto)-1;
2643 while (isspace(*end))
2644 end--;
2645 if (*end--==';')
2647 while (isspace(*end))
2648 end--;
2649 if (*end--==')')
2651 while (isspace(*end))
2652 end--;
2653 if (!strncmp(end-2, "...", 3))
2655 /* Seems to be a varargs function. Check if it will be recognized
2656 as "tagged". */
2657 unsigned int count;
2658 char fixedname[200]; /* Hope will be enough... */
2659 fdDef *tmpdef;
2661 for (count=0; count<sizeof TagExcTable/sizeof TagExcTable[0];
2662 count+=2)
2663 if (strcmp(funcname, TagExcTable[count+1])==0)
2664 return 1;
2666 if (!(tmpdef=fD_ctor()))
2668 fprintf(stderr, "No mem for FDs\n");
2669 exit(EXIT_FAILURE);
2672 strcpy(fixedname, funcname);
2673 if (strlen(funcname)>4 &&
2674 !strcmp(funcname+strlen(funcname)-4, "Tags"))
2676 /* Might be either nothing or "TagList". */
2677 fixedname[strlen(fixedname)-4]='\0';
2678 fD_NewName(tmpdef, fixedname);
2679 if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
2680 fD_cmpName))
2681 return 1;
2683 strcat(fixedname, "TagList");
2684 fD_NewName(tmpdef, fixedname);
2685 if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
2686 fD_cmpName))
2687 return 1;
2689 else
2691 strcat(fixedname, "A");
2692 fD_NewName(tmpdef, fixedname);
2693 if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
2694 fD_cmpName))
2695 return 1;
2700 return 0;
2704 ishandleddifferently(const char* proto, const char* funcname)
2706 /* First check if this is a vararg call? */
2707 if (varargsfunction(proto, funcname))
2708 return 1;
2710 /* It might be a dos.library "alias" name. */
2711 if (aliasfunction(funcname))
2712 return 1;
2714 /* It might be one from dos.library/DoPkt() family. */
2715 if (strlen(funcname)==6 && !strncmp(funcname, "DoPkt", 5) &&
2716 funcname[5]>='0' && funcname[6]<='4')
2717 return 1;
2719 /* Finally, it can be intuition.library/ReportMouse1(). */
2720 return !strcmp(funcname, "ReportMouse1");
2723 void
2724 printusage(const char* exename)
2726 fprintf(stderr,
2727 "Usage: %s [options] fd-file clib-file [[-o] output-file]\n"
2728 "Options:\n"
2730 "--mode=MODE\t\tMODE is one of the following:\n"
2731 "\tnew\t\t\tPreprocessor based (default)\n"
2732 "\told\t\t\tInline based\n"
2733 "\tstubs\t\t\tLibrary stubs\n"
2734 "\tgatestubs\t\tLibrary gate stubs\n"
2735 "\tgateproto\t\tLibrary gate prototypes\n"
2736 "\tproto\t\t\tBuild proto files (no clib-file required)\n"
2738 "--target=OS\t\tOS is one of the following: \n"
2739 "\t*-aros\t\t\tAROS (any CPU)\n"
2740 "\ti?86be*-amithlon\tAmithlon (Intel x86)\n"
2741 "\tm68k*-amigaos\t\tAmigaOS (Motorola 68000)\n"
2742 "\tm68k*-pos\t\tPOS (Motorola 68000)\n"
2743 "\tpowerpc*-powerup\tPowerUp (PowerPC)\n"
2744 "\tpowerpc*-morphos\tMorphOS (PowerPC)\n"
2746 "--direct-varargs-calls\tUse direct varargs call for MorphOS stubs\n"
2747 "--gateprefix=PREFIX\tLibrary gate function name prefix\n"
2748 "--libprefix=PREFIX\tLocal function name prefix\n"
2749 "--local\t\t\tUse local includes\n"
2750 "--quiet\t\t\tDon't display warnings\n"
2751 "--version\t\tPrint version number and exit\n\n"
2752 "Compatibility options:\n"
2753 "--new\t\t\tSame as --mode=new\n"
2754 "--old\t\t\tSame as --mode=old\n"
2755 "--stubs\t\t\tSame as --mode=stubs\n"
2756 "--gatestubs\t\tSame as --mode=gatestubs\n"
2757 "--proto\t\t\tSame as --mode=prot\n"
2758 "--pos\t\t\tSame as --target=m68k-pos\n"
2759 "--morphos\t\tSame as --target=powerpc-morphos\n"
2760 "--powerup\t\tSame as --target=powerpc-powerup\n"
2761 , exename);
2764 void output_proto(FILE* outfile)
2766 fprintf(outfile,
2767 "/* Automatically generated header! Do not edit! */\n\n"
2768 "#ifndef PROTO_%s_H\n"
2769 "#define PROTO_%s_H\n\n"
2770 "#include <clib/%s_protos.h>\n\n"
2771 "#ifndef _NO_INLINE\n"
2772 "#ifdef __GNUC__\n"
2773 "#include <inline/%s.h>\n"
2774 "#endif /* __GNUC__ */\n"
2775 "#endif /* !_NO_INLINE */\n\n",
2776 BaseNamU, BaseNamU, BaseNamL, BaseNamL);
2778 if (BaseName[0])
2779 fprintf(outfile,
2780 "#ifndef __NOLIBBASE__\n"
2781 "extern struct %s *\n"
2782 "#ifdef __CONSTLIBBASEDECL__\n"
2783 "__CONSTLIBBASEDECL__\n"
2784 "#endif /* __CONSTLIBBASEDECL__ */\n"
2785 "%s;\n"
2786 "#endif /* !__NOLIBBASE__ */\n\n",
2787 StdLib, BaseName);
2789 fprintf(outfile,
2790 "#endif /* !PROTO_%s_H */\n", BaseNamU);
2793 /******************************************************************************/
2796 main(int argc, char** argv)
2798 fdDef *tmpdef, /* a dummy to contain the name to look for */
2799 *founddef; /* the fdDef for which we found a prototype */
2800 fdFile *myfile;
2801 char *tmpstr;
2802 FILE *outfile;
2803 int closeoutfile=0;
2804 char *fdfilename=0, *clibfilename=0, *outfilename=0;
2806 int count;
2807 Error lerror;
2809 for (count=1; count<argc; count++)
2811 char *option=argv[count];
2812 if (*option=='-')
2814 option++;
2815 if (strcmp(option, "o")==0)
2817 if (count==argc-1 || outfilename)
2819 printusage(argv[0]);
2820 return EXIT_FAILURE;
2822 if (strcmp(argv[++count], "-"))
2823 outfilename=argv[count];
2825 else
2827 if (*option=='-') /* Accept GNU-style '--' options */
2828 option++;
2829 if (strncmp(option, "mode=", 5)==0)
2831 if (strcmp(option+5, "new")==0)
2832 output_mode=NEW;
2833 else if (strcmp(option+5, "old")==0)
2834 output_mode=OLD;
2835 else if (strcmp(option+5, "stubs")==0)
2836 output_mode=STUBS;
2837 else if (strcmp(option+5, "gatestubs")==0)
2838 output_mode=GATESTUBS;
2839 else if (strcmp(option+5, "gateproto")==0)
2840 output_mode=GATEPROTO;
2841 else if (strcmp(option+5, "proto")==0)
2842 output_mode=PROTO;
2844 else if (strncmp(option, "target=", 7)==0)
2846 if (MatchGlob("*-aros",option+7))
2847 target=AROS;
2848 else if (MatchGlob("i?86be*-amithlon",option+7))
2849 target=IX86BE_AMITHLON;
2850 else if (MatchGlob("m68k*-amigaos",option+7))
2851 target=M68K_AMIGAOS;
2852 else if (MatchGlob("m68k*-pos",option+7))
2853 target=M68K_POS;
2854 else if (MatchGlob("powerpc*-powerup",option+7))
2855 target=PPC_POWERUP;
2856 else if (MatchGlob("powerpc*-morphos",option+7))
2857 target=PPC_MORPHOS;
2858 else
2860 printusage(argv[0]);
2861 return EXIT_FAILURE;
2864 else if (strcmp(option, "direct-varargs-calls") == 0)
2865 DirectVarargsCalls = 1;
2866 else if (strncmp(option, "gateprefix=", 11)==0)
2867 gateprefix = option+11;
2868 else if (strncmp(option, "libprefix=", 10)==0)
2869 libprefix = option+10;
2870 else if (strcmp(option, "quiet") == 0)
2871 Quiet = 1;
2872 else if (strcmp(option, "version")==0)
2874 fprintf(stderr, "fd2inline version " VERSION "\n");
2875 return EXIT_SUCCESS;
2877 /* Compatibility options */
2878 else if (strcmp(option, "new")==0)
2879 output_mode=NEW;
2880 else if (strcmp(option, "old")==0)
2881 output_mode=OLD;
2882 else if (strcmp(option, "stubs")==0)
2883 output_mode=STUBS;
2884 else if (strcmp(option, "gatestubs")==0)
2885 output_mode=GATESTUBS;
2886 else if (strcmp(option, "proto")==0)
2887 output_mode=PROTO;
2888 else if (strcmp(option, "pos")==0)
2889 target=M68K_POS;
2890 else if (strcmp(option, "powerup")==0)
2891 target=PPC_POWERUP;
2892 else if (strcmp(option, "morphos")==0)
2893 target=PPC_MORPHOS;
2894 /* Unknown option */
2895 else
2897 printusage(argv[0]);
2898 return EXIT_FAILURE;
2902 else
2904 /* One of the filenames */
2905 if (!fdfilename)
2906 fdfilename=option;
2907 else if (!clibfilename)
2908 clibfilename=option;
2909 else if (!outfilename)
2910 outfilename=option;
2911 else
2913 printusage(argv[0]);
2914 return EXIT_FAILURE;
2919 if (!fdfilename || (!clibfilename && output_mode!=PROTO))
2921 printusage(argv[0]);
2922 return EXIT_FAILURE;
2925 if (target==M68K_POS && output_mode!=NEW)
2927 fprintf(stderr, "Target is not compatible with the mode.\n");
2928 return EXIT_FAILURE;
2931 if (!(arrdefs=malloc(FDS*sizeof(fdDef*))))
2933 fprintf(stderr, "No mem for FDs\n");
2934 return EXIT_FAILURE;
2936 for (count=0; count<FDS; count++)
2937 arrdefs[count]=NULL;
2939 if (!(myfile=fF_ctor(fdfilename)))
2941 fprintf(stderr, "Couldn't open file '%s'.\n", fdfilename);
2942 return EXIT_FAILURE;
2945 lerror=false;
2947 for (count=0; count<FDS && lerror==false; count++)
2949 if (!(arrdefs[count]=fD_ctor()))
2951 fprintf(stderr, "No mem for FDs\n" );
2952 return EXIT_FAILURE;
2956 if ((lerror=fF_readln(myfile))==false)
2958 fF_SetError(myfile, false);
2959 lerror=fD_parsefd(arrdefs[count], myfile);
2962 while (lerror==nodef);
2964 if (count<FDS)
2966 count--;
2967 fD_dtor(arrdefs[count]);
2968 arrdefs[count]=NULL;
2970 fds=count;
2972 qsort(arrdefs, count, sizeof arrdefs[0], fD_cmpName);
2974 if (output_mode!=NEW || target==AROS)
2976 unsigned int count2;
2977 StdLib="Library";
2979 for (count2=0; count2<sizeof LibExcTable/sizeof LibExcTable[0]; count2+=2)
2980 if (strcmp(BaseName, LibExcTable[count2])==0)
2982 StdLib=LibExcTable[count2+1];
2983 break;
2987 fF_dtor(myfile);
2989 if (output_mode!=PROTO)
2991 if (!(myfile=fF_ctor(clibfilename)))
2993 fprintf(stderr, "Couldn't open file '%s'.\n", clibfilename);
2994 return EXIT_FAILURE;
2997 if (!(tmpdef=fD_ctor()))
2999 fprintf(stderr, "No mem for FDs\n");
3000 return EXIT_FAILURE;
3003 for (lerror=false; lerror==false || lerror==nodef;)
3004 if ((lerror=fF_readln(myfile))==false)
3006 fF_SetError(myfile, false); /* continue even on errors */
3007 tmpstr=fF_FuncName(myfile);
3009 if (tmpstr)
3011 fdDef **res;
3012 fD_NewName(tmpdef, tmpstr);
3013 res=(fdDef**)bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
3014 fD_cmpName);
3016 if (res)
3018 founddef=*res;
3019 DBP(fprintf(stderr, "found (%s).\n", fD_GetName(founddef)));
3020 fF_SetError(myfile, false);
3021 lerror=fD_parsepr(founddef, myfile);
3023 else
3024 if (!ishandleddifferently(myfile->line, tmpstr))
3025 if (!Quiet)
3026 fprintf(stderr, "Don't know what to do with <%s> in line %lu.\n",
3027 tmpstr, myfile->lineno);
3028 free(tmpstr);
3032 fD_dtor(tmpdef);
3034 fF_dtor(myfile);
3037 if (strlen(fdfilename)>7 &&
3038 !strcmp(fdfilename+strlen(fdfilename)-7, "_lib.fd"))
3040 char *str=fdfilename+strlen(fdfilename)-8;
3041 while (str!=fdfilename && str[-1]!='/' && str[-1]!=':')
3042 str--;
3043 //lcs strncpy(BaseNamL, str, strlen(str)-7);
3044 strncpy(BaseNamU, str, strlen(str)-7);
3045 BaseNamU[strlen(str)-7]='\0';
3046 strcpy(BaseNamL, BaseNamU);
3047 strcpy(BaseNamC, BaseNamU);
3049 else
3051 strcpy(BaseNamU, BaseName);
3052 if (strlen(BaseNamU)>4 && strcmp(BaseNamU+strlen(BaseNamU)-4, "Base")==0)
3053 BaseNamU[strlen(BaseNamU)-4]='\0';
3054 if (target==M68K_POS && strncmp(BaseNamU, "gb_", 3)==0)
3055 memmove(BaseNamU, &BaseNamU[3], strlen(&BaseNamU[3])+1);
3056 strcpy(BaseNamL, BaseNamU);
3057 strcpy(BaseNamC, BaseNamU);
3059 StrUpr(BaseNamU);
3060 BaseNamC[0]=toupper(BaseNamC[0]);
3062 if (outfilename)
3064 if (!(outfile=fopen(outfilename, "w")))
3066 fprintf(stderr, "Couldn't open output file.\n");
3067 return EXIT_FAILURE;
3069 else
3071 closeoutfile=1;
3074 else
3075 outfile=stdout;
3077 if (output_mode==PROTO)
3078 output_proto(outfile);
3079 else
3081 if (output_mode==NEW || output_mode==OLD || output_mode==STUBS ||
3082 output_mode==GATESTUBS || output_mode==GATEPROTO)
3084 if (output_mode==GATESTUBS || output_mode==GATEPROTO)
3086 fprintf(outfile,
3087 "/* Automatically generated stubs! Do not edit! */\n\n");
3089 else
3091 fprintf(outfile,
3092 "/* Automatically generated header! Do not edit! */\n\n"
3093 "#ifndef %sINLINE_%s_H\n"
3094 "#define %sINLINE_%s_H\n\n",
3095 (target==M68K_POS ? "__INC_POS_P" : "_"),
3096 BaseNamU,
3097 (target==M68K_POS ? "__INC_POS_P" : "_"),
3098 BaseNamU );
3101 if (output_mode==NEW)
3103 if(target==M68K_POS)
3105 fprintf(outfile,
3106 "#ifndef __INC_POS_PINLINE_MACROS_H\n"
3107 "#include <pInline/macros.h>\n"
3108 "#endif /* !__INC_POS_PINLINE_MACROS_H */\n\n" );
3110 else if(target==AROS)
3112 fprintf(outfile,
3113 "#ifndef AROS_LIBCALL_H\n"
3114 "#include <aros/libcall.h>\n"
3115 "#endif /* !AROS_LIBCALL_H */\n\n");
3117 else
3119 fprintf(outfile,
3120 "#ifndef __INLINE_MACROS_H\n"
3121 "#include <inline/macros.h>\n"
3122 "#endif /* !__INLINE_MACROS_H */\n\n");
3125 else
3127 FILE* clib;
3129 fprintf(outfile,
3130 "#ifndef __INLINE_STUB_H\n"
3131 "#include <inline/stubs.h>\n"
3132 "#endif /* !__INLINE_STUB_H */\n\n");
3134 fprintf(outfile, "#ifdef __CLIB_TYPES__\n" );
3136 clib = fopen( clibfilename, "r" );
3138 if( clib == NULL )
3140 fprintf(stderr, "Couldn't open file '%s'.\n", clibfilename);
3142 else
3144 char* buffer = malloc( 1024 );
3146 if( buffer == NULL )
3148 fprintf(stderr, "No memory for line buffer.\n " );
3150 else
3152 while( fgets( buffer, 1023, clib ) != NULL )
3154 if( buffer[ 0 ] == '#' /* Pre-processor instruction */ ||
3155 strncmp( buffer, "typedef", 7 ) == 0 )
3157 fprintf(outfile, buffer );
3161 free( buffer );
3164 fclose( clib );
3167 fprintf(outfile, "#endif /* __CLIB_TYPES__ */\n\n" );
3169 if(target==AROS)
3171 fprintf(outfile,
3172 "#include <aros/libcall.h>\n\n" );
3174 else if(target==IX86BE_AMITHLON)
3176 fprintf(outfile,
3177 "#ifndef __INLINE_MACROS_H\n"
3178 "#include <inline/macros.h>\n"
3179 "#endif /* __INLINE_MACROS_H */\n\n");
3181 else if (target == PPC_MORPHOS)
3183 fprintf(outfile,
3184 "#include <emul/emulregs.h>\n\n" );
3188 else
3190 fprintf(stderr, "Internal error: Unknown output mode in main().\n");
3192 if (closeoutfile)
3194 fclose(outfile);
3197 return EXIT_FAILURE;
3200 if (BaseName[0])
3202 if (output_mode==NEW)
3204 fprintf(outfile,
3205 "#ifndef %s%s_BASE_NAME\n"
3206 "#define %s%s_BASE_NAME %s\n"
3207 "#endif /* !%s%s_BASE_NAME */\n\n",
3208 (target==M68K_POS ? "__" : ""), BaseNamU,
3209 (target==M68K_POS ? "__" : ""), BaseNamU, BaseName,
3210 (target==M68K_POS ? "__" : ""), BaseNamU);
3211 if (target==M68K_POS)
3212 fprintf(outfile,
3213 "#ifndef __%s_LIB_NAME\n"
3214 "#define __%s_LIB_NAME %s\n"
3215 "#endif /* !__%s_LIB_NAME */\n\n",
3216 BaseNamU, BaseNamU,
3217 (strcmp(BaseName, "gb_ExecBase") ? BaseName : "gb_ExecLib"),
3218 BaseNamU);
3220 else
3221 fprintf(outfile,
3222 "#ifndef BASE_EXT_DECL\n"
3223 "#define BASE_EXT_DECL\n"
3224 "#define BASE_EXT_DECL0 extern struct %s *%s;\n"
3225 "#endif /* !BASE_EXT_DECL */\n"
3226 "#ifndef BASE_PAR_DECL\n"
3227 "#define BASE_PAR_DECL\n"
3228 "#define BASE_PAR_DECL0 void\n"
3229 "#endif /* !BASE_PAR_DECL */\n"
3230 "#ifndef BASE_NAME\n"
3231 "#define BASE_NAME %s\n"
3232 "#endif /* !BASE_NAME */\n\n"
3233 "BASE_EXT_DECL0\n\n", StdLib, BaseName, BaseName);
3236 for (count=0; count<FDS && arrdefs[count]; count++)
3238 DBP(fprintf(stderr, "outputting %ld...\n", count));
3240 fD_write(outfile, arrdefs[count]);
3241 fD_dtor(arrdefs[count]);
3242 arrdefs[count]=NULL;
3245 if (output_mode!=NEW)
3246 if (BaseName[0])
3247 fprintf(outfile,
3248 "#undef BASE_EXT_DECL\n"
3249 "#undef BASE_EXT_DECL0\n"
3250 "#undef BASE_PAR_DECL\n"
3251 "#undef BASE_PAR_DECL0\n"
3252 "#undef BASE_NAME\n\n");
3254 if (output_mode==NEW || output_mode==OLD || output_mode==STUBS)
3256 fprintf(outfile, "#endif /* !%sINLINE_%s_H */\n",
3257 (target==M68K_POS ? "__INC_POS_P" : "_"), BaseNamU);
3261 free(arrdefs);
3263 if (closeoutfile)
3265 fclose(outfile);
3268 return EXIT_SUCCESS;