# # Create the export list for perl. # # Needed by WIN32 and OS/2 for creating perl.dll # and by AIX for creating libperl.a when -Dusershrplib is in effect. # # reads global.sym, pp.sym, perlvars.h, intrpvar.h, thrdvar.h, config.h # On OS/2 reads miniperl.map as well my $PLATFORM; my $CCTYPE; my %bincompat5005 = (Perl_call_argv => "perl_call_argv", Perl_call_method => "perl_call_method", Perl_call_pv => "perl_call_pv", Perl_call_sv => "perl_call_sv", Perl_get_av => "perl_get_av", Perl_get_cv => "perl_get_cv", Perl_get_hv => "perl_get_hv", Perl_get_sv => "perl_get_sv", Perl_init_i18nl10n => "perl_init_i18nl10n", Perl_init_i18nl14n => "perl_init_i18nl14n", Perl_new_collate => "perl_new_collate", Perl_new_ctype => "perl_new_ctype", Perl_new_numeric => "perl_new_numeric", Perl_require_pv => "perl_require_pv", Perl_safesyscalloc => "Perl_safecalloc", Perl_safesysfree => "Perl_safefree", Perl_safesysmalloc => "Perl_safemalloc", Perl_safesysrealloc => "Perl_saferealloc", Perl_set_numeric_local => "perl_set_numeric_local", Perl_set_numeric_standard => "perl_set_numeric_standard"); my $bincompat5005 = join("|", keys %bincompat5005); while (@ARGV) { my $flag = shift; $define{$1} = 1 if ($flag =~ /^-D(\w+)$/); $define{$1} = $2 if ($flag =~ /^-D(\w+)=(.+)$/); $CCTYPE = $1 if ($flag =~ /^CCTYPE=(\w+)$/); $PLATFORM = $1 if ($flag =~ /^PLATFORM=(\w+)$/); } my @PLATFORM = qw(aix win32 os2); my %PLATFORM; @PLATFORM{@PLATFORM} = (); defined $PLATFORM || die "PLATFORM undefined, must be one of: @PLATFORM\n"; exists $PLATFORM{$PLATFORM} || die "PLATFORM must be one of: @PLATFORM\n"; my $config_sh = "config.sh"; my $config_h = "config.h"; my $thrdvar_h = "thrdvar.h"; my $intrpvar_h = "intrpvar.h"; my $perlvars_h = "perlvars.h"; my $global_sym = "global.sym"; my $pp_sym = "pp.sym"; my $globvar_sym = "globvar.sym"; my $perlio_sym = "perlio.sym"; if ($PLATFORM eq 'aix') { # Nothing for now. } elsif ($PLATFORM eq 'win32') { $CCTYPE = "MSVC" unless defined $CCTYPE; foreach ($thrdvar_h, $intrpvar_h, $perlvars_h, $global_sym, $pp_sym, $globvar_sym) { s!^!..\\!; } } unless ($PLATFORM eq 'win32') { open(CFG,$config_sh) || die "Cannot open $config_sh: $!\n"; while () { if (/^(?:ccflags|optimize)='(.+)'$/) { $_ = $1; $define{$1} = 1 while /-D(\w+)/g; } if ($PLATFORM eq 'os2') { $CONFIG_ARGS = $1 if /^(?:config_args)='(.+)'$/; $ARCHNAME = $1 if /^(?:archname)='(.+)'$/; } } close(CFG); } open(CFG,$config_h) || die "Cannot open $config_h: $!\n"; while () { $define{$1} = 1 if /^\s*#\s*define\s+(MYMALLOC)\b/; $define{$1} = 1 if /^\s*#\s*define\s+(USE_THREADS)\b/; $define{$1} = 1 if /^\s*#\s*define\s+(USE_PERLIO)\b/; $define{$1} = 1 if /^\s*#\s*define\s+(MULTIPLICITY)\b/; $define{$1} = 1 if /^\s*#\s*define\s+(PERL_BINCOMPAT_5005)\b/; } close(CFG); if ($PLATFORM eq 'win32') { warn join(' ',keys %define)."\n"; if ($define{PERL_OBJECT}) { print "LIBRARY Perl56\n"; print "DESCRIPTION 'Perl interpreter'\n"; print "EXPORTS\n"; # output_symbol("perl_alloc"); output_symbol("perl_get_host_info"); output_symbol("perl_alloc_using"); # output_symbol("perl_construct"); # output_symbol("perl_destruct"); # output_symbol("perl_free"); # output_symbol("perl_parse"); # output_symbol("perl_run"); # output_symbol("RunPerl"); # exit(0); } else { if ($CCTYPE ne 'GCC') { print "LIBRARY Perl\n"; print "DESCRIPTION 'Perl interpreter, export autogenerated'\n"; } else { $define{'PERL_GLOBAL_STRUCT'} = 1; $define{'MULTIPLICITY'} = 1; } print "EXPORTS\n"; } } elsif ($PLATFORM eq 'os2') { ($v = $]) =~ s/(\d\.\d\d\d)(\d\d)$/$1_$2/; $v .= '-thread' if $ARCHNAME =~ /-thread/; #$sum = 0; #for (split //, $v) { # $sum = ($sum * 33) + ord; # $sum &= 0xffffff; #} #$sum += $sum >> 5; #$sum &= 0xffff; #$sum = printf '%X', $sum; ($dll = $define{PERL_DLL}) =~ s/\.dll$//i; # print STDERR "'$dll' <= '$define{PERL_DLL}'\n"; print <<"---EOP---"; LIBRARY '$dll' INITINSTANCE TERMINSTANCE DESCRIPTION '\@#perl5-porters\@perl.org:$v#\@ Perl interpreter, configured as $CONFIG_ARGS' STACKSIZE 32768 CODE LOADONCALL DATA LOADONCALL NONSHARED MULTIPLE EXPORTS ---EOP--- } elsif ($PLATFORM eq 'aix') { print "#!\n"; } my %skip; my %export; sub skip_symbols { my $list = shift; foreach my $symbol (@$list) { $skip{$symbol} = 1; } } sub emit_symbols { my $list = shift; foreach my $symbol (@$list) { my $skipsym = $symbol; # XXX hack if ($define{PERL_OBJECT}) { $skipsym =~ s/^Perl_[GIT](\w+)_ptr$/PL_$1/; } emit_symbol($symbol) unless exists $skip{$skipsym}; } } if ($PLATFORM eq 'win32') { skip_symbols [qw( PL_statusvalue_vms PL_archpat_auto PL_cryptseen PL_DBcv PL_generation PL_lastgotoprobe PL_linestart PL_modcount PL_pending_ident PL_sortcxix PL_sublex_info PL_timesbuf main Perl_ErrorNo Perl_GetVars Perl_do_exec3 Perl_do_ipcctl Perl_do_ipcget Perl_do_msgrcv Perl_do_msgsnd Perl_do_semop Perl_do_shmio Perl_dump_fds Perl_init_thread_intern Perl_my_bzero Perl_my_htonl Perl_my_ntohl Perl_my_swap Perl_my_chsize Perl_same_dirent Perl_setenv_getix Perl_unlnk Perl_watch Perl_safexcalloc Perl_safexmalloc Perl_safexfree Perl_safexrealloc Perl_my_memcmp Perl_my_memset PL_cshlen PL_cshname PL_opsave Perl_do_exec Perl_getenv_len Perl_my_pclose Perl_my_popen )]; } elsif ($PLATFORM eq 'aix') { skip_symbols([qw( Perl_dump_fds Perl_ErrorNo Perl_GetVars Perl_my_bcopy Perl_my_bzero Perl_my_chsize Perl_my_htonl Perl_my_memcmp Perl_my_memset Perl_my_ntohl Perl_my_swap Perl_safexcalloc Perl_safexfree Perl_safexmalloc Perl_safexrealloc Perl_same_dirent Perl_unlnk PL_cryptseen PL_opsave PL_statusvalue_vms PL_sys_intern )]); } if ($PLATFORM eq 'os2') { emit_symbols([qw( ctermid get_sysinfo Perl_OS2_init OS2_Perl_data dlopen dlsym dlerror my_tmpfile my_tmpnam my_flock malloc_mutex threads_mutex nthreads nthreads_cond os2_cond_wait os2_stat pthread_join pthread_create pthread_detach XS_Cwd_change_drive XS_Cwd_current_drive XS_Cwd_extLibpath XS_Cwd_extLibpath_set XS_Cwd_sys_abspath XS_Cwd_sys_chdir XS_Cwd_sys_cwd XS_Cwd_sys_is_absolute XS_Cwd_sys_is_relative XS_Cwd_sys_is_rooted XS_DynaLoader_mod2fname XS_File__Copy_syscopy Perl_Register_MQ Perl_Deregister_MQ Perl_Serve_Messages Perl_Process_Messages init_PMWIN_entries PMWIN_entries Perl_hab_GET )]); } if ($define{'PERL_OBJECT'}) { skip_symbols [qw( Perl_getenv_len Perl_my_popen Perl_my_pclose )]; } else { skip_symbols [qw( PL_Dir PL_Env PL_LIO PL_Mem PL_Proc PL_Sock PL_StdIO )]; } if ($define{'MYMALLOC'}) { emit_symbols [qw( Perl_dump_mstats Perl_malloc Perl_mfree Perl_realloc Perl_calloc)]; } else { skip_symbols [qw( Perl_dump_mstats Perl_malloc Perl_mfree Perl_realloc Perl_calloc Perl_malloced_size)]; } unless ($define{'USE_THREADS'}) { skip_symbols [qw( PL_thr_key PL_sv_mutex PL_strtab_mutex PL_svref_mutex PL_malloc_mutex PL_cred_mutex PL_eval_mutex PL_eval_cond PL_eval_owner PL_threads_mutex PL_nthreads PL_nthreads_cond PL_threadnum PL_threadsv_names PL_thrsv PL_vtbl_mutex Perl_getTHR Perl_setTHR Perl_condpair_magic Perl_new_struct_thread Perl_per_thread_magicals Perl_thread_create Perl_find_threadsv Perl_unlock_condpair Perl_magic_mutexfree )]; } unless ($define{'USE_ITHREADS'}) { skip_symbols [qw( PL_sv_table Perl_dirp_dup Perl_fp_dup Perl_gp_dup Perl_he_dup Perl_mg_dup Perl_re_dup Perl_sv_dup Perl_sys_intern_dup Perl_sv_table_fetch Perl_sv_table_new Perl_sv_table_split Perl_sv_table_store )]; } unless ($define{'USE_THREADS'} or $define{'PERL_IMPLICIT_CONTEXT'} or $define{'PERL_OBJECT'}) { skip_symbols [qw( Perl_croak_nocontext Perl_die_nocontext Perl_deb_nocontext Perl_form_nocontext Perl_mess_nocontext Perl_warn_nocontext Perl_warner_nocontext Perl_newSVpvf_nocontext Perl_sv_catpvf_nocontext Perl_sv_setpvf_nocontext Perl_sv_catpvf_mg_nocontext Perl_sv_setpvf_mg_nocontext )]; } unless ($define{'FAKE_THREADS'}) { skip_symbols [qw(PL_curthr)]; } sub readvar { my $file = shift; my $proc = shift || sub { "PL_$_[2]" }; open(VARS,$file) || die "Cannot open $file: $!\n"; my @syms; while () { # All symbols have a Perl_ prefix because that's what embed.h # sticks in front of them. push(@syms, &$proc($1,$2,$3)) if (/\bPERLVAR(A?I?C?)\(([IGT])(\w+)/); } close(VARS); return \@syms; } if ($define{'USE_THREADS'} || $define{'MULTIPLICITY'}) { my $thrd = readvar($thrdvar_h); skip_symbols $thrd; } if ($define{'MULTIPLICITY'}) { my $interp = readvar($intrpvar_h); skip_symbols $interp; } if ($define{'PERL_GLOBAL_STRUCT'}) { my $global = readvar($perlvars_h); skip_symbols $global; emit_symbol('Perl_GetVars'); emit_symbols [qw(PL_Vars PL_VarsPtr)] unless $CCTYPE eq 'GCC'; } unless ($define{'DEBUGGING'}) { skip_symbols [qw( Perl_deb Perl_deb_growlevel Perl_debop Perl_debprofdump Perl_debstack Perl_debstackptrs Perl_runops_debug Perl_sv_peek PL_block_type PL_watchaddr PL_watchok)]; } if ($PLATFORM eq 'win32' && $define{'HAVE_DES_FCRYPT'}) { emit_symbols [qw(win32_crypt)]; } # functions from *.sym files my @syms = ($global_sym, $pp_sym, $globvar_sym); if ($define{'USE_PERLIO'}) { push @syms, $perlio_sym; } for my $syms (@syms) { open (GLOBAL, "<$syms") || die "failed to open $syms: $!\n"; while () { next if (!/^[A-Za-z]/); # Functions have a Perl_ prefix # Variables have a PL_ prefix chomp($_); my $symbol = ($syms =~ /var\.sym$/i ? "PL_" : ""); $symbol .= $_; emit_symbol($symbol) unless exists $skip{$symbol}; } close(GLOBAL); } # variables if ($define{'PERL_OBJECT'}) { for my $f ($perlvars_h, $intrpvar_h, $thrdvar_h) { my $glob = readvar($f, sub { "Perl_" . $_[1] . $_[2] . "_ptr" }); emit_symbols $glob; } } else { unless ($define{'PERL_GLOBAL_STRUCT'}) { my $glob = readvar($perlvars_h); emit_symbols $glob; } unless ($define{'MULTIPLICITY'}) { my $glob = readvar($intrpvar_h); emit_symbols $glob; } unless ($define{'MULTIPLICITY'} || $define{'USE_THREADS'}) { my $glob = readvar($thrdvar_h); emit_symbols $glob; } } sub try_symbol { my $symbol = shift; return if $symbol !~ /^[A-Za-z]/; return if $symbol =~ /^\#/; $symbol =~s/\r//g; chomp($symbol); return if exists $skip{$symbol}; emit_symbol($symbol); } while () { try_symbol($_); } if ($PLATFORM eq 'win32') { foreach my $symbol (qw( boot_DynaLoader Perl_getTHR Perl_init_os_extras Perl_setTHR Perl_thread_create Perl_win32_init RunPerl GetPerlInterpreter SetPerlInterpreter win32_errno win32_environ win32_stdin win32_stdout win32_stderr win32_ferror win32_feof win32_strerror win32_fprintf win32_printf win32_vfprintf win32_vprintf win32_fread win32_fwrite win32_fopen win32_fdopen win32_freopen win32_fclose win32_fputs win32_fputc win32_ungetc win32_getc win32_fileno win32_clearerr win32_fflush win32_ftell win32_fseek win32_fgetpos win32_fsetpos win32_rewind win32_tmpfile win32_abort win32_fstat win32_stat win32_pipe win32_popen win32_pclose win32_rename win32_setmode win32_lseek win32_tell win32_dup win32_dup2 win32_open win32_close win32_eof win32_read win32_write win32_spawnvp win32_mkdir win32_rmdir win32_chdir win32_flock win32_execv win32_execvp win32_htons win32_ntohs win32_htonl win32_ntohl win32_inet_addr win32_inet_ntoa win32_socket win32_bind win32_listen win32_accept win32_connect win32_send win32_sendto win32_recv win32_recvfrom win32_shutdown win32_closesocket win32_ioctlsocket win32_setsockopt win32_getsockopt win32_getpeername win32_getsockname win32_gethostname win32_gethostbyname win32_gethostbyaddr win32_getprotobyname win32_getprotobynumber win32_getservbyname win32_getservbyport win32_select win32_endhostent win32_endnetent win32_endprotoent win32_endservent win32_getnetent win32_getnetbyname win32_getnetbyaddr win32_getprotoent win32_getservent win32_sethostent win32_setnetent win32_setprotoent win32_setservent win32_getenv win32_putenv win32_perror win32_setbuf win32_setvbuf win32_flushall win32_fcloseall win32_fgets win32_gets win32_fgetc win32_putc win32_puts win32_getchar win32_putchar win32_malloc win32_calloc win32_realloc win32_free win32_sleep win32_times win32_alarm win32_open_osfhandle win32_get_osfhandle win32_ioctl win32_utime win32_uname win32_wait win32_waitpid win32_kill win32_str_os_error win32_opendir win32_readdir win32_telldir win32_seekdir win32_rewinddir win32_closedir win32_longpath win32_os_id )) { try_symbol($symbol); } } elsif ($PLATFORM eq 'os2') { open MAP, 'miniperl.map' or die 'Cannot read miniperl.map'; /^\s*[\da-f:]+\s+(\w+)/i and $mapped{$1}++ foreach ; close MAP or die 'Cannot close miniperl.map'; @missing = grep { !exists $mapped{$_} and !exists $bincompat5005{$_} } keys %export; delete $export{$_} foreach @missing; } # Now all symbols should be defined because # next we are going to output them. foreach my $symbol (sort keys %export) { output_symbol($symbol); } sub emit_symbol { my $symbol = shift; chomp($symbol); $export{$symbol} = 1; } sub output_symbol { my $symbol = shift; $symbol = $bincompat5005{$symbol} if $define{PERL_BINCOMPAT_5005} and $symbol =~ /^($bincompat5005)$/; if ($PLATFORM eq 'win32') { $symbol = "_$symbol" if $CCTYPE eq 'BORLAND'; print "\t$symbol\n"; # XXX: binary compatibility between compilers is an exercise # in frustration :-( # if ($CCTYPE eq "BORLAND") { # # workaround Borland quirk by exporting both the straight # # name and a name with leading underscore. Note the # # alias *must* come after the symbol itself, if both # # are to be exported. (Linker bug?) # print "\t_$symbol\n"; # print "\t$symbol = _$symbol\n"; # } # elsif ($CCTYPE eq 'GCC') { # # Symbols have leading _ whole process is $%@"% slow # # so skip aliases for now # nprint "\t$symbol\n"; # } # else { # # for binary coexistence, export both the symbol and # # alias with leading underscore # print "\t$symbol\n"; # print "\t_$symbol = $symbol\n"; # } } elsif ($PLATFORM eq 'os2') { print qq( "$symbol"\n); } elsif ($PLATFORM eq 'aix') { print "$symbol\n"; } } 1; __DATA__ # extra globals not included above. perl_alloc perl_construct perl_destruct perl_free perl_parse perl_run