#!../../perl ## ## test.syms -- test for function/variable symbols ## ## Copyright (c) 1994-2000 William Setzer ## ## You may distribute under the terms of either the Artistic License ## or the GNU General Public License, as specified in the README file. ## ## This program is modelled after parts of the dist-3.0 distribution. ## In many cases I just hand-converted the sh script to perl, so this ## program probably falls under the Artistic license. At the very least, ## it has the "look and feel". Will I be sued? :-) ## ## Thanks to Raphael Manfredi and the other contributors of dist-3.0. ## ## VMS patches thanks to Peter Prymmer my $verbose; my $panels; my $menus; my $forms; open IN, "list.syms" or die "Can't open list.syms: $!\n"; open(OUTH, ">CursesDef.h") or die "Can't open CursesDef.h: $!\n"; open LOG, ">&STDERR" or die "Can't redirect to STDERR: $!\n"; while (@ARGV) { my $arg = shift; $arg eq 'PANELS' and ++$panels and next; $arg eq 'MENUS' and ++$menus and next; $arg eq 'FORMS' and ++$forms and next; $arg =~ /^-h/ and Usage(); $arg =~ /^-v/ and ++$verbose and next; $arg =~ /^-l/ and do { my $logfile = shift or Usage("<-l> needs a filename"); open LOG, ">$logfile" or die "Can't open file '$logfile': $!\n"; open STDERR, ">&LOG" or die "Can't redirect STDERR: $!\n"; next; }; $arg =~ /^-/ and Usage("Unknown option: $_"); Usage("Unknown argument: $_"); } if (@ARGV) { Usage() } select LOG; $| = 1; # Prep compile stage # # Get a compile command so we can test for curses symbols. # (There has got to be an easier way. Blech.) # my $compile = "{CC} {DEFS} {INCS} {CFLAGS} {FILE} {LFLAGS} {LIBS} {NULL}"; my $makefile = ($^O =~ /VMS/) ? "Descrip.MMS" : "Makefile"; open MF, $makefile or die "Can't open $makefile: $!\n"; while () { if (/^CC\s*=\s*(.*)/) { my $A = $1; $compile =~ s/{CC}/$A/ } elsif (/^INC\s*=\s*(.*)/) { my $A = $1; $compile =~ s/{INCS}/$A/ } elsif (/^CCFLAGS\s*=\s*(.*)/) { my $A = $1; $compile =~ s/{CFLAGS}/$A/ } elsif (/^LDLOADLIBS\s*=\s*(.*)/) { my $A = $1; $compile =~ s/{LIBS}/$A/ } elsif (/^LDDLFLAGS\s*=\s*(.*)/) { ## Only get -L's. Other options can cause strange link behavior. ## (I shoulda stayed in bed.) # my $A = $1; my $B; while ($A =~ m!(-L\S+)!g) { $B .= " $1"; } $compile =~ s/{LFLAGS}/$B/; } } close MF; # Left to handle: DEFS/FILE/NULL # DEFS => "cc" define of "SYM" to "_C_SYM_" # FILE => "cc" compile of file _C_FILE_.c into executable _C_FILE_ # NULL => output of system call to dev null # # _C_SYM_ and _C_FILE_ will be filled in later if ($^O =~ /VMS/i) { $compile =~ s!{DEFS}!/DEFINE=SYM="_C_SYM_"!; $compile =~ s!{FILE}!_C_FILE_.c!; # no non-verbose way } elsif ($^O eq 'MSWin32') { $compile =~ s!{DEFS}!-DSYM="_C_SYM_"!; $compile =~ s!{FILE}!_C_FILE_.c!; $compile =~ s!{NULL}!>nul 2>&1! unless $verbose; } else { $compile =~ s!{DEFS}!-DSYM="_C_SYM_"!; $compile =~ s!{FILE}!-o _C_FILE_ _C_FILE_.c!; $compile =~ s!{NULL}!>/dev/null 2>&1! unless $verbose; } $compile =~ s!{NULL}!!; # print STDOUT "compile: $compile\n"; if ($compile =~ /{/) { die "OOPS: internal error getting compile command: $compile\n"; } ### ## Now gererate the .h file # print OUTH <<'EOHDR'; /* This file is automatically generated; changes will be lost. ** ** If you need to edit this file because "test.syms" didn't do a good ** job, be sure and save a copy of your changes. ** ** The "define"s below are simply educated guesses. If you are ** having problems compiling, check the appropriate symbol to see if ** it was set correctly: For each line, if the answer to the question ** is "no", that line should start with "#undef"; if the answer is ** yes, it should start with "#define". */ EOHDR print OUTH $panels ? "#define " : "#undef ", "C_PANELSUPPORT /* Add in panel library support? */", "\n\n"; print OUTH $menus ? "#define " : "#undef ", "C_MENUSUPPORT /* Add in menu library support? */", "\n\n"; print OUTH $forms ? "#define " : "#undef ", "C_FORMSUPPORT /* Add in form library support? */", "\n\n"; # Some functions return either int or void, depending on what compiler # and libcurses.a you are using. For the int/void test, if the # compiler doesn't complain about assigning the sym to an int # variable, we assume the function returns int. Otherwise, we assume # it returns void. my %tstfile = qw( E testsym I testint V testsym T testtyp); while () { next if /^\S*#/; next unless /\S/; my ($action, $sym, $args) = /^([A-Z])\s+(\w+)\s*(\(.*\))?/; my $file = $tstfile{$action}; my $cmd = $compile; unless (defined $sym and defined $file) { warn "WARNING: internal error on symbol $_\n"; } $cmd =~ s/_C_SYM_/"$sym$args"/ge; $cmd =~ s/_C_FILE_/$file/g; print LOG $cmd, "\n" if $verbose; my $ret = `$cmd`; my $rc = $?; print LOG $ret if $verbose; print LOG "(rc = $rc)\n" if $verbose; my $ssym = $sym; $ssym =~ s/^w//; my $c_sym; my $comment; if ($action eq 'E') { print LOG "function '$sym' ", ($rc ? "NOT " : ""), "found\n"; $c_sym = uc "C_$ssym"; $comment = "Does function '$ssym' exist?"; } elsif ($action eq 'I') { print LOG "function '$sym' returns ", ($rc ? "void" : "int"), "\n"; $c_sym = uc "C_INT$ssym"; $comment = "Does function '$ssym' return 'int'?"; } elsif ($action eq 'V') { print LOG "variable '$sym' ", ($rc ? "NOT " : ""), "found\n"; $c_sym = uc "C_$ssym"; $comment = "Does variable '$ssym' exist?"; } elsif ($action eq 'T') { print LOG "typedef '$sym' ", ($rc ? "NOT " : ""), "found\n"; $c_sym = uc "C_TYP$ssym"; $comment = "Does typedef '$ssym' exist?"; } else { warn "WARNING: internal error on symbol $_\n"; } print OUTH $rc ? "#undef " : "#define ", $c_sym, " " x (24 - length $c_sym), "/* ", $comment, " " x (42 - length $comment), "*/\n"; } unlink "testsym"; unlink "testint"; unlink "testtyp"; 1 while unlink "testsym.obj"; # Possibly pointless VMSism 1 while unlink "testint.obj"; # Possibly pointless VMSism 1 while unlink "testtyp.obj"; # Possibly pointless VMSism close IN; close OUTH; close LOG; exit 0; ### ## Helper functions # sub Usage { print LOG @_, "\n"; print LOG < Create file and dump output into it. EOM } __END__