1################################################################################ 2# 3# mkppport_fnc.pl -- generate ppport.fnc 4# 5# This program should be run when regenerating the data for ppport.h 6# (devel/regenerate). It should be run after parts/embed.fnc is updated, and 7# after mkapidoc.pl has been run. 8# 9# Its purpose is to generate ppport.fnc, a file which has the same syntax as 10# embed.fnc and apidoc.fnc, but contains entries that should only be tested 11# when ppport.h is enabled during the test. 12# 13# Thus it includes items that are Devel::PPPort only, and items that it 14# figures out aren't tested by the other two functions. 15# 16# These otherwise-untested items are those: 17# 1) for which D:P provides and are not found in embed.fnc nor apidoc.fnc, 18# or aren't listed as public API in those files 19# 2) and for which tests can be automatically generated that they at least 20# compile. 21# 22# The reason that an item isn't in those two files is that it is an 23# undocumented macro. (If it's not a macro, it has to be in embed.fnc, and if 24# it's documented, mkapidoc.pl would find it and place it in apidoc.fnc.) 25# 26# And, the reason we can't generate tests for undocumented macros is we don't 27# readily know the types of the parameters, which we need to get a C program 28# to compile. We could easily discover the number of parameters, but gleaning 29# their types is harder. 30# 31# Instead of expending effort to cope with undocumented items, document them 32# instead, improving the product doubly. 33# 34# However, if the macro has no parameters, there are no types to need to know. 35# And, it turns out, that it may be that many of these macros (which typically 36# just define constants) really don't need to be documented. They may be 37# something that is considered to be provided, but should actually have been 38# internal constants, not exposed to the outside world. And they're a lot of 39# them. So this function was written to handle them. 40# 41# Algorithms could be devised to read the =xsubs sections and associate code 42# found therein with the item, and to include the code as the test for the 43# item, but again, it would be better to just document them. 44# 45# scanprov, run as part of regeneration, will find when all functions, API or 46# not, became defined; but not macros. 47################################################################################ 48# 49# This program is free software; you can redistribute it and/or 50# modify it under the same terms as Perl itself. 51# 52################################################################################ 53 54use strict; 55use warnings; 56use re '/aa'; 57 58my $main_dir = $0; 59my $source_dir = $ARGV[0]; 60die "Need base directory as argument" unless -e $source_dir; 61 62# Up one level 63$main_dir =~ s;[^/]*$;;; 64$main_dir =~ s;/$;;; 65 66# Up a second level 67$main_dir =~ s;[^/]*$;;; 68$main_dir =~ s;/$;;; 69 70$main_dir = '.' unless $main_dir; 71require "$main_dir/parts/ppptools.pl"; 72 73 74my @provided = map { /^(\w+)/ ? $1 : () } `$^X ppport.h --list-provided`; 75die "Nothing provided" unless @provided; 76 77my $api_fnc = "$main_dir/parts/apidoc.fnc"; 78my $embed_fnc = "$main_dir/parts/embed.fnc"; 79 80# One of the outputs is a known element provided only by us. 81my @out = 'Am|void|sv_magic_portable|NN SV* sv|NULLOK SV* obj|int how|NULLOK const char* name|I32 namlen'; 82 83# First, get the known elements 84my @embeds = parse_embed($api_fnc, $embed_fnc); 85 86# Look for %include lines in the ppport.h generator 87my $PPPort = "$main_dir/PPPort_pm.PL"; 88open F, "<", $PPPort or die "Can't open $PPPort: $!"; 89 90# Now find all the elements furnished by us whose signatures we don't know 91# (hence not in embed.fnc nor apidoc.fnc) and have no parameters. 92my @no_parameters; 93while (<F>) { 94 next unless/^%include (\w+)/; 95 my @implementation = split /\n/, 96 parse_partspec("$main_dir/parts/inc/$1")->{'implementation'}; 97 while (defined (my $line = shift @implementation)) { 98 my $var; 99 if ($line =~ /^ \s* __UNDEFINED__ \s+ (\w+) \s /x) { 100 $var = $1; 101 } 102 elsif ($line =~ /^ \s* __NEED_VAR__ \s+ (\w+) \s+ (\w+) /x) { 103 $var = $2; 104 } 105 elsif ($line =~ / ^ \# \s* define \s+ ( \w+ ) \s /x) { 106 $var = $1; 107 } 108 109 next unless defined $var; 110 next if $var =~ / ^ D_PPP_ /x; # Skip internal only 111 next if grep { $1 eq $_->{'name'} } @embeds; # Skip known elements 112 next if grep { $1 eq $_ } @no_parameters; # Skip if already have it 113 push @no_parameters, $var; 114 } 115} 116 117push @out, map { "AmnT|void|$_" } @no_parameters; 118 119@out = sort sort_api_lines @out; 120 121my $out = "parts/ppport.fnc"; 122open OUT, ">", $out or die "Could open '$out' for writing: $!"; 123 124print OUT <<EOF; 125:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 126: 127: !!!! Do NOT edit this file directly! -- Edit devel/mkppport_fnc.pl instead. !!!! 128: 129: Perl/Pollution/Portability 130: 131:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 132: 133: Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz. 134: Version 2.x, Copyright (C) 2001, Paul Marquess. 135: Version 1.x, Copyright (C) 1999, Kenneth Albanowski. 136: 137: This program is free software; you can redistribute it and/or 138: modify it under the same terms as Perl itself. 139: 140:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 141: 142: This file lists all functions/macros that are provided by Devel::PPPort that 143: would not be tested otherwise; because either they are not public, or they 144: exist only in D:P. It is in the same format as the F<embed.fnc> that ships 145: with the Perl source code. 146: 147: Since these are used only to provide the argument types, it's ok to have the 148: return value be void for some where it's a potential issue. 149 150EOF 151 152print OUT map { "$_\n" } sort sort_api_lines @out; 153print OUT "\n"; 154print "$out regenerated\n"; 155 156close OUT; 157