2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
15 /* Prototypes of reusable functions */
17 /* Read in one line from file
18 - mallocs needed space */
19 char *get_line(FILE *file
);
21 /* Search for '#Keyword' in string
22 - mallocs needed space
23 - returns 'Keyword' */
24 char *keyword(char *line
);
26 /* Searches line for whitespace separated words
27 - outarray = pointer to array of found words (strings)
28 - mallocs needed space
29 - frees previously allocated space before !
31 char **words=NULL; get_words(line,&words) */
32 int get_words(char *line
, char ***outarray
);
34 /* Converts string to lower case */
35 void strlower(char *string
);
38 returns 0 for equal files,
39 1 for different files,
40 -1 if file1 is not present,
41 -2 if file2 is not present */
42 int filesdiffer( char *file1
, char *file2
);
44 /* Compares old and new file,
45 if old file is not found or different from new
46 new file will be renamed to name of old
47 old will be named old.bak */
48 void moveifchanged(char *old
, char *new);
50 /* Parses file or lib.conf if file==NULL
51 puts values in struct libconf
52 returns 0 on success */
53 struct libconf
* parse_libconf(char *file
);
56 char *get_line(FILE *fd
)
65 count
= fread(&buffer
,1,1,fd
);
67 } while(count
!=0 && buffer
!='\n');
68 if(len
==0 && count
==0)
70 fseek( fd
, -len
, SEEK_CUR
);
71 line
= malloc( (len
+1) * sizeof(char) );
72 fread (line
,1,len
,fd
);
75 while(isspace(line
[len
])&& len
>=0)
84 char *keyword(char *line
)
92 while(line
[len
] && !isspace(line
[len
]))
94 key
= malloc( len
* sizeof(char) );
95 strncpy( key
, &line
[1], len
-1 );
104 int get_words(char *line
, char ***outarray
)
112 fprintf( stderr
, "Passed invalid NULL pointer to get_words()!\n" );
130 while( *word
&& isspace(*word
) )
133 while( word
[len
] && !isspace(word
[len
]) )
138 array
= realloc( array
, (num
+1) * sizeof(char *) );
139 array
[num
-1] = malloc( (len
+1) * sizeof(char) );
140 strncpy( array
[num
-1], word
, len
);
141 array
[num
-1][len
] = 0;
153 void strlower(char *string
)
157 *string
= tolower(*string
);
162 int filesdiffer( char *file1
, char *file2
)
166 char buffer1
[1], buffer2
[1];
169 fd1
= fopen(file1
,"rb");
174 fd2
= fopen(file2
,"rb");
182 cnt1
= fread(buffer1
,1,1,fd1
);
183 cnt2
= fread(buffer2
,1,1,fd2
);
184 } while( cnt1
&& cnt2
&& buffer1
[0]==buffer2
[0] );
185 if( buffer1
[0]!=buffer2
[0] || cnt1
!= cnt2
)
194 void moveifchanged(char *old
, char *new)
196 struct stat
*statold
, *statnew
;
199 statold
= calloc(1, sizeof(struct stat
) );
200 statnew
= calloc(1, sizeof(struct stat
) );
201 if(stat(old
,statold
))
203 /* Couldn't stat old file -- assume non-existent */
209 if(stat(new,statnew
))
211 /* Couldn't stat new file -- this shouldn't happen */
212 fprintf( stderr
, "Couldn't stat() file %s!\n", new );
217 bakname
= malloc( (strlen(old
)+5) * sizeof(char) );
218 sprintf( bakname
, "%s.bak", old
);
219 if(statold
->st_size
!= statnew
->st_size
)
224 else if( filesdiffer(old
,new) )
266 char *libbasetypeptr
;
267 int version
, revision
;
275 struct libconf
* parse_libconf(char *file
)
283 fd
= fopen((file
?file
:"lib.conf"),"rb");
286 fprintf( stderr
, "Couldn't open %s!\n", (file
?file
:"lib.conf") );
289 lc
= calloc (1, sizeof (struct libconf
));
290 while( (line
= get_line(fd
)) )
292 num
= get_words(line
,&words
);
295 if( strcmp(words
[0],"name")==0 )
298 len
= strlen(words
[1]);
299 lc
->libname
= strdup(words
[1]);
301 else if( strcmp(words
[0],"libname")==0 )
304 lc
->libname
= strdup(words
[1]);
306 else if( strcmp(words
[0],"basename")==0 )
308 len
= strlen(words
[1]);
310 lc
->basename
= strdup(words
[1]);
312 else if( strcmp(words
[0],"libbase")==0 )
314 len
= strlen(words
[1]);
316 lc
->libbase
= strdup(words
[1]);
318 else if( strcmp(words
[0],"libbasetype")==0 )
321 for( i
=1 ; i
<num
; i
++ )
322 len
+= strlen(words
[i
]);
324 free(lc
->libbasetype
);
325 lc
->libbasetype
= malloc( len
* sizeof(char) );
326 strcpy(lc
->libbasetype
, words
[1] );
327 for( i
=2 ; i
<num
; i
++ )
329 strcat( lc
->libbasetype
, " " );
330 strcat( lc
->libbasetype
, words
[i
] );
333 else if( strcmp(words
[0],"libbasetypeptr")==0 )
336 for( i
=1 ; i
<num
; i
++ )
337 len
+= strlen(words
[i
]);
339 free(lc
->libbasetypeptr
);
340 lc
->libbasetypeptr
= malloc( len
* sizeof(char) );
341 strcpy(lc
->libbasetypeptr
, words
[1]);
342 for( i
=2 ; i
<num
; i
++ )
344 strcat( lc
->libbasetypeptr
, " " );
345 strcat( lc
->libbasetypeptr
, words
[i
] );
348 else if( strcmp(words
[0],"version")==0 )
351 while( words
[1][i
] && words
[1][i
]!='.' )
353 lc
->revision
= (words
[1][i
]==0?0:atoi(&words
[1][i
+1]));
361 lc
->version
= atoi(words
[1]);
364 else if( strcmp(words
[0],"copyright")==0 )
367 while( *word
&& isspace(*word
) )
370 lc
->copyright
= strdup(word
);
372 else if( strcmp(words
[0],"define")==0 )
375 lc
->define
= strdup(words
[1]);
377 else if( strcmp(words
[0],"type")==0 )
379 if( strcmp(words
[1],"device")==0 )
381 else if( strcmp(words
[1],"library")==0 )
382 lc
->type
= t_library
;
383 else if( strcmp(words
[1],"resource")==0 )
384 lc
->type
= t_resource
;
385 else if( strcmp(words
[1],"hidd")==0 )
387 else if( strcmp(words
[1],"gadget")==0 )
389 else if( strcmp(words
[1],"image")==0 )
391 else if( strcmp(words
[1],"class")==0 )
393 else if( strcmp(words
[1],"datatype")==0 )
394 lc
->type
= t_datatype
;
395 else if( strcmp(words
[1],"usbclass")==0 )
396 lc
->type
= t_usbclass
;
398 else if( strcmp(words
[0],"options")==0 || strcmp(words
[0],"option")==0 )
400 for( i
=1 ; i
<num
; i
++ )
402 if( strcmp(words
[i
],"noexpunge")==0 )
403 lc
->option
|= o_noexpunge
;
404 else if( strcmp(words
[i
],"rom")==0 )
406 else if( strcmp(words
[i
],"unique")==0 )
407 lc
->option
|= o_unique
;
408 else if( strcmp(words
[i
],"nolibheader")==0 )
409 lc
->option
|= o_nolibheader
;
410 else if( strcmp(words
[i
],"hasrt")==0 )
411 lc
->option
|= o_hasrt
;
419 if( lc
->libname
== NULL
)
421 fprintf( stderr
, "Missing field \"name\" in lib.conf!\n" );
424 if( lc
->basename
== NULL
)
426 lc
->basename
= strdup(lc
->libname
);
427 lc
->basename
[0] = toupper(lc
->basename
[0]);
429 if( lc
->libbase
== NULL
)
431 lc
->libbase
= malloc( (strlen(lc
->basename
)+5) * sizeof(char) );
432 sprintf( lc
->libbase
, "%sBase", lc
->basename
);
434 if( lc
->libbasetype
== NULL
)
436 lc
->libbasetype
= malloc( (strlen(lc
->libbase
)+8) * sizeof(char) );
437 sprintf( lc
->libbasetype
, "struct %s", lc
->libbase
);
439 if( lc
->libbasetypeptr
== NULL
)
441 lc
->libbasetypeptr
= malloc( (strlen(lc
->libbasetype
)+3) * sizeof(char) );
442 sprintf( lc
->libbasetypeptr
, "%s *", lc
->libbasetype
);
445 if( lc
->define
== NULL
)
446 lc
->define
= strdup( "_LIBDEFS_H" );
448 lc
->type
= t_library
;
455 # Create libdefs.h from a file lib.conf. lib.conf may contain these options:
457 # name <string> - Init the various fields with reasonable defaults. If
458 # <string> is XXX, then this is the result:
463 # libbasetype XxxBase
464 # libbasetypeptr XxxBase *
466 # Variables will only be changed if they have not yet been
469 # libname <string> - Set libname to <string>. This is the name of the
470 # library (ie. you can open it with <string>.library).
471 # It will show up in the version string, too.
472 # basename <string> - Set basename to <string>. The basename is used in
473 # the AROS-LHx macros in the location part (last parameter)
474 # and to specify defaults for libbase and libbasetype
475 # in case they have no value yet. If <string> is xXx, then
476 # libbase will become xXxBase and libbasetype will become
478 # libbase <string> - Defines the name of the library base (ie. SysBase,
479 # DOSBase, IconBase, etc). If libbasetype is not set, then
480 # it is set to <string>, too.
481 # libbasetype <string> - The type of libbase (with struct), ie.
482 # struct ExecBase, struct DosLibrary, struct IconBase, etc).
483 # libbasetypeptr <string> - Type of a pointer to the libbase. (eg.
484 # struct ExecBase *).
485 # version <version>.<revision> - Specifies the version and revision of the
486 # library. 41.0103 means version 41 and revision 103.
487 # copyright <string> - Copyright string.
488 # define <string> - The define to use to protect the resulting file
489 # against double inclusion (ie. #ifndef <string>...)
490 # The default is _LIBDEFS_H.
491 # type <string> - What kind of library is this ? Valid values
492 # for <string> are: device, library, resource and hidd.
493 # option <string>... - Specify an option. Valid values for <string> are:
495 # noexpunge - Once the lib/dev is loaded, it can't be
496 # removed from memory. Be careful with this
498 # rom - For ROM based libraries. Implies noexpunge and
500 # unique - Generate unique names for all external
502 # nolibheader - We don't want to use the LibHeader prefixed
503 # functions in the function table.
504 # hasrt - This library has resource tracking.
506 # You can specify more than one option in a config file and
507 # more than one option per option line. Separate options by
511 int genlibdefs(int argc
, char **argv
)
515 char *date
, *filename
, *conffile
;
520 filename
= "libdefs.h";
521 conffile
= "lib.conf";
522 for (i
=2; i
<=argc
; i
++)
524 if (strcmp(argv
[i
-1],"-o")==0)
530 conffile
= argv
[i
-1];
534 date
= malloc( 11 * sizeof(char) );
535 sprintf( date
, "%02d.%02d.%4d", tm
->tm_mday
, tm
->tm_mon
+1, tm
->tm_year
+1900 );
536 fd
= fopen(filename
,"w");
539 fprintf( stderr
, "Couldn't open file %s!\n", "libdefs.h.new" );
543 if(!(lc
= parse_libconf(conffile
)) )
549 if( lc
->copyright
== NULL
)
551 lc
->copyright
= strdup("");
553 fprintf( fd
, "/* *** Automatic generated file. Do not edit *** */\n\n");
554 fprintf( fd
, "#ifndef %s\n#define %s\n", lc
->define
, lc
->define
);
556 if (lc
->type
== t_library
)
558 fprintf( fd
, "#define NAME_STRING \"%s.library\"\n", lc
->libname
);
559 fprintf( fd
, "#define NT_TYPE NT_LIBRARY\n" );
561 else if (lc
->type
== t_device
)
563 fprintf( fd
, "#define NAME_STRING \"%s.device\"\n", lc
->libname
);
564 fprintf( fd
, "#define NT_TYPE NT_DEVICE\n" );
566 else if (lc
->type
== t_resource
)
568 fprintf( fd
, "#define NAME_STRING \"%s.resource\"\n", lc
->libname
);
569 fprintf( fd
, "#define NT_TYPE NT_RESOURCE\n" );
571 else if (lc
->type
== t_hidd
)
573 fprintf( fd
, "#define NAME_STRING \"%s.hidd\"\n", lc
->libname
);
574 fprintf( fd
, "#define NT_TYPE NT_HIDD\n" );
576 else if (lc
->type
== t_gadget
)
578 fprintf( fd
, "#define NAME_STRING \"%s.gadget\"\n", lc
->libname
);
579 fprintf( fd
, "#define NT_TYPE NT_LIBRARY\n" );
581 else if (lc
->type
== t_image
)
583 fprintf( fd
, "#define NAME_STRING \"%s.image\"\n", lc
->libname
);
584 fprintf( fd
, "#define NT_TYPE NT_LIBRARY\n" );
586 else if (lc
->type
== t_class
)
588 fprintf( fd
, "#define NAME_STRING \"%s.class\"\n", lc
->libname
);
589 fprintf( fd
, "#define NT_TYPE NT_LIBRARY\n" );
591 else if (lc
->type
== t_datatype
)
593 fprintf( fd
, "#define NAME_STRING \"%s.datatype\"\n", lc
->libname
);
594 fprintf( fd
, "#define NT_TYPE NT_LIBRARY\n" );
596 else if (lc
->type
== t_usbclass
)
598 fprintf( fd
, "#define NAME_STRING \"%s.class\"\n", lc
->libname
);
599 fprintf( fd
, "#define NT_TYPE NT_LIBRARY\n" );
602 if (lc
->option
& o_rom
)
603 lc
->option
|= o_noexpunge
;
605 if (lc
->option
& o_noexpunge
)
606 fprintf( fd
, "#define NOEXPUNGE\n" );
607 if (lc
->option
& o_rom
)
608 fprintf( fd
, "#define ROMBASED\n" );
609 if (lc
->option
& o_nolibheader
)
610 fprintf( fd
, "#define NOLIBHEADER\n" );
612 if (lc
->option
& o_rom
|| lc
->option
& o_unique
)
614 fprintf( fd
, "#define LC_UNIQUE_PREFIX %s\n", lc
->basename
);
615 fprintf( fd
, "#define LC_BUILDNAME(n) %s ## n\n", lc
->basename
);
619 fprintf( fd
, "#define LC_BUILDNAME(n) n\n" );
622 fprintf( fd
, "#define LIBBASE %s\n", lc
->libbase
);
623 fprintf( fd
, "#define LIBBASETYPE %s\n", lc
->libbasetype
);
624 fprintf( fd
, "#define LIBBASETYPEPTR %s\n", lc
->libbasetypeptr
);
625 fprintf( fd
, "#define VERSION_NUMBER %d\n", lc
->version
);
626 fprintf( fd
, "#define REVISION_NUMBER %d\n", lc
->revision
);
627 fprintf( fd
, "#define BASENAME %s\n", lc
->basename
);
628 fprintf( fd
, "#define BASENAME_STRING \"%s\"\n", lc
->basename
);
629 fprintf( fd
, "#define VERSION_STRING \"$VER: %s %d.%d (%s)\\r\\n\"\n", lc
->libname
, lc
->version
, lc
->revision
, date
);
630 fprintf( fd
, "#define LIBEND %s_end\n", lc
->basename
);
631 fprintf( fd
, "#define LIBFUNCTABLE %s_functable\n", lc
->basename
);
632 fprintf( fd
, "#define COPYRIGHT_STRING \"%s\"\n", lc
->copyright
);
633 fprintf( fd
, "#endif /* %s */\n", lc
->define
);
641 void emit(FILE *out
, struct libconf
*lc
, char **names
, int number
)
645 fprintf( out
, "/*\n" );
646 fprintf( out
, " Copyright %c 1995-2015, The AROS Development Team. All rights reserved.\n", 0xa9 );
647 fprintf( out
, " *** Automatic generated file. Do not edit ***\n" );
648 fprintf( out
, " Desc: Function table for %s\n", lc
->basename
);
649 fprintf( out
, " Lang: english\n" );
650 fprintf( out
, "*/\n" );
651 fprintf( out
, "#ifndef LIBCORE_COMPILER_H\n" );
652 fprintf( out
, "# include <libcore/compiler.h>\n" );
653 fprintf( out
, "#endif\n" );
654 fprintf( out
, "#ifndef NULL\n" );
655 fprintf( out
, "#define NULL ((void *)0)\n" );
656 fprintf( out
, "#endif\n\n" );
657 fprintf( out
, "#ifndef LC_LIBDEFS_FILE\n" );
658 fprintf( out
, "#define LC_LIBDEFS_FILE \"libdefs.h\"\n" );
659 fprintf( out
, "#endif\n" );
660 fprintf( out
, "#include LC_LIBDEFS_FILE\n" );
661 if(lc
->option
& o_nolibheader
)
663 fprintf( out
, "extern void AROS_SLIB_ENTRY(open,BASENAME,1) (void);\n" );
664 fprintf( out
, "extern void AROS_SLIB_ENTRY(close,BASENAME,2) (void);\n" );
665 fprintf( out
, "extern void AROS_SLIB_ENTRY(expunge,BASENAME,3) (void);\n" );
666 fprintf( out
, "extern void AROS_SLIB_ENTRY(null,BASENAME,0) (void);\n" );
670 fprintf( out
, "extern void AROS_SLIB_ENTRY(LC_BUILDNAME(OpenLib),LibHeader,1) (void);\n" );
671 fprintf( out
, "extern void AROS_SLIB_ENTRY(LC_BUILDNAME(CloseLib),LibHeader,2) (void);\n" );
672 fprintf( out
, "extern void AROS_SLIB_ENTRY(LC_BUILDNAME(ExpungeLib),LibHeader,3) (void);\n" );
673 fprintf( out
, "extern void AROS_SLIB_ENTRY(LC_BUILDNAME(ExtFuncLib),LibHeader,4) (void);\n" );
675 for( i
= 0 ; i
< number
-4 ; i
++ )
678 fprintf( out
, "extern void AROS_SLIB_ENTRY(%s,BASENAME,%d) (void);\n", names
[i
], i
+5 );
680 fprintf( out
, "\nvoid *const LIBFUNCTABLE[]=\n{\n" );
681 if(lc
->option
& o_nolibheader
)
683 fprintf( out
, " AROS_SLIB_ENTRY(open, BASENAME, 1),\n" );
684 fprintf( out
, " AROS_SLIB_ENTRY(close, BASENAME, 2),\n" );
685 fprintf( out
, " AROS_SLIB_ENTRY(expunge, BASENAME, 3),\n" );
686 fprintf( out
, " AROS_SLIB_ENTRY(null, BASENAME, 0),\n" );
690 fprintf( out
, " AROS_SLIB_ENTRY(LC_BUILDNAME(OpenLib),LibHeader,1),\n" );
691 fprintf( out
, " AROS_SLIB_ENTRY(LC_BUILDNAME(CloseLib),LibHeader,2),\n" );
692 fprintf( out
, " AROS_SLIB_ENTRY(LC_BUILDNAME(ExpungeLib),LibHeader,3),\n" );
693 fprintf( out
, " AROS_SLIB_ENTRY(LC_BUILDNAME(ExtFuncLib),LibHeader,4),\n" );
695 for( i
= 0 ; i
< number
-4 ; i
++ )
698 fprintf( out
, " AROS_SLIB_ENTRY(%s,BASENAME,%d), /* %d */\n", names
[i
], i
+5, i
+5 );
700 fprintf( out
, " NULL, /* %d */\n", i
+5 );
702 fprintf( out
, " (void *)-1L\n};\n" );
705 int genfunctable(int argc
, char **argv
)
707 FILE *fd
= NULL
, *fdo
;
710 char *word
, **words
= NULL
;
711 int in_archive
, in_header
, in_function
, in_autodoc
, in_code
;
713 char *funcname
= NULL
, **funcnames
= NULL
;
715 /* Well, there are already 4 functions (open,close,expunge,null) */
721 /* First check if we have a HIDD which does not have an archive */
722 if(!(lc
=parse_libconf(NULL
)))
725 if (lc
->type
== t_hidd
|| lc
->type
== t_gadget
|| lc
->type
== t_class
|| lc
->type
== t_usbclass
)
732 fd
= fopen(argv
[1],"rb");
735 fprintf( stderr
, "Couldn't open file %s!\n", argv
[1] );
745 fprintf( stderr
, "Usage: %s <archfile>\n", argv
[0] );
749 fdo
= fopen("functable.c.new","w");
752 fprintf( stderr
, "Couldn't open file %s!\n", "functable.c.new" );
763 while( (line
= get_line(fd
)) )
765 word
= keyword(line
);
768 if( strcmp(word
,"Archive")==0 && !in_archive
)
770 else if( strcmp(word
,"/Archive")==0 && in_archive
&& ! in_function
)
772 else if( strcmp(word
,"AutoDoc")==0 && in_function
&& !in_autodoc
&& !in_code
)
774 else if( strcmp(word
,"/AutoDoc")==0 && in_autodoc
)
776 else if( strcmp(word
,"Code")==0 && in_function
&& !in_code
&& !in_autodoc
)
778 else if( strcmp(word
,"/Code")==0 && in_code
)
780 else if( strcmp(word
,"Header")==0 && in_archive
&& !in_function
)
782 else if( strcmp(word
,"/Header")==0 && in_header
)
784 else if( strcmp(word
,"Function")==0 && in_archive
&& !in_function
&& !in_header
)
786 num
= get_words(line
,&words
);
787 funcname
= strdup(words
[num
-1]);
790 else if( strcmp(word
,"/Function")==0 && in_function
&& !in_autodoc
&& !in_code
)
792 else if( strcmp(word
,"LibOffset")==0 && in_function
&& !in_autodoc
&& !in_code
)
794 get_words(line
,&words
);
795 num
= atoi(words
[1]);
798 funcnames
= realloc( funcnames
, (num
-4) * sizeof(char *));
799 /* initialize new memory */
800 for( ;numfuncs
<num
; numfuncs
++)
801 funcnames
[numfuncs
-4] = NULL
;
803 funcnames
[num
-5] = funcname
;
811 emit(fdo
,lc
,funcnames
,numfuncs
);
817 moveifchanged("functable.c","functable.c.new");
824 const char * m68k_registers
[] = {
843 struct pragma_description
845 struct pragma_description
*next
;
848 unsigned short offset
;
853 char * skipstr(char * line
, char skipper
,int direction
)
855 while (line
[0] == skipper
) {
861 void free_pragma_description(struct pragma_description
* pd
)
863 struct pragma_description
* _pd
;
872 struct pragma_description
* find_pragma_description(struct pragma_description
* pd
,
876 if (0 == strcmp(pd
->funcname
,
884 struct pragma_description
* parse_pragmas(char * filename
)
888 struct pragma_description
* base_pd
= NULL
;
889 fdi
= fopen(filename
,"r");
892 fprintf(stderr
, "Couldn't open file %s!\n",filename
);
896 while( (line
= get_line(fdi
))) {
898 //printf("%s\n",line);
900 * look for '#', then 'pragma'.
902 substr
= skipstr(line
,' ',1);
904 if (substr
[0] == '#'){
906 substr
= skipstr(substr
, ' ',1);
907 //printf("1. %s\n",substr);
908 if (0 == strncmp(substr
, "pragma",6)) {
910 substr
= skipstr(substr
,' ',1);
911 //printf("2. %s\n",substr);
912 if (!strncmp(substr
, "amicall",7)) {
914 substr
= skipstr(substr
,' ',1);
916 if (substr
[0] == '(') {
917 struct pragma_description
* pd
= calloc(1,sizeof(struct pragma_description
));
919 substr
= skipstr(substr
,' ',1);
926 * Now read the name of the base
929 comma
= strchr(substr
, ',');
930 lastchar
= skipstr(comma
-1,' ',-1);
932 strncpy(&pd
->basename
[0],
935 //printf("basename: %s\n",pd->basename);
938 * after the comma comes the offset in HEX!
940 pd
->offset
= strtol(comma
+1,&lastchar
,16)/6;
941 //printf("Offset : %x\n",pd->offset);
944 * Now for the next ','
946 comma
= strchr(lastchar
, ',');
947 comma
= skipstr(comma
+1,' ',1);
948 //printf("%s\n",comma);
950 if ( NULL
== comma
) {
951 fprintf(stderr
, "%d: Error parsing pragma file!\n",__LINE__
);
952 free_pragma_description(base_pd
);
958 * Now the name of the function
960 lastchar
= strchr(comma
+1, '(');
961 if ( NULL
== lastchar
) {
962 fprintf(stderr
, "%d: Error parsing pragma file!\n",__LINE__
);
963 free_pragma_description(base_pd
);
969 strncpy(&pd
->funcname
[0],
971 skipstr(lastchar
,' ',-1)-comma
);
972 //printf("funcname: %s\n",pd->funcname);
974 substr
= lastchar
+ 1;
975 //printf("%s\n",substr);
976 lastchar
= strchr(substr
,')');
978 * Now read the CPU registers.
981 while (substr
< lastchar
) {
983 substr
= skipstr(substr
, ' ',1);
985 if (substr
[0] == 'a' ||
988 } else if (substr
[0] == 'd' ||
991 fprintf(stderr
, "Wrong register (letter) in pragma file!\n");
992 free_pragma_description(base_pd
);
997 if (substr
[1] >= '0' && substr
[1] <= '8') {
998 r
+= substr
[1] - '0';
1000 fprintf(stderr
, "Wrong register (number) in pragma file!\n");
1001 free_pragma_description(base_pd
);
1007 printf("parameter %d goes into %s\n",
1011 pd
->args
[pd
->numargs
] = r
;
1015 skipstr(substr
, ' ', 1);
1022 } else if (!strncmp(substr
, "libcall",7)) {
1023 struct pragma_description
* pd
= calloc(1,sizeof(struct pragma_description
));
1025 //substr = skipstr(substr,' ',1);
1028 char parameters_s
[20];
1029 char hex
[3]={0,0,0};
1032 * Read in the description of the
1035 sscanf(substr
, "%s %s %s %s",
1040 pd
->offset
= strtol(offset_s
,NULL
,16)/6;
1042 printf("|%s| |%s| %d %s[%zd]\t",
1047 strlen(parameters_s
));
1050 * Process the parameters.
1052 i
= strlen(parameters_s
)-1;
1053 hex
[0] = parameters_s
[i
-1];
1054 hex
[1] = parameters_s
[i
];
1056 pd
->numargs
= strtol(hex
,NULL
,16);
1060 hex
[0] = parameters_s
[i
];
1061 pd
->args
[c
] = strtol(hex
,NULL
,16);
1062 printf("%s ",m68k_registers
[pd
->args
[c
]]);
1071 } else if(!strncmp(substr
, "usrcall",7)) {
1073 substr
= skipstr(substr
,' ',1);
1075 if (substr
[0] == '(') {
1076 struct pragma_description
* pd
= calloc(1,sizeof(struct pragma_description
));
1078 substr
= skipstr(substr
,' ',1);
1081 pd
->offset
= 0xffff; // sign for user function
1085 * Now the name of the function
1087 printf("%s\n",substr
);
1088 lastchar
= strchr(substr
+1, '(');
1089 if ( NULL
== lastchar
) {
1090 fprintf(stderr
, "%d: Error parsing pragma file!\n",__LINE__
);
1091 free_pragma_description(base_pd
);
1097 strncpy(&pd
->funcname
[0],
1099 skipstr(lastchar
,' ',-1)-substr
);
1100 //printf("funcname: %s\n",pd->funcname);
1102 substr
= lastchar
+ 1;
1103 //printf("%s\n",substr);
1104 lastchar
= strchr(substr
,')');
1106 * Now read the CPU registers.
1109 while (substr
< lastchar
) {
1111 substr
= skipstr(substr
, ' ',1);
1113 if (substr
[0] == 'a' ||
1116 } else if (substr
[0] == 'd' ||
1119 fprintf(stderr
, "Wrong register (letter) in pragma file!\n");
1120 free_pragma_description(base_pd
);
1125 if (substr
[1] >= '0' && substr
[1] <= '8') {
1126 r
+= substr
[1] - '0';
1128 fprintf(stderr
, "Wrong register (number) in pragma file!\n");
1129 free_pragma_description(base_pd
);
1135 printf("parameter %d goes into %s\n",
1139 pd
->args
[pd
->numargs
] = r
;
1143 skipstr(substr
, ' ', 1);
1161 int countchars (char * s
, char c
)
1173 * Add a line to the cache. If NULL is added the old cache
1174 * is flushed to the disk.
1175 * If a line is added everything that ended with a ';' up
1176 * to that point will be written into the file and the
1177 * cache will be cut down to everything that was not written
1179 * If a 'end-of-comment' is added also everything is flushed to output.
1181 char * addtocache(char * cache
, char * newline
, int len
, FILE * fdo
)
1185 char * newcache
= NULL
;
1188 if (NULL
== newline
) {
1189 if (NULL
!= cache
) {
1190 fprintf(fdo
, "%s\n", cache
);
1197 semic
= strchr(newline
, ';');
1198 endcomment
= strstr(newline
, "*/");
1200 if (NULL
!= semic
|| NULL
!= endcomment
) {
1201 int newlinelen
= strlen(newline
);
1202 int i
= newlinelen
-1;
1205 * write the cache and everything up to the
1206 * last ';' in the new line to the file.
1208 if (NULL
!= cache
) {
1209 fprintf(fdo
,"%s\n",cache
);
1210 //printf("1. Flush: |%s|\n",cache);
1213 if (NULL
!= endcomment
) {
1214 i
= endcomment
- newline
+ 1;
1216 while (newline
[i
] != ';')
1222 memcpy(tmp
,newline
,i
+1);
1224 fprintf(fdo
, "%s",tmp
);
1225 //printf("2. Flush: |%s|\n",tmp);
1228 if (i
< newlinelen
) {
1229 newcache
= malloc(newlinelen
-i
+1);
1230 memcpy(newcache
, &newline
[i
+1], newlinelen
-i
);
1231 newcache
[newlinelen
-i
] = 0;
1237 * ';' could not be found. Enhance the cache.
1241 cachelen
= strlen(cache
);
1243 cachelen
+= strlen(newline
)+1+1;
1244 newcache
= malloc(cachelen
);
1246 sprintf(newcache
,"%s\n%s",cache
,newline
);
1248 sprintf(newcache
,"%s",newline
);
1249 //printf("cache: %s\tnewcache: %s\n",cache,newcache);
1256 char * clear_cache(char * cache
)
1263 * cut out all '\n' '\t' and ' ' at the end and
1264 * beginning of a string
1266 void strtrim(char ** s
)
1268 int end
= strlen(*s
)-1;
1273 while ((start
< end
) && (
1274 '\t' == (*s
)[start
] ||
1275 '\n' == (*s
)[start
] ||
1276 ' ' == (*s
)[start
])) {
1281 '\t' == (*s
)[end
] ||
1282 '\n' == (*s
)[end
] ||
1283 ' ' == (*s
)[end
])) {
1287 if ((end
> start
) && ((start
> 0) || (end_orig
!= end
))) {
1288 newstr
= malloc(end
-start
+2);
1289 strncpy(newstr
, (*s
)+start
, end
-start
+1);
1290 newstr
[end
-start
+1] = 0;
1296 char * getfuncname(char * s
)
1298 int i
= strlen(s
)-1;
1305 else if ('(' == s
[i
]) {
1309 while (i
>= 0 && ' ' == s
[i
])
1316 while (i
> 0 && ' ' != s
[i
] && '\n' != s
[i
])
1325 name
= malloc(last
-i
+2);
1326 strncpy(name
, &s
[i
+1], last
-i
);
1338 char * get_returntype(char * pattern
, char * funcname
)
1343 len
= strstr(pattern
, funcname
) - pattern
;
1345 ret_type
= malloc(len
-c
+1);
1346 strncpy(ret_type
, pattern
+c
, len
-c
);
1347 ret_type
[len
-c
] = 0;
1354 void get_argument(int num
, int max
, char * pattern
, char ** type
, char ** val
)
1359 if ('(' == pattern
[i
++]) {
1366 if (',' == pattern
[i
])
1371 /* Start of nth argument. */
1372 start
= &pattern
[i
];
1374 //printf("start: %s\n",start);
1378 if (',' == start
[i
])
1380 else if ('(' == start
[i
])
1382 else if (')' == start
[i
])
1392 //printf("end at %d\n",i);
1394 * Search for the parameter value backwards
1398 if (1 == other
&& (' ' == start
[c
] || '\t' == start
[c
] || '\n' == start
[c
] || '*' == start
[c
]))
1401 if (' ' != start
[c
])
1406 //printf("variable at %d\n",c);
1407 *type
= malloc(c
+2);
1408 strncpy(*type
, start
, c
+1);
1410 *val
= malloc(i
-c
+2);
1411 strncpy(*val
, start
+c
+1, i
-c
);
1413 //printf("|%s| |%s|\n",*type,*val);
1424 * Rewrite a c function to AROS style c function
1426 int rewrite_function(FILE * fdo
,
1428 struct pragma_description
* pd
,
1429 struct libconf
* lc
,
1435 char * argtype
, * argval
;
1436 memset(&output
[0],0,1024);
1438 printf("must pick ???? from info in: \n%s\n",pattern
);
1439 ret_type
= get_returntype(pattern
,pd
->funcname
);
1442 if (0xffff != pd
->offset
) {
1444 "\nAROS_LH%d(%s, %s,\n",
1450 while (i
< pd
->numargs
) {
1451 get_argument(i
, pd
->numargs
,pattern
, &argtype
, &argval
);
1453 " AROS_LHA(%s, %s, %s),\n",
1456 m68k_registers
[pd
->args
[i
]]);
1463 if (0 != pd
->offset
) {
1465 " %s, %s, %d, %s)\n{\n",
1472 " struct ExecBase *, SysBase, 0, %s)\n{\n",
1477 * Make the entry in the defines file. Only write
1478 * those functions with offset > 4 (not init,open,close,
1481 if (pd
->offset
> 4) {
1482 fprintf(fdefines
, "#ifndef %s\n#define %s(",
1488 while (i
< pd
->numargs
) {
1489 get_argument(i
, pd
->numargs
,pattern
, &argtype
, &argval
);
1493 if (i
< pd
->numargs
-1) {
1494 fprintf(fdefines
,",");
1502 fprintf(fdefines
,") \\\n\tAROS_LC%d(%s,%s, \\\n",
1508 while (i
< pd
->numargs
) {
1509 get_argument(i
, pd
->numargs
,pattern
, &argtype
, &argval
);
1511 "\tAROS_LCA(%s,%s,%s),\\\n",
1514 m68k_registers
[pd
->args
[i
]]);
1522 "\t%s, %s, %d, %s)\n#endif\n\n",
1532 "\nAROS_UFH%d(%s, %s",
1538 while (i
< pd
->numargs
) {
1539 get_argument(i
, pd
->numargs
,pattern
, &argtype
, &argval
);
1544 ",\n AROS_UFHA(%s, %s, %s)",
1547 m68k_registers
[pd
->args
[i
]]);
1553 fprintf(fdo
,")\n{\n");
1559 * Rewrite a whole c source code file according to the info provided
1560 * from a pragma file.
1562 int rewritecfile(FILE * fdi
,
1564 struct pragma_description
* pd
,
1565 struct libconf
* lc
,
1569 int depth
= 0; // counting '{' and '}'
1570 char * cache
= NULL
;
1573 line
= get_line(fdi
);
1575 cache
= addtocache(cache
, NULL
, 0, fdo
);
1580 depth
= countchars(line
,'{');
1584 * A function begins in this line.
1587 cache
= addtocache(cache
,line
,-1,fdo
);
1589 //printf("\ncache where to find function: %s\n",cache);
1590 funcname
= getfuncname(cache
);
1591 if (funcname
!= NULL
) {
1592 struct pragma_description
* _pd
;
1593 printf("funcname: %s",funcname
);
1594 _pd
= find_pragma_description(pd
, funcname
);
1596 printf("-> Rewriting!\n");
1597 rewrite_function(fdo
,cache
,_pd
,lc
,fdefines
);
1599 * Do not throw the cache into the
1602 cache
= clear_cache(cache
);
1604 printf("-> Not rewriting!\n");
1607 //printf("ADDING 1\n");
1608 // cache = addtocache(cache,line,-1,fdo);
1611 //printf("ADDING 2\n");
1612 cache
= addtocache(cache
,NULL
,0,fdo
);
1616 * No function begins in this line.
1617 * So let's collect it unless it is
1618 * a comment ot starts with a '#'.
1620 substr
= skipstr(line
, ' ',1);
1622 if ('#' == substr
[0] ||
1623 NULL
!= strstr(line
,"//") ) {
1624 cache
= addtocache(cache
,line
,-1,fdo
);
1625 cache
= addtocache(cache
,NULL
,0,fdo
);
1626 //printf("cache: %p\n",cache);
1627 //fprintf(fdo,"%s\n",line);
1629 cache
= addtocache(cache
,line
,-1,fdo
);
1632 depth
-= countchars(line
,'}');
1634 depth
+= countchars(line
,'{');
1635 depth
-= countchars(line
,'}');
1636 fprintf(fdo
,"%s\n",line
);
1644 FILE * create_definesfile(char * filename
)
1646 FILE * fdo
= fopen(filename
, "r");
1649 * If file existed position at end.
1653 fdo
= fopen(filename
, "a+");
1658 * File does not exist, so start it, if possible.
1660 fdo
= fopen(filename
, "w");
1662 fprintf(fdo
, "#include <aros/libcall.h>\n"
1663 "#include <exec/types.h>\n\n");
1671 * Generate AROS source code for a library from the description
1672 * in a pragmas file.
1674 int genarossource(int argc
, char **argv
)
1678 FILE *fdefines
= NULL
;
1680 char * sourcefile
, * destfile
;
1683 struct pragma_description
* pd
;
1687 fprintf(stderr
,"Usage: %s <source pragma file> <source c file> <dest c file> <output defines file>\n", argv
[0]);
1691 if(!(lc
= parse_libconf(NULL
)) )
1695 filename
= malloc( (strlen(argv
[1])+strlen(lc
->libname
)+20) * sizeof(char) );
1696 sprintf( filename
, "%s", argv
[1]);
1698 sourcefile
= argv
[2];
1700 definesfile
= argv
[4];
1702 pd
= parse_pragmas(filename
);
1705 fprintf(stderr
, "Could not read in the pragmas!\n");
1710 * Now open and parse the C input file and generate an output.
1712 fdi
= fopen(sourcefile
, "r");
1713 fdo
= fopen(destfile
, "w");
1714 fdefines
= create_definesfile(definesfile
);
1716 if (NULL
!= fdi
&& NULL
!= fdo
&& NULL
!= fdefines
)
1717 rewritecfile(fdi
,fdo
,pd
,lc
,fdefines
);
1723 if (NULL
!= fdefines
)
1726 free_pragma_description(pd
);
1734 int main(int argc
, char **argv
)
1741 fprintf( stderr
, "Usage: %s [-h|-t|-c|-R] <parameter>\n", argv
[0] );
1742 fprintf( stderr
, " -h help\n -t genfunctable\n -c genlibdefs\n -R genarossource\n" );
1746 if( argv
[1][0] == '-' )
1749 option
= argv
[1][1];
1750 argv
[1] = malloc( (strlen(argv
[0])+4) * sizeof(char) );
1751 sprintf( argv
[1], "%s -%c", argv
[0], option
);
1755 retval
= genarossource(argc
, &argv
[1]);
1758 retval
= genfunctable( argc
, &argv
[1] );
1761 retval
= genlibdefs( argc
, &argv
[1] );
1765 fprintf( stdout
, "Usage: %s [-h|-t|-c|-R] <parameter>\n", argv
[0] );
1766 fprintf( stdout
, " -h help\n -t genfunctable\n -c genlibdefs\n -R genarossource\n" );