t000755001750001750 013605534015 12152 5ustar00ingyingy000000000000Inline-0.86file100644001750001750 11213605534015 13126 0ustar00ingyingy000000000000Inline-0.86/t# Inline Foo file foo-sub test1 { foo-return $_[0] foo-eq 'test1'; } Inline-0.86000755001750001750 013605534015 11766 5ustar00ingyingy000000000000README100644001750001750 12641013605534015 12773 0ustar00ingyingy000000000000Inline-0.86NAME Inline - Write Perl Subroutines in Other Programming Languages VERSION This document describes Inline version 0.86. SYNOPSIS use Inline C; print "9 + 16 = ", add(9, 16), "\n"; print "9 - 16 = ", subtract(9, 16), "\n"; __END__ __C__ int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; } DESCRIPTION The Inline module allows you to put source code from other programming languages directly "inline" in a Perl script or module. The code is automatically compiled as needed, and then loaded for immediate access from Perl. Inline saves you from the hassle of having to write and compile your own glue code using facilities like XS or SWIG. Simply type the code where you want it and run your Perl as normal. All the hairy details are handled for you. The compilation and installation of your code chunks all happen transparently; all you will notice is the delay of compilation on the first run. The Inline code only gets compiled the first time you run it (or whenever it is modified) so you only take the performance hit once. Code that is Inlined into distributed modules (like on the CPAN) will get compiled when the module is installed, so the end user will never notice the compilation time. Best of all, it works the same on both Unix and Microsoft Windows. See "Inline- Support" for support information. Why Inline? Do you want to know "Why would I use other languages in Perl?" or "Why should I use Inline to do it?"? I'll try to answer both. Why would I use other languages in Perl? The most obvious reason is performance. For an interpreted language, Perl is very fast. Many people will say "Anything Perl can do, C can do faster". (They never mention the development time :-) Anyway, you may be able to remove a bottleneck in your Perl code by using another language, without having to write the entire program in that language. This keeps your overall development time down, because you're using Perl for all of the non-critical code. Another reason is to access functionality from existing API-s that use the language. Some of this code may only be available in binary form. But by creating small subroutines in the native language, you can "glue" existing libraries to your Perl. As a user of the CPAN, you know that code reuse is a good thing. So why throw away those Fortran libraries just yet? If you are using Inline with the C language, then you can access the full internals of Perl itself. This opens up the floodgates to both extreme power and peril. Maybe the best reason is "Because you want to!". Diversity keeps the world interesting. TMTOWTDI! Why should I use Inline to do it? There are already two major facilities for extending Perl with C. They are XS and SWIG. Both are similar in their capabilities, at least as far as Perl is concerned. And both of them are quite difficult to learn compared to Inline. There is a big fat learning curve involved with setting up and using the XS environment. You need to get quite intimate with the following docs: * perlxs * perlxstut * perlapi * perlguts * perlmod * h2xs * xsubpp * ExtUtils::MakeMaker With Inline you can be up and running in minutes. There is a C Cookbook with lots of short but complete programs that you can extend to your real-life problems. No need to learn about the complicated build process going on in the background. You don't even need to compile the code yourself. Inline takes care of every last detail except writing the C code. Perl programmers cannot be bothered with silly things like compiling. "Tweak, Run, Tweak, Run" is our way of life. Inline does all the dirty work for you. Another advantage of Inline is that you can use it directly in a script. You can even use it in a Perl one-liner. With XS and SWIG, you always set up an entirely separate module. Even if you only have one or two functions. Inline makes easy things easy, and hard things possible. Just like Perl. Finally, Inline supports several programming languages (not just C and C++). As of this writing, Inline has support for C, C++, Java, Python, Ruby, Tcl, Assembler, Basic, Guile, Befunge, Octave, Awk, BC, TT (Template Toolkit), WebChat and even PERL. New Inline Language Support Modules (ILSMs) are regularly being added. See Inline-API for details on how to create your own ILSM. USING THE INLINE.PM MODULE Inline is a little bit different than most of the Perl modules that you are used to. It doesn't import any functions into your namespace and it doesn't have any object oriented methods. Its entire interface (with two minor exceptions) is specified through the 'use Inline ...' command. This section will explain all of the different ways to use Inline. If you want to begin using C with Inline immediately, see Inline::C-Cookbook. The Basics The most basic form for using Inline is: use Inline X => "X source code"; where 'X' is one of the supported Inline programming languages. The second parameter identifies the source code that you want to bind to Perl. The source code can be specified using any of the following syntaxes: The DATA Keyword. use Inline Java => 'DATA'; # Perl code goes here ... __DATA__ __Java__ /* Java code goes here ... */ The easiest and most visually clean way to specify your source code in an Inline Perl program is to use the special DATA keyword. This tells Inline to look for a special marker in your DATA filehandle's input stream. In this example the special marker is __Java__, which is the programming language surrounded by double underscores. In case you've forgotten, the DATA pseudo file is comprised of all the text after the __END__ or __DATA__ section of your program. If you're working outside the main package, you'd best use the __DATA__ marker or else Inline will not find your code. Using this scheme keeps your Perl code at the top, and all the ugly Java stuff down below where it belongs. This is visually clean and makes for more maintainable code. An excellent side benefit is that you don't have to escape any characters like you might in a Perl string. The source code is verbatim. For these reasons, I prefer this method the most. The only problem with this style is that since Perl can't read the DATA filehandle until runtime, it obviously can't bind your functions until runtime. The net effect of this is that you can't use your Inline functions as barewords (without predeclaring them) because Perl has no idea they exist during compile time. The FILE and BELOW keywords. use Inline::Files; use Inline Java => 'file'; # Perl code goes here ... __JAVA__ /* Java code goes here ... */ This is the newest method of specifying your source code. It makes use of the Perl module Inline::Files written by Damian Conway. The basic style and meaning are the same as for the DATA keyword, but there are a few syntactic and semantic twists. First, you must say 'use Inline::Files' before you 'use Inline' code that needs those files. The special 'DATA' keyword is replaced by either 'file' or 'below'. This allows for the bad pun idiom of: use Inline C => 'below'; You can omit the __DATA__ tag now. Inline::Files is a source filter that will remove these sections from your program before Perl compiles it. They are then available for Inline to make use of. And since this can all be done at compile time, you don't have to worry about the caveats of the 'DATA' keyword. This module has a couple small gotchas. Since Inline::Files only recognizes file markers with capital letters, you must specify the capital form of your language name. Also, there is a startup time penalty for using a source code filter. At this point Inline::Files is alpha software and use of it is experimental. Inline's integration of this module is also fledgling at the time being. One of things I plan to do with Inline::Files is to get line number info so when an extension doesn't compile, the error messages will point to the correct source file and line number. My best advice is to use Inline::Files for testing (especially as support for it improves), but use DATA for production and distributed/CPAN code. Strings use Inline Java => <<'END'; /* Java code goes here ... */ END # Perl code goes here ... You also just specify the source code as a single string. A handy way to write the string is to use Perl's "here document" style of quoting. This is ok for small functions but can get unwieldy in the large. On the other hand, the string variant probably has the least startup penalty and all functions are bound at compile time. If you wish to put the string into a scalar variable, please be aware that the use statement is a compile time directive. As such, all the variables it uses must also be set at compile time, before the 'use Inline' statement. Here is one way to do it: my $code; BEGIN { $code = < $code; # Perl code goes here ... The bind() Function An alternative to using the BEGIN block method is to specify the source code at run time using the 'Inline->bind()' method. (This is one of the interface exceptions mentioned above) The bind() method takes the same arguments as 'use Inline ...'. my $code = <bind(Java => $code); You can think of bind() as a way to eval() code in other programming languages. Although bind() is a powerful feature, it is not recommended for use in Inline based modules. In fact, it won't work at all for installable modules. See instructions below for creating modules with Inline. Other Methods The source code for Inline can also be specified as an external filename, a reference to a subroutine that returns source code, or a reference to an array that contains lines of source code. (Note that if the external source file is in the current directory it must be specified with a leading '.' - ie '.file.ext' instead of simply 'file.ext'.) These methods are less frequently used but may be useful in some situations. For instance, to load your C++ code from a file named the same as your perl module with a swapped file extension, you can use: use Inline CPP => (__FILE__ =~ s/\.pm$/.cpp/r); Shorthand If you are using the 'DATA' or 'file' methods described above and there are no extra parameters, you can omit the keyword altogether. For example: use Inline 'Java'; # Perl code goes here ... __DATA__ __Java__ /* Java code goes here ... */ or use Inline::Files; use Inline 'Java'; # Perl code goes here ... __JAVA__ /* Java code goes here ... */ More about the DATA Section If you are writing a module, you can also use the DATA section for POD and AutoLoader subroutines. Just be sure to put them before the first Inline marker. If you install the helper module Inline::Filters, you can even use POD inside your Inline code. You just have to specify a filter to strip it out. You can also specify multiple Inline sections, possibly in different programming languages. Here is another example: # The module Foo.pm package Foo; use AutoLoader; use Inline C; use Inline C => DATA => filters => 'Strip_POD'; use Inline Python; 1; __DATA__ sub marine { # This is an autoloaded subroutine } =head1 External subroutines =cut __C__ /* First C section */ __C__ /* Second C section */ =head1 My C Function Some POD doc. =cut __Python__ """A Python Section""" An important thing to remember is that you need to have one use Inline Foo => 'DATA' for each __Foo__ marker, and they must be in the same order. This allows you to apply different configuration options to each section. Configuration Options Inline tries to do the right thing as often as possible. But sometimes you may need to override the default actions. This is easy to do. Simply list the Inline configuration options after the regular Inline parameters. All configuration options are specified as (key, value) pairs. use Inline (C => 'DATA', directory => './inline_dir', libs => '-lfoo', inc => '-I/foo/include', prefix => 'XXX_', warnings => 0, ); You can also specify the configuration options on a separate Inline call like this: use Inline (C => Config => directory => './inline_dir', libs => '-lfoo', inc => '-I/foo/include', prefix => 'XXX_', warnings => 0, ); use Inline C => <<'END_OF_C_CODE'; The special keyword 'Config' tells Inline that this is a configuration-only call. No source code will be compiled or bound to Perl. If you want to specify global configuration options that don't apply to a particular language, just leave the language out of the call. Like this: use Inline Config => warnings => 0; The Config options are inherited and additive. You can use as many Config calls as you want. And you can apply different options to different code sections. When a source code section is passed in, Inline will apply whichever options have been specified up to that point. Here is a complex configuration example: use Inline (Config => directory => './inline_dir', ); use Inline (C => Config => libs => '-lglobal', ); use Inline (C => 'DATA', # First C Section libs => ['-llocal1', '-llocal2'], ); use Inline (Config => warnings => 0, ); use Inline (Python => 'DATA', # First Python Section libs => '-lmypython1', ); use Inline (C => 'DATA', # Second C Section libs => [undef, '-llocal3'], ); The first Config applies to all subsequent calls. The second Config applies to all subsequent C sections (but not Python sections). In the first C section, the external libraries global, local1 and local2 are used. (Most options allow either string or array ref forms, and do the right thing.) The Python section does not use the global library, but does use the same DIRECTORY, and has warnings turned off. The second C section only uses the local3 library. That's because a value of undef resets the additive behavior. The directory and warnings options are generic Inline options. All other options are language specific. To find out what the C options do, see Inline::C. On and Off If a particular config option has value options of 1 and 0, you can use the 'enable' and 'disable' modifiers. In other words, this: use Inline Config => force_build => 1, clean_after_build => 0; could be reworded as: use Inline Config => enable => force_build => disable => clean_after_build; Playing 'with' Others Inline has a special configuration syntax that tells it to get more configuration options from other Perl modules. Here is an example: use Inline with => 'Event'; This tells Inline to load the module Event.pm and ask it for configuration information. Since Event has a C API of its own, it can pass Inline all of the information it needs to be able to use Event C callbacks seamlessly. That means that you don't need to specify the typemaps, shared libraries, include files and other information required to get this to work. You can specify a single module or a list of them. Like: use Inline with => qw(Event Foo Bar); Currently, modules that works with Inline include Event, PDL, and those that use Alien::Build. In order to make your module work with Inline in this way, your module needs to provide a class method called Inline that takes an Inline language as a parameter (e.g. "C"), and returns a reference to a hash with configuration information that is acceptable to the relevant ILSM. For C, see C Configuration Options. E.g.: my $confighashref = Event->Inline('C'); # only supports C in 1.21 # hashref contains keys INC, TYPEMAPS, MYEXTLIB, AUTO_INCLUDE, BOOT If your module uses ExtUtils::Depends version 0.400 or higher, your module only needs this: package Module; use autouse Module::Install::Files => qw(Inline); Inline Shortcuts Inline lets you set many configuration options from the command line. These options are called 'shortcuts'. They can be very handy, especially when you only want to set the options temporarily, for say, debugging. For instance, to get some general information about your Inline code in the script Foo.pl, use the command: perl -MInline=info Foo.pl If you want to force your code to compile, even if its already done, use: perl -MInline=force Foo.pl If you want to do both, use: perl -MInline=info -MInline=force Foo.pl or better yet: perl -MInline=info,force Foo.pl The Inline 'directory' Inline needs a place to build your code and to install the results of the build. It uses a single directory named '.Inline/' under normal circumstances. If you create this directory in your home directory, the current directory or in the directory where your program resides, Inline will find and use it. You can also specify it in the environment variable PERL_INLINE_DIRECTORY or directly in your program, by using the directory keyword option. If Inline cannot find the directory in any of these places it will create a '_Inline/' directory in either your current directory or the directory where your script resides. One of the key factors to using Inline successfully, is understanding this directory. When developing code it is usually best to create this directory (or let Inline do it) in your current directory. Remember that there is nothing sacred about this directory except that it holds your compiled code. Feel free to delete it at any time. Inline will simply start from scratch and recompile your code on the next run. If you have several programs that you want to force to recompile, just delete your '.Inline/' directory. It is probably best to have a separate '.Inline/' directory for each project that you are working on. You may want to keep stable code in the <.Inline/> in your home directory. On multi-user systems, each user should have their own '.Inline/' directories. It could be a security risk to put the directory in a shared place like /tmp/. Debugging Inline Errors All programmers make mistakes. When you make a mistake with Inline, like writing bad C code, you'll get a big error report on your screen. This report tells you where to look to do the debugging. Some languages may also dump out the error messages generated from the build. When Inline needs to build something it creates a subdirectory under your DIRECTORY/build/ directory. This is where it writes all the components it needs to build your extension. Things like XS files, Makefiles and output log files. If everything goes OK, Inline will delete this subdirectory. If there is an error, Inline will leave the directory intact and print its location. The idea is that you are supposed to go into that directory and figure out what happened. Read the doc for your particular Inline Language Support Module for more information. The 'config' Registry File Inline keeps a cached file of all of the Inline Language Support Module's meta data in a file called config. This file can be found in your directory directory. If the file does not exist, Inline creates a new one. It will search your system for any module beginning with Inline::. It will then call that module's register() method to get useful information for future invocations. Whenever you add a new ILSM, you should delete this file so that Inline will auto-discover your newly installed language module. (This should no longer be necessary as of Inline-0.49.) CONFIGURATION OPTIONS This section lists all of the generic Inline configuration options. For language specific configuration, see the doc for that language. directory The directory config option is the directory that Inline uses to both build and install an extension. Normally Inline will search in a bunch of known places for a directory called '.Inline/'. Failing that, it will create a directory called '_Inline/' If you want to specify your own directory, use this configuration option. Note that you must create the directory directory yourself. Inline will not do it for you. name You can use this option to set the name of your Inline extension object module. For example: use Inline C => 'DATA', name => 'Foo::Bar'; would cause your C code to be compiled in to the object: lib/auto/Foo/Bar/Bar.so lib/auto/Foo/Bar/Bar.inl (The .inl component contains dependency information to make sure the source code is in sync with the executable) If you don't use name, Inline will pick a name for you based on your program name or package name. In this case, Inline will also enable the autoname option which mangles in a small piece of the MD5 fingerprint into your object name, to make it unique. autoname This option is enabled whenever the name parameter is not specified. To disable it say: use Inline C => 'DATA', disable => 'autoname'; autoname mangles in enough of the MD5 fingerprint to make your module name unique. Objects created with autoname will never get replaced. That also means they will never get cleaned up automatically. autoname is very useful for small throw away scripts. For more serious things, always use the name option. version Specifies the version number of the Inline extension object. It is used only for modules, and it must match the global variable $VERSION. Additionally, this option should used if (and only if) a module is being set up to be installed permanently into the Perl sitelib tree using Inline::MakeMaker (NOT used by Inline::Module). Inline will croak if you use it otherwise. The presence of the version parameter is the official way to let Inline know that your code is an installable/installed module. Inline will never generate an object in the temporary cache (_Inline/ directory) if version is set. It will also never try to recompile a module that was installed into someone's Perl site tree. So the basic rule is develop without version, and deliver with version. with with can also be used as a configuration option instead of using the special 'with' syntax. Do this if you want to use different sections of Inline code with different modules. (Probably a very rare usage) use Event; use Inline C => DATA => with => 'Event'; Modules specified using the config form of with will not be automatically required. You must use them yourself. using You can override modules that get used by ILSMs with the using option. This is typically used to override the default parser for Inline::C, but might be used by any ILSM for any purpose. use Inline config => using => '::Parser::RecDescent'; use Inline C => '...'; This would tell Inline::C to use Inline::C::Parser::RecDescent. global_load This option is for compiled languages only. It tells Inline to tell DynaLoader to load an object file in such a way that its symbols can be dynamically resolved by other object files. May not work on all platforms. See the global shortcut below. untaint You can use this option whenever you use Perl's -T switch, for taint checking. This option tells Inline to blindly untaint all tainted variables. (This is generally considered to be an appallingly insecure thing to do, and not to be recommended - but the option is there for you to use if you want. Please consider using something other than Inline for scripts that need taint checking.) It also turns on safemode by default. See the untaint shortcut below. You will see warnings about blindly untainting fields in both %ENV and Inline objects. If you want to silence these warnings, set the Config option no_untaint_warn => 1. There can be some problems untainting Inline scripts where older versions of Cwd, such as those that shipped with early versions of perl-5.8 (and earlier), are installed. Updating Cwd will probably solve these problems. safemode Perform extra safety checking, in an attempt to thwart malicious code. This option cannot guarantee security, but it does turn on all the currently implemented checks. (Currently, the only "currently implemented check" is to ensure that the directory option has also been used.) There is a slight startup penalty by using safemode. Also, using untaint automatically turns this option on. If you need your code to start faster under -T (taint) checking, you'll need to turn this option off manually. Only do this if you are not worried about security risks. See the unsafe shortcut below. force_build Makes Inline build (compile) the source code every time the program is run. The default is 0. See the force shortcut below. build_noisy Tells ILSMs that they should dump build messages to the terminal rather than be silent about all the build details. build_timers Tells ILSMs to print timing information about how long each build phase took. Usually requires Time::HiRes. clean_after_build Tells Inline to clean up the current build area if the build was successful. Sometimes you want to disable this for debugging. Default is 1. See the noclean shortcut below. clean_build_area Tells Inline to clean up the old build areas within the entire Inline directory. Default is 0. See the clean shortcut below. print_info Tells Inline to print various information about the source code. Default is 0. See the info shortcut below. print_version Tells Inline to print version info about itself. Default is 0. See the version shortcut below. reportbug Puts Inline into 'reportbug' mode, which is what you want if you desire to report a bug. rewrite_config_file Default is 0, but setting rewrite_config_file => 1 will mean that the existing configuration file in the Inline directory will be overwritten. (This is useful if the existing config file is not up to date as regards supported languages.) warnings This option tells Inline whether to print certain warnings. Default is 1. INLINE CONFIGURATION SHORTCUTS This is a list of all the shortcut configuration options currently available for Inline. Specify them from the command line when running Inline scripts. perl -MInline=noclean inline_script.pl or perl -MInline=info,force,noclean inline_script.pl You can specify multiple shortcuts separated by commas. They are not case sensitive. You can also specify shortcuts inside the Inline program like this: use Inline 'info', 'force', 'noclean'; NOTE: If a 'use Inline' statement is used to set shortcuts, it can not be used for additional purposes. clean Tells Inline to remove any build directories that may be lying around in your build area. Normally these directories get removed immediately after a successful build. Exceptions are when the build fails, or when you use the noclean or reportbug options. force Forces the code to be recompiled, even if everything is up to date. global Turns on the global_load option. info This is a very useful option when you want to know what's going on under the hood. It tells Inline to print helpful information to STDERR. Among the things that get printed is a list of which Inline functions were successfully bound to Perl. noclean Tells Inline to leave the build files after compiling. noisy Use the build_noisy option to print messages during a build. reportbug Puts Inline into reportbug mode, which does special processing when you want to report a bug. reportbug also automatically forces a build, and doesn't clean up afterwards. This is so that you can tar and mail the build directory to me. reportbug will print exact instructions on what to do. Please read and follow them carefully. NOTE: reportbug informs you to use the tar command. If your system does not have tar, please use the equivalent zip command. safe Turns safemode on. untaint will turn this on automatically. While this mode performs extra security checking, it does not guarantee safety. site_install This parameter used to be used for creating installable Inline modules. It has been removed from Inline altogether and replaced with a much simpler and more powerful mechanism, Inline::MakeMaker. See the section below on how to create modules with Inline. _testing Used internally by Ct09parser.t and Ct10callback.t(in the Inline::C test suite). Setting this option with Inline::C will mean that files named parser_id and void_test are created in the ./Inline_test directory, creating that directory if it doesn't already exist. The files (but not the ./Inline_test directory) are cleaned up by calling Inline::C::_testing_cleanup(). Also used by t/06rewrite_config.t to trigger a warning. timers Turn on build_timers to get extra diagnostic info about builds. unsafe Turns safemode off. Use this in combination with untaint for slightly faster startup time under -T. Only use this if you are sure the environment is safe. untaint Turn the untaint option on. Used with -T switch. In terms of secure practices, this is definitely not a recommended way of dealing with taint checking, but it's the only option currently available with Inline. Use it at your own risk. version Tells Inline to report its release version. WRITING MODULES WITH INLINE The current preferred way to author CPAN modules with Inline is to use Inline::Module (distributed separately). Inline ships with Inline::MakeMaker, which helps you set up a Makefile.PL that invokes Inline at install time to compile all the code before it gets installed, but the resulting module still depends on Inline and the language support module like Inline::C. In order to avoid this dependency, what you really want to do is convert your distribution to plain XS before uploading it to CPAN. Inline::Module fills that role, and also integrates well with more modern authoring tools. See Inline::Module for details on that approach, or continue reading below for the older Inline::MakeMaker technique. Let's say that you wanted to write a module called Math::Simple. Start by using the following command: h2xs -PAXn Math::Simple This will generate a bunch of files that form a skeleton of what you need for a distributable module. (Read the h2xs manpage to find out what the options do) Next, modify the Simple.pm file to look like this: package Math::Simple; $VERSION = '1.23'; use base 'Exporter'; @EXPORT_OK = qw(add subtract); use strict; use Inline C => 'DATA', version => '1.23', name => 'Math::Simple'; # The following Inline->init() call is optional - see below for more info. #Inline->init(); 1; __DATA__ =pod =cut __C__ int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; } The important things to note here are that you must specify a name and version parameter. The name must match your module's package name. The version parameter must match your module's $VERSION variable and they must be considered valid by version::parse. NOTE: These are Inline's sanity checks to make sure you know what you're doing before uploading your code to CPAN. They insure that once the module has been installed on someone's system, the module would not get automatically recompiled for any reason. This makes Inline based modules work in exactly the same manner as XS based ones. Finally, you need to modify the Makefile.PL. Simply change: use ExtUtils::MakeMaker; to use Inline::MakeMaker; And, in order that the module build work correctly in the cpan shell, add the following directive to the Makefile.PL's WriteMakefile(): CONFIGURE_REQUIRES => { 'Inline::MakeMaker' => 0.45, 'ExtUtils::MakeMaker' => 6.52, }, This CONFIGURE_REQUIRES directive ensures that the cpan shell will install Inline on the user's machine (if it's not already present) before building your Inline-based module. Specifying of "ExtUtils::MakeMaker => 6.52," is optional, and can be omitted if you like. It ensures only that some harmless warnings relating to the CONFIGURE_REQUIRES directive won't be emitted during the building of the module. It also means, of course, that ExtUtils::Makemaker will first be updated on the user's machine unless the user already has version 6.52 or later. If the "Inline->init();" is not done then, having installed Math::Simple, a warning that "One or more DATA sections were not processed by Inline" will appear when (and only when) Math::Simple is loaded by a "require call. It's a harmless warning - and if you're prepared to live with it, then there's no need to make the "Inline->init();" call. When the person installing Math::Simple does a "make", the generated Makefile will invoke Inline in such a way that the C code will be compiled and the executable code will be placed into the ./blib directory. Then when a "make install" is done, the module will be copied into the appropriate Perl sitelib directory (which is where an installed module should go). Now all you need to do is: perl Makefile.PL make dist That will generate the file Math-Simple-0.20.tar.gz which is a distributable package. (It will also generate some harmless warnings in relation to CONFIGURE_REQUIRES unless the version of your ExtUtils::MakeMaker is 6.52 or later.) That's all there is to it. IMPORTANT NOTE: Although the above steps will produce a workable module, you still have a few more responsibilities as a budding new CPAN author. You need to write lots of documentation and write lots of tests. Take a look at some of the better CPAN modules for ideas on creating a killer test harness. Actually, don't listen to me, go read these: * perldoc perlnewmod * http://www.cpan.org/modules/04pause.html * http://www.cpan.org/modules/00modlist.long.html HOW INLINE WORKS In reality, Inline just automates everything you would need to do if you were going to do it by hand (using XS, etc). Inline performs the following steps: * Receive the Source Code Inline gets the source code from your script or module with a statements like the following: use Inline C => "Source-Code"; or use Inline; bind Inline C => "Source-Code"; where C is the programming language of the source code, and Source- Code is a string, a file name, an array reference, or the special 'DATA' keyword. Since Inline is coded in a "use" statement, everything is done during Perl's compile time. If anything needs to be done that will affect the Source- Code, it needs to be done in a BEGIN block that is before the "use Inline ..." statement. If you really need to specify code to Inline at runtime, you can use the bind() method. Source code that is stowed in the 'DATA' section of your code, is read in by an INIT subroutine in Inline. That's because the DATA filehandle is not available at compile time. * Check if the Source Code has been Built Inline only needs to build the source code if it has not yet been built. It accomplishes this seemingly magical task in an extremely simple and straightforward manner. It runs the source text through the Digest::MD5 module to produce a 128-bit "fingerprint" which is virtually unique. The fingerprint along with a bunch of other contingency information is stored in a .inl file that sits next to your executable object. For instance, the C code from a script called example.pl might create these files: example_pl_3a9a.so example_pl_3a9a.inl If all the contingency information matches the values stored in the .inl file, then proceed to step 8. (No compilation is necessary) * Find a Place to Build and Install At this point Inline knows it needs to build the source code. The first thing to figure out is where to create the great big mess associated with compilation, and where to put the object when it's done. By default Inline will try to build and install under the first place that meets one of the following conditions: 1. The DIRECTORY= config option; if specified 2. The PERL_INLINE_DIRECTORY environment variable; if set 3. .Inline/ (in current directory); if exists and $PWD != $HOME 4. bin.Inline (in directory of your script); if exists 5. ~/.Inline/ - if exists 6. ./_Inline/ - if exists 7. bin/_Inline - if exists 8. Create ./_Inline/ - if possible 9. Create bin/_Inline/ - if possible Failing that, Inline will croak. This is rare and easily remedied by just making a directory that Inline will use. If the PERL_INSTALL_ROOT Environment Variable has been set, you will need to make special provision for that if the 'make install' phase of your Inline scripts are to succeed. If the module option is being compiled for permanent installation, then Inline will only use ./_Inline/ to build in, and the $Config{installsitearch} directory to install the executable in. This action is caused by Inline::MakeMaker, and is intended to be used in modules that are to be distributed on the CPAN, so that they get installed in the proper place. * Parse the Source for Semantic Cues Inline::C uses the module Parse::RecDescent to parse through your chunks of C source code and look for things that it can create run-time bindings to. In C it looks for all of the function definitions and breaks them down into names and data types. These elements are used to correctly bind the C function to a Perl subroutine. Other Inline languages like Python and Java actually use the python and javac modules to parse the Inline code. * Create the Build Environment Now Inline can take all of the gathered information and create an environment to build your source code into an executable. Without going into all the details, it just creates the appropriate directories, creates the appropriate source files including an XS file (for C) and a Makefile.PL. * Build the Code and Install the Executable The planets are in alignment. Now for the easy part. Inline just does what you would do to install a module. "`perl Makefile.PL && make && make test && make install>". If something goes awry, Inline will croak with a message indicating where to look for more info. * Tidy Up By default, Inline will remove all of the mess created by the build process, assuming that everything worked. If the build fails, Inline will leave everything intact, so that you can debug your errors. Setting the noclean shortcut option will also stop Inline from cleaning up. * DynaLoad the Executable For C (and C++), Inline uses the DynaLoader::bootstrap method to pull your external module into Perl space. Now you can call all of your external functions like Perl subroutines. Other languages like Python and Java, provide their own loaders. SEE ALSO For information about using Inline with C see Inline::C. For sample programs using Inline with C see Inline::C-Cookbook. For "Formerly Answered Questions" about Inline, see Inline-FAQ. For information on supported languages and platforms see Inline-Support. For information on writing your own Inline Language Support Module, see Inline-API. Inline's mailing list is inline@perl.org To subscribe, send email to inline-subscribe@perl.org BUGS AND DEFICIENCIES When reporting a bug, please do the following: * Put "use Inline 'reportbug';" at the top of your code, or use the command line option "perl -MInline=reportbug ...". * Run your code. * Follow the printed directions. AUTHOR Ingy döt Net Sisyphus fixed some bugs and is current co-maintainer. COPYRIGHT * Copyright 2000-2019. Ingy döt Net. * Copyright 2008, 2010-2014. Sisyphus. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html Changes100644001750001750 4647513605534015 13402 0ustar00ingyingy000000000000Inline-0.860.86 Wed Jan 8 21:19:58 PST 2020 - Fix various test problems 0.85 Mon Jan 6 07:33:52 PST 2020 - Fix a taint issue @mohawk2++ 0.84 Mon Jan 6 07:04:31 PST 2020 - https://github.com/ingydotnet/inline-pm/pull/75 Make correct PERL5LIB to pass on including -I flags @mohawk2++ 0.83 Sun 28 Apr 2019 11:30:37 AM CEST - Reference Inline::Module in docs related to installation (PR#68 @nrdvana++) - create_config_file: don't accidentally skip rest of directory scanning (PR#73 @eserte++) - Merge per-language config, not overwrite (PR#71 @mohawk++) 0.82 Sun 31 Mar 2019 04:10:24 PM CEST - Another fix for @INC PR#69 TINITA 0.81 Sun 03 Feb 2019 04:42:05 PM CET - Regular release, see developer releases 0.80_03 Fri 01 Feb 2019 11:26:18 PM CET - Fix @inc, add another exception for Inline::C (SISYPHUS++) 0.80_02 Fri Jun 22 22:21:11 MDT 2018 - Revert PR/61 - failed on travis 0.80_01 Fri Jun 22 21:39:49 MDT 2018 - PR/59 @pypt++ Travis test against Perl 5.22, 5.24, 5.26 - PR/60 @pypt++ Calculate MD5 hashes of UTF-8 source by encoding it first - PR/61 @rurban++ Fix wrong -I in subcmd - PR/66 @soren++ Fix failing tests on systems missing perldiag.pod - PR/67 NERDVANA++ Relax the version requirement for installing modules 0.80 Fri Mar 13 20:03:52 PDT 2015 - Fix dependency problem in Inline::MakeMaker affecting parallel builds 0.79 Tue Feb 17 16:16:55 PST 2015 - Windows fixes. Mithaldu++ 0.78 Tue Dec 2 15:21:30 EST 2014 - Move working code of Inline::import to Inline::import_heavy to support Inline::Module 0.77 Fri Sep 19 23:13:20 UTC 2014 - Allow new USING usages. - Updated the docs. 0.76 Tue Aug 19 16:43:41 PDT 2014 - Missed a TAB in previous release :\ 0.75 Tue Aug 19 16:18:15 PDT 2014 - Replace tabs with spaces. 0.74 Sat Aug 16 16:53:28 PDT 2014 - Change ' / ' to '/' in doc 0.73 Sat Aug 16 11:15:52 PDT 2014 - Meta 0.0.2 0.72 Sat Aug 16 01:37:38 PDT 2014 - Remove File::Basename from tests 0.71 Fri Aug 15 22:54:05 PDT 2014 - Add t/000-require-modules.t 0.70 Fri Aug 15 18:27:20 PDT 2014 - Add t/000-compile-modules.t 0.69 Fri Aug 15 20:54:27 BST 2014 - Restore deprecated "WriteInlineMakefile" for now. 0.68 Mon Aug 11 01:19:12 BST 2014 - Update "with" docs for EU::D 0.400. 0.67 Fri Aug 8 00:37:17 BST 2014 - Remove WriteInlineMakefile. - Make "use Inline" keywords case-insensitive. - Add a devel ILSM test for running before release 0.66 Fri Aug 1 00:43:36 BST 2014 - Change Inline::Config check to avoid false positives 0.65 Wed Jul 30 04:18:50 BST 2014 - Update docs and M14_usage_Config error message 0.64 Sat Jul 19 22:19:18 BST 2014 - Instrument "Inline::Config" error - Lock reading as well as writing of config file - Prevent adding non .pm modules to the Makefile 0.63 Thu Jul 17 07:51:46 PDT 2014 - Add mailing list info to Meta and Contributing 0.62 Sun Jul 13 21:49:16 PDT 2014 - Actually make the 5.8.1 change I said I did in 0.61 0.61 Sun Jul 13 21:47:14 PDT 2014 - Make Inline dep on perl 5.8.1 per The Lancaster Consensus - https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md#minimum-supported-perl - Fix Metadata errors 0.60 Sun Jul 13 21:19:48 PDT 2014 - Use the new ZD Contributing file 0.59 Sat Jul 12 12:11:10 PDT 2014 - Finish migrating and updating docs 0.58 Fri Jul 11 07:02:12 BST 2014 - Fix tabs, add $VERSIONs, fix prereqs 0.57 Fri Jul 11 02:05:00 BST 2014 - Inline::C separated from Inline 0.56_03 Thu Jul 10 13:36:04 BST 2014 - The "with" interface changed slightly - to get right $language use $_[-1]. - Add Contrib file 0.56_02 Thu Jul 10 03:36:04 BST 2014 - Remove AutoLoader stuff. 0.56_01 Wed Jul 9 17:10:04 PDT 2014 - Move to Zilla-Dist - Remove Inline::C from Inline dist 0.56 9 Jul 2014 - Clean up formatting and whitespace - Removed a "sleep" from Inline::Foo::build 0.55_05 8 Jul 2014 - Make "with" hook return undef croak, test that. 0.55_04 8 Jul 2014 - Suppress warnings in older perls from C/t/14void_arg_PRD.t. - setruid throws exception not just on Win32 - trap in t/08taint.t. - C/t/14void_arg_PRD.t - Fix typo. 0.55_03 1 Jul 2014 - Update ToDo to post 0.44(!) - repository cpan metadata added, typo fixes (thanks dsteinbrunner) - Update "with" hook to be class method, not function (and test). - Make "make dist" update C/C.pm and Inline::MakeMaker's $VERSION. - Undo change disabling BUILD_NOISY for Win32 when shell eq 'cmd' 0.55_02 date Sun 22 Jun 2014 - Version updated to 0.55_02 and released to CPAN - Inline.pm - additional changes to -T handling. (Thanks Ed J). 0.55_01 date Mon 5 May 2014 - Update version number to 0.55_01 0.55 date Mon 28 Apr 2014 - Version 0.55 released to CPAN 0.54_05 date Sun 13 Apr 2014 - Update version number to 0.54_05. - Inline.pod - Add documentation regarding "with" and modules. (Thanks to Ed J.) 0.54_04 date Wed 10 Apr 2014 - Add META.yml & META.json to distro - Released to CPAN. 0.54_03 date Wed 9 Apr 2014 - Released to CPAN. (No changes from 0.54_01.) 0.54_01 Mon 31 Mar 2014 - Update version nmuyber to 0.54_01 - Makefile.PL - add META_MERGE info (thanks David Steinbrunner). - Inline.pod - Correct typos (thanks David Steinbrunner). 0.54 Sat 29 Mar 2014 - Update version number to 0.54 - Release version 0.54 to CPAN 0.53_02 Fri 7 Mar 2014 - Update version to 0.53_02 0.53_01 Thurs 12 Sep 2013 - Inline.pm - Update version number to 0.53_01 0.53 Wed 1 May 2013 - Version 0.53 released to CPAN 0.52_02 Wed 24 Apr 2013 - Version 0.52_02 released to CPAN 0.52_01 Thurs 11 Apr 2013 - Version 0.52_01 released to CPAN - Inline.pm - in sub read_DATA() replace: @{$DATA{$pkg}} = split /(?m)(__\S+?__\n)/, $data with: @{$DATA{$pkg}} = split /(?m)^[ \t]{0,}(__\S+?__\n)/, $data; Otherwise some non-markers can be treated as markers. Thanks to Chris Nighswonger and Stefan Seifert. Added C/t/21read_DATA.t and C/t/22read_DATA_2.t as the test cases. NOTE: This is not a complete fix - it's still possible to write code (albeit in an unorthodox fashion) such that a non-marker can be treated as a marker. 0.52 Thurs 07 Mar 2013 - Version 0.52 released to CPAN 0.51_03 Wed 28 Nov 2012 - Version 0.51_03 released to CPAN 0.51_02 Tues 20 Nov 2012 - Version 0.51_02 released to CPAN 0.51_01 Tues 20 Nov 2012 - Version 0.51_01 released to CPAN 0.51 Sat 13 Oct 2012 - Version 0.51 released to CPAN. 0.50_03 Mon 8 Oct 2012 - Version 0.50_03 released to CPAN. 0.50_02 Tues 14 Feb 2012 - Inline.pm - Bump version number to 0.50_02 0.50_01 Wed 8 Feb 2012 - Inline.pm - Add a warning prior to croaking with M62_invalid_config_file(). That way, we'll at least see what $config contains. This is in response to FAIL report http://www.cpantesters.org/cpan/report/3287249c-5151-11e1-9dba-4238887bd19e - Bump version number to 0.50_01 0.50 Tues 7 Feb 2012 - Version 0.50 released to CPAN - Inline.pm - Bump version number to 0.50 0.49_02 Fri 3 Feb 2012 - Version 0.49_02 released to CPAN - Inline.pm - Bring version numbering into line with recommendations made in http://perldoc.perl.org/perlmodstyle.html#Version-numbering 0.49_01 Sun 25 Dec 2011 - As the result of input from David Oswald - Inline.pod - Changes relating to "CONFIGURE_REQUIRES" and fix typo reported in ticket 73108. - Inline-FAQ.pod - Changes relating to "CONFIGURE_REQUIRES" - Inline.pm - Bump version to 0.49_01 - lib/Inline/MakeMaker.pm - Bump version to 0.49_01 0.49 Thurs 8 Dec 2011 - Version 0.49 released to CPAN - Inline.pm - small alteration to M19_usage_language error message 0.48_02 Fri 9 Sept 2011 - Bump Inline version to 0.48_02 0.48_01 Mon 11 Apr 2011 - Version 0.48_01 released to CPAN - t/05files.t - Have t/05files.t provide a reason for skipping the tests. - Inline.pm - Create REWRITE_CONFIG_FILE config option. - Makefile.PL - Test::Warn 0.23 or later needed for perl-5.13 and later. (Older perls need 0.21 or later). 0.48 Mon 21 Feb 2011 - Version 0.48 released to CPAN. (No changes from 0.47_02.) 0.47_02 Tues 1 Feb 2011 - Version 0.47_02 released to CPAN. - Makefile.PL - Change the Test::Warn dependency from 0.22 to 0.21 and specify it in top-level Makefile.PL instead of in C/Makefile.PL. 0.47_01 Sun 30 January 2011 - Version 0.47_01 released to CPAN. Changes only to Inline::C test suite - see C/Changes. 0.47 Fri 21 January 2011 - Version 0.47 released to CPAN. No changes from 0.46_02 0.46_02 Wed 29 December 2010 - lib/Inline/MakeMaker.pm - apply patch from Raymond Mroz to accommodate the modern h2xs directory structure. Bump Inline::MakeMaker version to 0.45. 0.46_01 Sun 14 feb 2010 - Inline.pm - add archname and perlversion number to config filename. - C/C.pm - Second attempt at accommodating 'ccache cc' compiler (RT ticket 40140). 0.46 Fri Feb 12 2010 - Same as 0.45_02 (plus some minor doc alterations in Inline.pod). 0.45_02 Fri Feb 5 2010 - Changes to Inline.pm, denter.pm, and Inline.pod relating to "fixing" untainting (to the extent that untainting of -T inline scripts works as documented). Many thanks to Patrick LeBoutillier. - Also added C/t/08taint.t (which contains -T on the shebang line) as a basic test of untainting. (RT ticket 13084) 0.45_01 Thurs Jan 28 2010 - C/C.pod - document that *fully qualified* paths for LIBS, INC, TYPEMAPS and MYEXTLIB are needed. (RT ticket 5207) - Inline.pm - remove "defined" from "defined %main::Inline::Config::" as that usage causes a deprecation warning with perl-5.11 and later. (RT ticket 53227) - Inline.pm - fix sub push_overrides (RT ticket 49669) This change responsible for "Subroutine Inline::C::get_parser redefined" warnings that can occur during build stage under certain circumstances. - denter.pm - local()ise $_ (in four places) (RT ticket 16801) - Inline.pod - doc correction (thanks Alejandro Ochoa). - C/Makefile.PL - accommodate 'ccache cc' (RT ticket 40140) - accommodate ActivePerl-5.10.1 and later (RT ticket 49419) - C/Cookbook.pod - typo fixes (thanks Brad Barber) - Change "NAME" from "C Cookbook ..." to "Inline::C-Cookbook ...". (RT ticket 45417) 0.45 Sat Nov 22 2008 - No changes from 0.44_01 0.44_01 Tues Oct 11 2008 - Apply patch to Inline.pm that addresses a problem with whitespace occurring in the name of the build directory. (RT ticket 4150) - Fix ParseRegExp.pm. (RT ticket 6327) - Fix (in Inline.pm) problem regarding the calling of the same script from different builds of perl. (RT ticket 29326) - Allow Inline::install() subroutine to apply to languages other than C and CPP. (RT ticket 35517) - Fix C/Makefile.PL so that the C compiler can still be found when $Config{cc} reports something like /some/place/cc. (RT ticket 8251) - In C/C.pm, allow for the calling of multiple typemaps (RT ticket 5639), and have the "No Inline C functions bound to Perl" warning specify the file for which no bindings were found (RT ticket 17774). - Minor doc fixes. 0.44 Mon Oct 28 10:31:51 PST 2002 - Doc fixes. Thanks Mitchell. - Put all current ILSMs in doc and Makefile.PL - Applied some patches from Patrick LeBoutillier, including one to make things work out of the box on Win95 and friends. Rob helped too. - Added a warning to help debug why certain ILSMs might be failing. - Changes to Inline-FAQ - Fixed ParseRecDescent to handle 'unsigned foo()' and 'long foo()' - Updated README - Fixed %INC problem - Used File::Spec::Unix for %INC keys (which are always in Unix form) - Applied Mitchell's patch for Inline::C::ParseRegExp - Updated pod docs - Shortened BUILD_TIMER precision, per Leon Brocard's suggestion. - Applied Mitchell Charity's patch to fix Piers Harding's CPP problem. - Fixed bug with USING keyword - Added the USING keyword. This allows you to specify a list of modules which can override certain parts of the Inline process. - Added Inline::C::ParseRecDescent and Inline::C::ParseRegExp to provide two (hopefully) functionally identical C parsers. You use one of these by saying 'use Inline C => DATA => USING => "ParseRegExp"'. Big thanks to Mitchell Charity for ParseRegExp. It's over two orders of magnitude faster than ParseRecDescent. - Added the more diagnostics to BUILD_NOISY. - Added BUILD_TIMERS for benchmarking the Inline build process. - Applied a (BIG) patch to the Inline distribution to use File::Spec to manipulate all file paths. Thanks Mitchell Charity! - Fixed a bug in OS X. Inline::C was being required even if the object was cached. That's because Inline.pm wasn't checking for .bundle. - Added an option to Inline::C called BUILD_NOISY. Setting this to true will cause the build process to dump output to the screen instead of to a file. You can set it with 'BUILD_NOISY => 1,' or 'ENABLE => "BUILD_NOISY"'. - Honor the PERL_INLINE_BUILD_NOISY environment variable, to do the same as above. Environment variable has higher precedence. - Print the contents of 'out.make' to the screen on failure. This will happen when BUILD_NOISY is off. When its on, you'll see the messages in real time, but they won't go to 'out.make'. - Provide the NOISY shortcut so you can say 'perl -MInline=force,noisy foo.pl'. - Inline::MakeMaker uses the NOISY shortcut for its build command. This way module builds are noisy like they should be. - Integrated the new improved Inline::MakeMaker - WriteInlineMakefile is deprecated for WriteMakefile - Added a patch by Rafael Garcia-Suarez to use $^X when $Config::Config{perlpath} is wrong. (It happens) - Refactored the Parse::RecDescent grammar - Moved grammar module to Inline::C::recdescent - Support 'const' in types. Requested by Nicholas Clark - Other modifiers seemed to be busted. Like 'unsigned'. Got them working. - Started integrating Mitchell Charity's parser. Don't know how to turn it on yet. It's currently in Inline::C::charity - Allow C++ based modules to be installed as well as C ones. Requested by Piers Harding. - Call validate() for interpreted ILSMs even on load(). This patch is dedicated to the very patient Mark Fowler who waited almost a year for it. I hope that never happens again. 0.43 Sat Jul 21 14:58:46 PDT 2001 - Removed *old* deprecated functionality. - Inline now works with *all* Perl release versions 5.005 and above. - I was comparing a version number to a md5 hash. Oops. Thanks Marcel. - Changed M51 error message which was causing confusion. It would often come up in places I didn't anticipate. - Use $Config{dlext} instead of $Config{so}. Thanks Marcel. 0.42 Sun Jun 10 18:21:06 PDT 2001 - Re-fixed config generator path bug prevents ILSMs like I::Python and I::Tcl from installing. (NEILW) 0.41 Tue Jun 5 00:23:46 PDT 2001 - Don't install .inline or .inl files with Inline::MakeMaker. Require object name to be same as package name for installation. Put hack in INIT block to fix Sarathy's patch ;) - Fixed config generator path bug that would prevent other ILSMs from installing. Thanks Patrick. - Applied patch to (hopefully) handle CRLF variations properly. Thanks Binkley 0.40 Sun May 27 18:59:59 PDT 2001 - Bugfix. NAME not set right without AUTONAME. - TRIAL8 of Inline-0.40 Added option to distribute binary PPM modules with or without source. Got UNTAINT to work again. - TRIAL7 of Inline-0.40 Fixed path bus for MacOS. Thanks Marcel. 'with' works again (with Event) Inline::MakeMaker adds WriteMakefile dependency for Inline 0.40 - TRIAL6 of Inline-0.40 - Made Denter YAML compliant - Croak on usage of SITE_INSTALL - Update Inline.pod for 0.40 features - Detect and croak on old config files - TRIAL5 of Inline-0.40 - Added alpha support for Inline::Files - Made all internal path names canonical - Finished TRIAL1 version of Inline-0.40 - Short object names - Safer config generation - AUTONAME support - Reinstituted AutoLoading - Put all messages into subroutines inside Inline.pm - Completely reorganized the Inline internal object into major groups - API - Contract space for the ILSMs. Guaranteed backwards compatible after Inline 1.00. - ILSM - Private space for ILSMs - INLINE - Private Inline space. Subject to constant change. - CONFIG - Config options. Not for use by ILSMs - MATCH - Matching criteria for the object. - STRUCT - Reserved for Inline::Struct - Added command proxy logic for Inline::MakeMaker utilities INSTALL, MAKEDIST, MAKEPPD - Got _INSTALL_ option working with Inline::MakeMaker - Replaced Inline's use of Data::Dumper with Inline::Denter. This is a stripped down version of Data::Denter. This change makes Inline more secure because it doesn't need to eval() untrusted code. Also removes the dependency on Safe.pm which has known security flaws. Yay! 0.33 Sat Apr 28 20:20:29 PDT 2001 - Use 'require FindBin' instead of 'use FindBin' for mod_perl. - Fixed Win32 bug. Drive letter 'c:' can be lower case. - Changed 'make install' to 'make pure_install' - Fixed bug of assuminh ':' for PATH separator. (Windows bug) - Rearranged test harness. Removed dependency on C for tests. Invented Inline::Foo for testing. - Added ENABLE and DISABLE config modifiers. - Changed the way ILSMs are detected. 0.32 Mon Feb 26 07:44:34 PST 2001 - Add DIRECTORY path to applicable warnings and error msgs - Warn if UNTAINT && SAFEMODE && ! DIRECTORY (croak if root) - Added GLOBAL_LOAD option with GLOBAL shortcut. - Added SAFEMODE option. - Safe->reval(DIRECTORY/config) if SAFE. - Blindly untaint all %ENV variables for UNTAINT. - Fixed MSWin32 bug of getting full path parts in dll name. - Fixed the "cut & paste" bug. (DOS line endings in Unix.) - Fixed detection of using Inline::Config. - Added UNTAINT option, which lets you use Inline with Perl's -T flag. 0.31 Fri Jan 19 00:13:31 PST 2001 - Changed doc instances of 'C' to 'Inline'. - Reorganized the internal structure of the Inline DIRECTORY - Shortened install path to .Inline/lib/auto/... - Lengthened the build path to .Inline/build/... - Changed BLIB option to DIRECTORY - Changed default DIRECTORY from blib_I to _Inline or .Inline 0.30 Fri Dec 8 02:00:17 PST 2000 - Major reworking of Inline.pm - Sweeping changes to - Configuaration - Syntax - Language integration Too much to list here. See ToDo 0.26 Thu Sep 14 20:51:11 PDT 2000 - localize $/ and $\ to shield them from things like 'perl -l'. Thanks Michael Schwern. 0.25 Fri Sep 1 10:07:33 PDT 2000 - Use MD5 on unmodified code only. User must force recompile if auto_headers change. This would have caused existing installs to break. - Don't determine build path unless really needed, since a blib_I might be created. This might be annoying for someone who is only *using* an Inline extension module. - Mangle $VERSION into object name for modules - Support Inline->import(C=>); syntax - Return an empty list when the C function is of type void and doesn't use any stack manipulating macros. (ie dXSARGS) It used to return whatever was passed in on the stack. :-( - Force rebuild when SITE_INSTALL option is set. - Figured out what was actually causing the 0.23 AutoLoader bug. - Can't autoload from "./blib" (relative path) when chdir() has been used. Fixed properly now. Can AutoLoad fix_make() again. :-) 0.24 Fri Aug 18 03:03:06 PDT 2000 - Fixed Autoload bug found during "make test" of Inline installation. 0.23 Wed Aug 16 18:10:07 PDT 2000 - Added support for MSWin32 operating systems which use the Microsoft Visual C++ compiler. 0.22 Wed Aug 9 18:55:54 PDT 2000 - First alpha release to CPAN 0.01 Mon Jul 24 11:23:25 2000 - original version; created by h2xs 1.19 LICENSE100644001750001750 4366013605534015 13105 0ustar00ingyingy000000000000Inline-0.86This software is copyright (c) 2020 by Ingy döt Net. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2020 by Ingy döt Net. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2020 by Ingy döt Net. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End MANIFEST100644001750001750 235413605534015 13204 0ustar00ingyingy000000000000Inline-0.86# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.012. CONTRIBUTING Changes LICENSE MANIFEST META.json META.yml Makefile.PL README example/modules/Boo-2.01/MANIFEST example/modules/Boo-2.01/Makefile.PL example/modules/Boo-2.01/lib/Boo.pm example/modules/Boo-2.01/lib/Boo/Far.pm example/modules/Boo-2.01/lib/Boo/Far/Faz.pm example/modules/Boo-2.01/t/boo.t example/modules/Math-Simple-1.23/Changes example/modules/Math-Simple-1.23/MANIFEST example/modules/Math-Simple-1.23/Makefile.PL example/modules/Math-Simple-1.23/Simple.pm example/modules/Math-Simple-1.23/test.pl inc/bin/testml-cpan inc/lib/TestML/Boolean.pm inc/lib/TestML/Bridge.pm inc/lib/TestML/Run.pm inc/lib/TestML/Run/TAP.pm inc/lib/TestML/StdLib.pm inc/t/03errors.tml.lingy inc/t/09perl5lib.tml.lingy lib/Inline.pm lib/Inline.pod lib/Inline/API.pod lib/Inline/FAQ.pod lib/Inline/Foo.pm lib/Inline/MakeMaker.pm lib/Inline/MakeMaker/Changes lib/Inline/Support.pod lib/Inline/denter.pm t/000-require-modules.t t/01usages.t t/02config.t t/03errors.t t/04create.t t/05files.t t/06rewrite_config.p t/06rewrite_config.t t/07rewrite2_config.p t/07rewrite2_config.t t/08unicode.t t/09perl5lib.t t/TestInlineSetup.pm t/TestMLBridge.pm t/author-pod-syntax.t t/file xt/ilsm-test.bash META.yml100644001750001750 155513605534015 13326 0ustar00ingyingy000000000000Inline-0.86--- abstract: 'Write Perl Subroutines in Other Programming Languages' author: - 'Ingy döt Net ' build_requires: JSON::PP: '0' Test::More: '0.88' Test::Warn: '0.23' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Inline no_index: directory: - example - inc - t - xt requires: Digest::MD5: '0' File::Spec: '0.8' perl: v5.8.1 version: '0.82' resources: bugtracker: https://github.com/ingydotnet/inline-pm/issues homepage: https://github.com/ingydotnet/inline-pm repository: https://github.com/ingydotnet/inline-pm.git version: '0.86' x_generated_by_perl: v5.28.0 x_serialization_backend: 'YAML::Tiny version 1.73' META.json100644001750001750 315213605534015 13471 0ustar00ingyingy000000000000Inline-0.86{ "abstract" : "Write Perl Subroutines in Other Programming Languages", "author" : [ "Ingy d\u00f6t Net " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Inline", "no_index" : { "directory" : [ "example", "inc", "t", "xt" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Test::Pod" : "1.41" } }, "runtime" : { "requires" : { "Digest::MD5" : "0", "File::Spec" : "0.8", "perl" : "v5.8.1", "version" : "0.82" } }, "test" : { "requires" : { "JSON::PP" : "0", "Test::More" : "0.88", "Test::Warn" : "0.23" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/ingydotnet/inline-pm/issues" }, "homepage" : "https://github.com/ingydotnet/inline-pm", "repository" : { "type" : "git", "url" : "https://github.com/ingydotnet/inline-pm.git", "web" : "https://github.com/ingydotnet/inline-pm" } }, "version" : "0.86", "x_generated_by_perl" : "v5.28.0", "x_serialization_backend" : "Cpanel::JSON::XS version 4.06" } 05files.t100644001750001750 113613605534015 13747 0ustar00ingyingy000000000000Inline-0.86/tuse strict; use warnings; use lib -e 't' ? 't' : 'test'; use TestInlineSetup; use Test::More; use Inline Config => DIRECTORY => $TestInlineSetup::DIR; BEGIN { eval "require Inline::Files"; if ($@) { warn "Skipping - couldn't load the Inline::Files module\n"; print "1..1\nok 1\n"; exit 0; } } use Inline::Files; BEGIN { plan(tests => 1, todo => [], onfail => sub {}, ); } # test 1 # Make sure that Inline::Files support works use Inline Foo => 'BELOW'; ok(test1('test1')); __FOO__ foo-sub test1 { foo-return $_[0] foo-eq 'test1'; } Makefile.PL100644001750001750 415113605534015 14022 0ustar00ingyingy000000000000Inline-0.86# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.012. use strict; use warnings; use 5.008001; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Write Perl Subroutines in Other Programming Languages", "AUTHOR" => "Ingy d\x{f6}t Net ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "Inline", "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.008001", "NAME" => "Inline", "PREREQ_PM" => { "Digest::MD5" => 0, "File::Spec" => "0.8", "version" => "0.82" }, "TEST_REQUIRES" => { "JSON::PP" => 0, "Test::More" => "0.88", "Test::Warn" => "0.23" }, "VERSION" => "0.86", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Digest::MD5" => 0, "File::Spec" => "0.8", "JSON::PP" => 0, "Test::More" => "0.88", "Test::Warn" => "0.23", "version" => "0.82" ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); use Config; use File::Find; my $file = 'inc/bin/testml-cpan'; open IN, '<', $file or die "Can't open '$file' for input"; my @bin = ; close IN; shift @bin; unshift @bin, "#!$Config{perlpath}\n"; open OUT, '>', $file or die "Can't open '$file' for output"; print OUT @bin; close OUT; chmod 0755, 'inc/bin/testml-cpan'; if ($^O eq 'MSWin32') { my $file = 'inc/bin/testml-cpan.cmd'; open OUT, '>', $file or die "Can't open '$file' for output"; print OUT 'if exist "%~dpn0" perl %0 %*', "\r\n"; close OUT; find sub { return unless -f && /\.t$/; my $file = $_; open IN, '<', $file or die "Can't open '$file' for input"; return unless =~ /testml-cpan/; my $text = do {local $/; }; close IN; open OUT, '>', $file or die "Can't open '$file' for output"; print OUT '#!inc\\bin\\testml-cpan', "\r\n"; print OUT $text; close OUT; }, 't'; } CONTRIBUTING100644001750001750 251513605534015 13704 0ustar00ingyingy000000000000Inline-0.86Contributing ============ The "Inline" Project needs your help! Please consider being a contributor. This file contains instructions that will help you be an effective contributor to the Project. GitHub ------ The code for this Project is hosted at GitHub. The URL is: https://github.com/ingydotnet/inline-pm You can get the code with this command: git clone https://github.com/ingydotnet/inline-pm If you've found a bug or a missing feature that you would like the author to know about, report it here: https://github.com/ingydotnet/inline-pm/issues or fix it and submit a pull request here: https://github.com/ingydotnet/inline-pm/pulls See these links for help on interacting with GitHub: * https://help.github.com/ * https://help.github.com/articles/creating-a-pull-request Zilla::Dist ----------- This Project uses Zilla::Dist to prepare it for publishing to CPAN. Read: https://metacpan.org/pod/Zilla::Dist::Contributing for up-to-date instructions on what contributors like yourself need to know to use it. IRC --- Inline has an IRC channel where you can find real people to help you: irc.perl.org#inline Join the channel. Join the team! Electronic Mailing List ----------------------- Inline has an email discussion list: inline@perl.org Thanks in advance, # This file generated by Zilla-Dist-0.1.3 01usages.t100644001750001750 403413605534015 14130 0ustar00ingyingy000000000000Inline-0.86/tuse strict; use warnings; my $t; use lib ($t = -e 't' ? 't' : 'test'); use TestInlineSetup; use Test::More; use Inline conFig => DiREcTOrY => $TestInlineSetup::DIR; unless ($TestInlineSetup::DIAG) { diag <<'EOD' Unable to load diagnostics module, test results are unaffected. The diagnostics module cannot be loaded. The module gets its explanations for messages from the perldoc file perldiag.pod. Although both the module and the perldoc file are core parts of perl, some packaging systems distribute them in separate packages. E.g. in Cygwin this package is called perl_pods. Installing this package should make the diagnostics module load correctly. EOD } use Inline Foo => File::Spec->catfile(File::Spec->curdir(),$t,'file'); ok(test1('test1'), 'read external file'); use Inline Foo => 'DATA'; ok(test2('test2'), 'DATA handle'); use Inline 'Foo'; ok(!test3('test3'), 'unspecified = DATA handle'); ok(test4('test4'), 'given as string'); use Inline Foo => 'foo-sub test4 { foo-return $_[0] foo-eq "test4"; }'; ok(test5('test5'), 'lang alias'); use Inline foo => 'foo-sub test5 { foo-return $_[0] foo-eq "test5"; }'; eval <<'END'; use Inline Foo => 'DATA'; Inline->init; ok(add(3, 7) == 10, 'Inline->init actual'); END is($@, '', 'init'); Inline->bind(Foo => 'foo-sub subtract { foo-return $_[0] foo-- $_[1]; }'); is(subtract(3, 7), -4, 'bind'); { package FakeMod; $INC{__PACKAGE__.'.pm'} = 1; sub Inline { return unless $_[1] eq 'Foo'; { PATTERN=>'qunx-' } } } Inline->import(wiTh => 'FakeMod'); Inline->bind(Foo => 'qunx-sub subtract2 { qunx-return $_[0] qunx-- $_[1]; }'); is(subtract2(3, 7), -4, 'with works'); { package NoWith; $INC{__PACKAGE__.'.pm'} = 1; sub Inline { } } Inline->import(with => 'NoWith'); eval { Inline->bind(NoWith => 'whatever'); }; isnt($@, '', 'check "with" croaks if no info returned'); done_testing; __END__ __Foo__ # Inline Foo file foo-sub test2 { foo-return $_[0] foo-eq 'test2'; } __Foo__ foo-sub test3 { foo-return $_[0] foo-eq 'yrlnry'; } __Foo__ foo-sub add { foo-return $_[0] foo-+ $_[1]; } 03errors.t100644001750001750 120213605534015 14151 0ustar00ingyingy000000000000Inline-0.86/t#!inc/bin/testml-cpan *perl.eval-catch =~ *error-patterns === Bad first parameter --- perl use Inline Bogus => 'code'; --- error-patterns(@/) You have specified 'Bogus' as an Inline programming language. I currently only know about the following languages: === Bad shortcut --- perl use Inline 'force', 'hocum'; --- error-patterns(@/) Invalid shortcut 'hocum' specified. Valid shortcuts are: VERSION, INFO, FORCE, NOCLEAN, CLEAN, UNTAINT, SAFE, UNSAFE, GLOBAL, NOISY and REPORTBUG === Bad config option --- perl use Inline Foo => 'xxx' => ENABLE => 'BOgUM'; --- error-patterns(@/) 'BOGUM' is not a valid config option for Inline::Foo 04create.t100644001750001750 70213605534015 14065 0ustar00ingyingy000000000000Inline-0.86/tuse strict; use warnings; use lib -e 't' ? 't' : 'test'; use TestInlineSetup; use Test::More tests => 1; BEGIN { delete $ENV{PERL_INLINE_DIRECTORY}; delete $ENV{HOME}; } # Make sure Inline can generate a new _Inline/ directory. # (But make sure it's in our own space.) use Inline Config => DIRECTORY => $TestInlineSetup::DIR; use Inline 'Foo'; ok(add(3, 7) == 10, 'in own DID'); __END__ __Foo__ foo-sub add { foo-return $_[0] + $_[1]; } 02config.t100644001750001750 113013605534015 14101 0ustar00ingyingy000000000000Inline-0.86/tuse strict; use warnings; use lib -e 't' ? 't' : 'test'; use TestInlineSetup; use Test::More tests => 2; use Inline Config => DIrECTORY => $TestInlineSetup::DIR, DISABLE => 'WARNINGS'; ok(test1('test1'), 'ENABLE'); use Inline Foo => <<'END_OF_FOO', ENaBLE => 'bAR'; foo-sub test1 { bar-return $_[0] bar-eq 'test1'; } END_OF_FOO ok(test2('test2'), 'PATTERN'); use Inline Foo => ConFig => ENABLE => 'BaR'; use Inline Foo => ConFig =>; # check accumulates instead of reset use Inline Foo => <<'END_OF_FOO', PAtTERN => 'gogo-'; gogo-sub test2 { bar-return $_[0] gogo-eq 'test2'; } END_OF_FOO lib000755001750001750 013605534015 12455 5ustar00ingyingy000000000000Inline-0.86Inline.pm100644001750001750 17230713605534015 14443 0ustar00ingyingy000000000000Inline-0.86/libuse strict; use warnings; package Inline; our $VERSION = '0.86'; use Inline::denter; use Config; use Carp; use Cwd qw(abs_path cwd); use Encode; use File::Spec; use File::Spec::Unix; use Fcntl qw(LOCK_EX LOCK_UN); use version; use utf8; my %CONFIG = (); my @DATA_OBJS = (); my $INIT = 0; my $version_requested = 0; my $version_printed = 0; my $untaint = 0; my $safemode = 0; our $languages = undef; our $did = '_Inline'; # Default Inline Directory # This is the config file written by create_config_file(). our $configuration_file = 'config-' . $Config::Config{'archname'} . '-' . $]; my %shortcuts = ( NOCLEAN => [CLEAN_AFTER_BUILD => 0], CLEAN => [CLEAN_BUILD_AREA => 1], FORCE => [FORCE_BUILD => 1], INFO => [PRINT_INFO => 1], VERSION => [PRINT_VERSION => 1], REPORTBUG => [REPORTBUG => 1], UNTAINT => [UNTAINT => 1], SAFE => [SAFEMODE => 1], UNSAFE => [SAFEMODE => 0], GLOBAL => [GLOBAL_LOAD => 1], NOISY => [BUILD_NOISY => 1], TIMERS => [BUILD_TIMERS => 1], NOWARN => [WARNINGS => 0], _INSTALL_ => [_INSTALL_ => 1], SITE_INSTALL => undef, # No longer supported. ); my $default_config = { NAME => '', AUTONAME => -1, VERSION => '', DIRECTORY => '', WITH => [], USING => [], CLEAN_AFTER_BUILD => 1, CLEAN_BUILD_AREA => 0, FORCE_BUILD => 0, PRINT_INFO => 0, PRINT_VERSION => 0, REPORTBUG => 0, UNTAINT => 0, NO_UNTAINT_WARN => 0, REWRITE_CONFIG_FILE => 0, SAFEMODE => -1, GLOBAL_LOAD => 0, BUILD_NOISY => 0, BUILD_TIMERS => 0, WARNINGS => 1, _INSTALL_ => 0, _TESTING => 0, }; sub UNTAINT {$untaint} sub SAFEMODE {$safemode} #============================================================================== # This is where everything starts. #============================================================================== sub import { my $class = shift; $class->import_heavy(@_); } sub import_heavy { local ($/, $") = ("\n", ' '); local ($\, $,); my $o; my ($pkg, $script) = caller(1); # Not sure what this is for. Let's see what breaks. # $pkg =~ s/^.*[\/\\]//; my $class = shift; if ($class ne 'Inline') { croak M01_usage_use($class) if $class =~ /^Inline::/; croak M02_usage(); } $CONFIG{$pkg}{template} ||= $default_config; return unless @_; &create_config_file(), return 1 if $_[0] eq '_CONFIG_'; goto &maker_utils if $_[0] =~ /^(install|makedist|makeppd)$/i; my $control = shift; if (uc $control eq uc 'with') { return handle_with($pkg, @_); } elsif (uc $control eq uc 'Config') { return handle_global_config($pkg, @_); } elsif (exists $shortcuts{uc($control)}) { handle_shortcuts($pkg, $control, @_); $version_requested = $CONFIG{$pkg}{template}{PRINT_VERSION}; return; } elsif ($control =~ /^\S+$/ and $control !~ /\n/) { my $language_id = $control; my $option = shift || ''; my @config = @_; my $next = 0; for (@config) { next if $next++ % 2; croak M02_usage() if /[\s\n]/; } $o = bless {}, $class; $o->{INLINE}{version} = $VERSION; $o->{API}{pkg} = $pkg; $o->{API}{script} = $script; $o->{API}{language_id} = $language_id; if ($option =~ /^(FILE|BELOW)$/i or not $option and defined $INC{File::Spec::Unix->catfile('Inline','Files.pm')} and Inline::Files::get_filename($pkg) ) { $o->read_inline_file; $o->{CONFIG} = handle_language_config($o->{CONFIG}, @config); } elsif ($option eq 'DATA' or not $option) { $o->{CONFIG} = handle_language_config($o->{CONFIG}, @config); push @DATA_OBJS, $o; return; } elsif (uc $option eq uc 'Config') { $CONFIG{$pkg}{$language_id} = handle_language_config($CONFIG{$pkg}{$language_id}, @config); return; } else { $o->receive_code($option); $o->{CONFIG} = handle_language_config($o->{CONFIG}, @config); } } else { croak M02_usage(); } $o->glue; } #============================================================================== # Run time version of import (public method) #============================================================================== sub bind { local ($/, $") = ("\n", ' '); local ($\, $,); my ($code, @config); my $o; my ($pkg, $script) = caller; my $class = shift; croak M03_usage_bind() unless $class eq 'Inline'; $CONFIG{$pkg}{template} ||= $default_config; my $language_id = shift or croak M03_usage_bind(); croak M03_usage_bind() unless ($language_id =~ /^\S+$/ and $language_id !~ /\n/); $code = shift or croak M03_usage_bind(); @config = @_; my $next = 0; for (@config) { next if $next++ % 2; croak M03_usage_bind() if /[\s\n]/; } $o = bless {}, $class; $o->{INLINE}{version} = $VERSION; $o->{API}{pkg} = $pkg; $o->{API}{script} = $script; $o->{API}{language_id} = $language_id; $o->receive_code($code); $o->{CONFIG} = handle_language_config($o->{CONFIG}, @config); $o->glue; } #============================================================================== # Process delayed objects that don't have source code yet. #============================================================================== # This code is an ugly hack because of the fact that you can't use an # INIT block at "run-time proper". So we kill the warning and tell users # to use an Inline->init() call if they run into problems. (rare) eval <read_DATA; $o->glue; } } sub END { warn M51_unused_DATA() if @DATA_OBJS; print_version() if $version_requested && not $version_printed; } #============================================================================== # Print a small report about the version of Inline #============================================================================== sub print_version { return if $version_printed++; print STDERR <{API}}{qw(pkg language_id)}; my @config = (%{$CONFIG{$pkg}{template}}, %{$CONFIG{$pkg}{$language_id} || {}}, %{$o->{CONFIG} || {}}, ); @config = $o->check_config(@config); $o->fold_options; $o->check_installed; $o->env_untaint if UNTAINT; if (not $o->{INLINE}{object_ready}) { $o->check_config_file; # Final DIRECTORY set here. push @config, $o->with_configs; my $language = $o->{API}{language}; croak M04_error_nocode($language_id) unless $o->{API}{code}; $o->check_module; } $o->env_untaint if UNTAINT; $o->obj_untaint if UNTAINT; print_version() if $version_requested; $o->reportbug() if $o->{CONFIG}{REPORTBUG}; if (not $o->{INLINE}{object_ready} or $o->{CONFIG}{PRINT_INFO} ) { eval "require $o->{INLINE}{ILSM_module}"; croak M05_error_eval('glue', $@) if $@; $o->push_overrides; bless $o, $o->{INLINE}{ILSM_module}; $o->validate(@config); } else { $o->{CONFIG} = {(%{$o->{CONFIG}}, @config)}; } $o->print_info if $o->{CONFIG}{PRINT_INFO}; unless ($o->{INLINE}{object_ready} or not length $o->{INLINE}{ILSM_suffix}) { $o->build(); $o->write_inl_file() unless $o->{CONFIG}{_INSTALL_}; } if ($o->{INLINE}{ILSM_suffix} ne 'so' and $o->{INLINE}{ILSM_suffix} ne 'dll' and $o->{INLINE}{ILSM_suffix} ne 'bundle' and $o->{INLINE}{ILSM_suffix} ne 'sl' and ref($o) eq 'Inline' ) { eval "require $o->{INLINE}{ILSM_module}"; croak M05_error_eval('glue', $@) if $@; $o->push_overrides; bless $o, $o->{INLINE}{ILSM_module}; $o->validate(@config); } $o->load; $o->pop_overrides; } #============================================================================== # Set up the USING overrides #============================================================================== sub push_overrides { my ($o) = @_; my ($language_id) = $o->{API}{language_id}; my ($ilsm) = $o->{INLINE}{ILSM_module}; for (@{$o->{CONFIG}{USING}}) { my $fixed_name = /^Parser?(Pegex|RegExp|RecDescent)$/ ? "Parser::$1" : $_; $fixed_name =~ s/^:://; my $using_module = /^::/ ? "Inline::${language_id}::$fixed_name" : /::/ ? $_ : "Inline::${language_id}::$fixed_name"; eval "require $using_module"; croak "Invalid module '$using_module' in USING list:\n$@" if $@; my $register; eval "\$register = $using_module->register"; croak "Invalid module '$using_module' in USING list:\n$@" if $@; for my $override (@{$register->{overrides}}) { no strict 'refs'; next if defined $o->{OVERRIDDEN}{$ilsm . "::$override"}; $o->{OVERRIDDEN}{$ilsm . "::$override"} = \&{$ilsm . "::$override"}; { no warnings 'redefine'; *{$ilsm . "::$override"} = \&{$using_module . "::$override"}; } } } } #============================================================================== # Restore the modules original methods #============================================================================== sub pop_overrides { my $nowarn = $] >= 5.006 ? "no warnings 'redefine';" : ''; eval ($nowarn . 'my ($o) = @_; for my $override (keys %{$o->{OVERRIDDEN}}) { no strict "refs"; *{$override} = $o->{OVERRIDDEN}{$override}; } delete $o->{OVERRIDDEN};') } #============================================================================== # Get source from the DATA filehandle #============================================================================== my (%DATA, %DATA_read); sub read_DATA { require Socket; my ($marker, $marker_tag); my $o = shift; my ($pkg, $language_id) = @{$o->{API}}{qw(pkg language_id)}; unless ($DATA_read{$pkg}++) { no strict 'refs'; *Inline::DATA = *{$pkg . '::DATA'}; local ($/); my ($CR, $LF) = (&Socket::CR, &Socket::LF); (my $data = ) =~ s/$CR?$LF/\n/g; @{$DATA{$pkg}} = split /(?m)^[ \t]{0,}(__\S+?__\n)/, $data; shift @{$DATA{$pkg}} unless ($ {$DATA{$pkg}}[0] || '') =~ /__\S+?__\n/; } ($marker, $o->{API}{code}) = splice @{$DATA{$pkg}}, 0, 2; croak M08_no_DATA_source_code($language_id) unless defined $marker; ($marker_tag = $marker) =~ s/__(\S+?)__\n/$1/; croak M09_marker_mismatch($marker, $language_id) unless $marker_tag eq $language_id; } #============================================================================== # Validate and store the non language-specific config options #============================================================================== sub check_config { my $o = shift; my @others; while (@_) { my ($key, $value) = (shift, shift); if (defined $default_config->{$key}) { if ($key =~ /^(WITH|USING)$/) { croak M10_usage_WITH_USING() if (ref $value and ref $value ne 'ARRAY'); $value = [$value] unless ref $value; $o->{CONFIG}{$key} = $value; next; } $o->{CONFIG}{$key} = $value, next if not $value; if ($key eq 'DIRECTORY') { croak M11_usage_DIRECTORY($value) unless (-d $value); $value = abs_path($value); } elsif ($key eq 'NAME') { croak M12_usage_NAME($value) unless $value =~ /^[a-zA-Z_](\w|::)*$/; } elsif ($key eq 'VERSION') { croak M13_usage_VERSION($value) unless version::is_lax($value); } $o->{CONFIG}{$key} = $value; } else { push @others, $key, $value; } } return (@others); } #============================================================================== # Set option defaults based on current option settings. #============================================================================== sub fold_options { my $o = shift; # The following small section of code seems, to me, to be unnecessary - which is the # reason that I've commented it out. I've left it here (including its associated comments) # in case it later becomes evident that there *is* good reason to include it. --sisyphus # ## This bit tries to enable UNTAINT automatically if required when running the test suite. # my $env_ha = $ENV{HARNESS_ACTIVE} || 0 ; # my ($harness_active) = $env_ha =~ /(.*)/ ; # if (($harness_active)&&(! $o->{CONFIG}{UNTAINT})){ # eval { # require Scalar::Util; # $o->{CONFIG}{UNTAINT} = # (Scalar::Util::tainted(Cwd::cwd()) ? 1 : 0) ; ## Disable SAFEMODE in the test suite, we know what we are doing... # $o->{CONFIG}{SAFEMODE} = 0 ; # warn "\n-[tT] enabled for test suite. #Automatically setting UNTAINT=1 and SAFEMODE=0.\n" # unless $Inline::_TAINT_WARNING_ ; # $Inline::_TAINT_WARNING_ = 1 ; # } ; # } ## $untaint = $o->{CONFIG}{UNTAINT} || 0; $safemode = (($o->{CONFIG}{SAFEMODE} == -1) ? ($untaint ? 1 : 0) : $o->{CONFIG}{SAFEMODE} ); if (UNTAINT and SAFEMODE and not $o->{CONFIG}{DIRECTORY}) { croak M49_usage_unsafe(1) if ($< == 0 or $> == 0); warn M49_usage_unsafe(0) if $^W; } if ($o->{CONFIG}{AUTONAME} == -1) { $o->{CONFIG}{AUTONAME} = length($o->{CONFIG}{NAME}) ? 0 : 1; } $o->{API}{cleanup} = ($o->{CONFIG}{CLEAN_AFTER_BUILD} and not $o->{CONFIG}{REPORTBUG}); } #============================================================================== # Check if Inline extension is preinstalled #============================================================================== sub check_installed { my $o = shift; $o->{INLINE}{object_ready} = 0; unless ($o->{API}{code} =~ /^[A-Fa-f0-9]{32}$/) { require Digest::MD5; my $encoded_code = $o->{API}{code}; if ( utf8::is_utf8($encoded_code)) { $encoded_code = Encode::encode_utf8($encoded_code); } $o->{INLINE}{md5} = Digest::MD5::md5_hex($encoded_code); } else { $o->{INLINE}{md5} = $o->{API}{code}; } return if $o->{CONFIG}{_INSTALL_}; return unless $o->{CONFIG}{VERSION}; croak M26_error_version_without_name() unless $o->{CONFIG}{NAME}; my @pkgparts = split(/::/, $o->{API}{pkg}); my $realname = File::Spec->catfile(@pkgparts) . '.pm'; my $realname_unix = File::Spec::Unix->catfile(@pkgparts) . '.pm'; my $realpath = $INC{$realname_unix} or croak M27_module_not_indexed($realname_unix); my ($volume,$dir,$file) = File::Spec->splitpath($realpath); my @dirparts = File::Spec->splitdir($dir); pop @dirparts unless $dirparts[-1]; push @dirparts, $file; my @endparts = splice(@dirparts, 0 - @pkgparts); $dirparts[-1] = 'arch' if $dirparts[-2] eq 'blib' && $dirparts[-1] eq 'lib'; File::Spec->catfile(@endparts) eq $realname or croak M28_error_grokking_path($realpath); $realpath = File::Spec->catpath($volume,File::Spec->catdir(@dirparts),""); $o->{API}{version} = $o->{CONFIG}{VERSION}; $o->{API}{module} = $o->{CONFIG}{NAME}; my @modparts = split(/::/,$o->{API}{module}); $o->{API}{modfname} = $modparts[-1]; $o->{API}{modpname} = File::Spec->catdir(@modparts); my $suffix = $Config{dlext}; my $obj = File::Spec->catfile($realpath,'auto',$o->{API}{modpname}, "$o->{API}{modfname}.$suffix"); croak M30_error_no_obj($o->{CONFIG}{NAME}, $o->{API}{pkg}, $realpath) unless -f $obj; @{$o->{CONFIG}}{qw( PRINT_INFO REPORTBUG FORCE_BUILD _INSTALL_ )} = (0, 0, 0, 0); $o->{install_lib} = $realpath; $o->{INLINE}{ILSM_type} = 'compiled'; $o->{INLINE}{ILSM_module} = 'Inline::C'; $o->{INLINE}{ILSM_suffix} = $suffix; $o->{INLINE}{object_ready} = 1; } #============================================================================== # Dynamically load the object module #============================================================================== sub load { my $o = shift; return if $o->{CONFIG}{_INSTALL_}; my ($pkg, $module) = @{$o->{API}}{qw(pkg module)}; croak M42_usage_loader() unless $o->{INLINE}{ILSM_type} eq 'compiled'; require DynaLoader; @Inline::ISA = qw(DynaLoader); my $global = $o->{CONFIG}{GLOBAL_LOAD} ? '0x01' : '0x00'; my $version = $o->{API}{version} || '0.00'; eval <bootstrap; END croak M43_error_bootstrap($module, $@) if $@; } #============================================================================== # Create file that satisfies the Makefile dependency for this object #============================================================================== sub satisfy_makefile_dep { my $o = shift; my $inline = $o->{API}{modinlname}; open INLINE, "> $inline" or croak M24_open_for_output_failed($inline); print INLINE "*** AUTOGENERATED by Inline.pm ***\n\n"; print INLINE "This file satisfies the make dependency for "; print INLINE "$o->{API}{module}\n"; close INLINE; return; } #============================================================================== # Process the config options that apply to all Inline sections #============================================================================== sub handle_global_config { my $pkg = shift; while (@_) { my ($key, $value) = (uc shift, shift); croak M02_usage() if $key =~ /[\s\n]/; if ($key =~ /^(ENABLE|DISABLE)$/) { ($key, $value) = (uc $value, $key eq 'ENABLE' ? 1 : 0); } croak M47_invalid_config_option($key) unless defined $default_config->{$key}; $CONFIG{$pkg}{template}{$key} = $value; } } #============================================================================== # Process the config options that apply to a particular language #============================================================================== sub handle_language_config { my %merge_with = %{ shift || {} }; my @values; while (@_) { my ($key, $value) = (uc shift, shift); croak M02_usage() if $key =~ /[\s\n]/; if ($key eq 'ENABLE') { push @values, uc $value, 1; } elsif ($key eq 'DISABLE') { push @values, uc $value, 0; } else { push @values, $key, $value; } } return {%merge_with, @values}; } #============================================================================== # Validate and store shortcut config options #============================================================================== sub handle_shortcuts { my $pkg = shift; for my $option (@_) { my $OPTION = uc($option); if ($OPTION eq 'SITE_INSTALL') { croak M58_site_install(); } elsif ($shortcuts{$OPTION}) { my ($method, $arg) = @{$shortcuts{$OPTION}}; $CONFIG{$pkg}{template}{$method} = $arg; } else { croak M48_usage_shortcuts($option); } } } #============================================================================== # Process the with command #============================================================================== sub handle_with { my $pkg = shift; croak M45_usage_with() unless @_; for (@_) { croak M02_usage() unless /^[\w:]+$/; eval "require $_;"; croak M46_usage_with_bad($_) . $@ if $@; push @{$CONFIG{$pkg}{template}{WITH}}, $_; } } #============================================================================== # Perform cleanup duties #============================================================================== sub DESTROY { my $o = shift; $o->clean_build if $o->{CONFIG}{CLEAN_BUILD_AREA}; } #============================================================================== # Get the source code #============================================================================== sub receive_code { my $o = shift; my $code = shift; croak M02_usage() unless (defined $code and $code); if (ref $code eq 'CODE') { $o->{API}{code} = &$code; } elsif (ref $code eq 'ARRAY') { $o->{API}{code} = join '', @$code; } elsif ($code =~ m|[/\\:]| and $code =~ m|^[/\\:\w.\-\ \$\[\]<>]+$|) { if (-f $code) { local ($/, *CODE); open CODE, "< $code" or croak M06_code_file_failed_open($code); $o->{API}{code} = ; } else { croak M07_code_file_does_not_exist($code); } } else { $o->{API}{code} = $code; } } #============================================================================== # Get the source code from an Inline::Files filehandle #============================================================================== sub read_inline_file { my $o = shift; my ($lang, $pkg) = @{$o->{API}}{qw(language_id pkg)}; my $langfile = uc($lang); croak M59_bad_inline_file($lang) unless $langfile =~ /^[A-Z]\w*$/; croak M60_no_inline_files() unless (defined $INC{File::Spec::Unix->catfile("Inline","Files.pm")} and $Inline::Files::VERSION =~ /^\d\.\d\d$/ and $Inline::Files::VERSION ge '0.51'); croak M61_not_parsed() unless $lang = Inline::Files::get_filename($pkg); { no strict 'refs'; local $/; $Inline::FILE = \*{"${pkg}::$langfile"}; # open $Inline::FILE; $o->{API}{code} = <$Inline::FILE>; # close $Inline::FILE; } } #============================================================================== # Read the cached config file from the Inline directory. This will indicate # whether the Language code is valid or not. #============================================================================== sub check_config_file { my ($DIRECTORY, %config); my $o = shift; croak M14_usage_Config() if $Inline::Config::VERSION; croak M63_no_source($o->{API}{pkg}) if $o->{INLINE}{md5} eq $o->{API}{code}; # First make sure we have the DIRECTORY if ($o->{CONFIG}{_INSTALL_}) { croak M15_usage_install_directory() if $o->{CONFIG}{DIRECTORY}; my $cwd = Cwd::cwd(); $DIRECTORY = $o->{INLINE}{DIRECTORY} = File::Spec->catdir($cwd, $did); if (not -d $DIRECTORY) { _mkdir($DIRECTORY, 0777) or croak M16_DIRECTORY_mkdir_failed($DIRECTORY); } } else { $DIRECTORY = $o->{INLINE}{DIRECTORY} = $o->{CONFIG}{DIRECTORY} || $o->find_temp_dir; } if($o->{CONFIG}{REWRITE_CONFIG_FILE}) { if(-e File::Spec->catfile($DIRECTORY, $configuration_file)) { my $unlink = unlink(File::Spec->catfile($DIRECTORY, $configuration_file)); if(!$unlink) {warn "REWRITE_CONFIG_FILE is set, but removal of config file failed"} else {warn "config file removal successful\n" if $o->{CONFIG}{_TESTING}} } } my $load_cfg = sub { $o->create_config_file($DIRECTORY) if not -e File::Spec->catfile($DIRECTORY, $configuration_file); open CONFIG, "< ".File::Spec->catfile($DIRECTORY,$configuration_file) or croak M17_config_open_failed($DIRECTORY); flock(CONFIG, LOCK_EX) if $^O !~ /^VMS|riscos|VOS$/; my $config = join '', ; flock(CONFIG, LOCK_UN) if $^O !~ /^VMS|riscos|VOS$/; close CONFIG; unless($config =~ /^version :/) { warn "\$load_cfg sub: \$config: *${config}*\n"; croak M62_invalid_config_file(File::Spec->catfile($DIRECTORY,$configuration_file)); } if(UNTAINT) { warn "In Inline::check_config_file(): Blindly untainting Inline configuration file information.\n" unless $o->{CONFIG}{NO_UNTAINT_WARN}; ($config) = $config =~ /(.*)/s; } %config = Inline::denter->new()->undent($config); } ; $load_cfg->() ; if (! defined $config{languages}->{$o->{API}{language_id}}){ my $unlink = unlink(File::Spec->catfile($DIRECTORY, $configuration_file)); if(!$unlink) {warn "Failed to remove config file"} else {warn "config file removed\n" if $o->{CONFIG}{_TESTING}} $load_cfg->() ; } $Inline::languages = $config{languages}; { no warnings ('numeric'); # These warnings were a pain with devel releases. # If there's a problem with the version number, the # error message will output $config{version} anyway. croak M18_error_old_version($config{version}, $DIRECTORY) unless (defined $config{version} and $config{version} =~ /TRIAL/ or $config{version} >= 0.40); } # numeric warnings re-enabled. croak M19_usage_language($o->{API}{language_id}, $DIRECTORY) unless defined $config{languages}->{$o->{API}{language_id}}; $o->{API}{language} = $config{languages}->{$o->{API}{language_id}}; if ($o->{API}{language} ne $o->{API}{language_id}) { if (defined $o->{$o->{API}{language_id}}) { $o->{$o->{API}{language}} = $o->{$o->{API}{language_id}}; delete $o->{$o->{API}{language_id}}; } } $o->{INLINE}{ILSM_type} = $config{types}->{$o->{API}{language}}; $o->{INLINE}{ILSM_module} = $config{modules}->{$o->{API}{language}}; $o->{INLINE}{ILSM_suffix} = $config{suffixes}->{$o->{API}{language}}; } sub derive_minus_I { my $o = shift; require Cwd; my @libexclude = ( # perl has these already (grep length, map $Config{$_}, qw(archlibexp privlibexp sitearchexp sitelibexp vendorarchexp vendorlibexp)), (defined $ENV{PERL5LIB} ? ( map { my $l = $_; ($l, map File::Spec->catdir($l, $Config{$_}), qw(version archname)) } split $Config{path_sep}, $ENV{PERL5LIB} ) : ()), ); if ($^O eq 'MSWin32') { # Strawberry Perl Unix-ises its @INC, so we need to add Unix-y versions push @libexclude, map { my $d = $_; $d =~ s#\\#/#g; $d } @libexclude; } my %libexclude = map { $_=>1 } @libexclude; my @libinclude = grep !$libexclude{$_}, grep { $_ ne '.' } @INC; # grep is because on Windows, Cwd::abs_path blows up on non-exist dir @libinclude = map Cwd::abs_path($_), grep -e, @libinclude; my %seen; @libinclude = grep !$seen{$_}++, @libinclude; # de-dup @libinclude = map /(.*)/s, @libinclude if UNTAINT; @libinclude; } #============================================================================== # Auto-detect installed Inline language support modules #============================================================================== sub create_config_file { my ($o, $dir) = @_; # This subroutine actually fires off another instance of perl. # with arguments that make this routine get called again. # That way the queried modules don't stay loaded. if (defined $o) { ($dir) = $dir =~ /(.*)/s if UNTAINT; my $perl = $Config{perlpath}; $perl = $^X unless -f $perl; ($perl) = $perl =~ /(.*)/s if UNTAINT; local $ENV{PERL5OPT} if defined $ENV{PERL5OPT}; my @_inc = map "-I$_", $o->derive_minus_I; system $perl, @_inc, "-MInline=_CONFIG_", "-e1", "$dir" and croak M20_config_creation_failed($dir); return; } my ($lib, $mod, $register, %checked, %languages, %types, %modules, %suffixes); for my $lib (@INC) { next unless -d File::Spec->catdir($lib,"Inline"); opendir LIB, File::Spec->catdir($lib,"Inline") or warn(M21_opendir_failed(File::Spec->catdir($lib,"Inline"))), next; while ($mod = readdir(LIB)) { next unless $mod =~ /\.pm$/; $mod =~ s/\.pm$//; next if ($checked{$mod}++); if ($mod eq 'Config') { # Skip Inline::Config warn M14_usage_Config(); next; } next if $mod =~ /^(MakeMaker|denter|messages)$/; # @INC is made safe by -T disallowing PERL5LIB et al ($mod) = $mod =~ /(.*)/; eval "require Inline::$mod;"; warn($@), next if $@; eval "\$register=&Inline::${mod}::register"; next if $@; my $language = ($register->{language}) or warn(M22_usage_register($mod)), next; for (@{$register->{aliases}}) { warn(M23_usage_alias_used($mod, $_, $languages{$_})), next if defined $languages{$_}; $languages{$_} = $language; } $languages{$language} = $language; $types{$language} = $register->{type}; $modules{$language} = "Inline::$mod"; $suffixes{$language} = $register->{suffix}; } closedir LIB; } my $file = File::Spec->catfile($ARGV[0], $configuration_file); open CONFIG, "> $file" or croak M24_open_for_output_failed($file); flock(CONFIG, LOCK_EX) if $^O !~ /^VMS|riscos|VOS$/; print CONFIG Inline::denter->new() ->indent(*version => $Inline::VERSION, *languages => \%languages, *types => \%types, *modules => \%modules, *suffixes => \%suffixes, ); flock(CONFIG, LOCK_UN) if $^O !~ /^VMS|riscos|VOS$/; close CONFIG; exit 0; } #============================================================================== # Check to see if code has already been compiled #============================================================================== sub check_module { my ($module, $module2); my $o = shift; return $o->install if $o->{CONFIG}{_INSTALL_}; if ($o->{CONFIG}{NAME}) { $module = $o->{CONFIG}{NAME}; } elsif ($o->{API}{pkg} eq 'main') { $module = $o->{API}{script}; my($v,$d,$file) = File::Spec->splitpath($module); $module = $file; $module =~ s|\W|_|g; $module =~ s|^_+||; $module =~ s|_+$||; $module = 'FOO' if $module =~ /^_*$/; $module = "_$module" if $module =~ /^\d/; } else { $module = $o->{API}{pkg}; } $o->{API}{suffix} = $o->{INLINE}{ILSM_suffix}; $o->{API}{directory} = $o->{INLINE}{DIRECTORY}; my $auto_level = 2; while ($auto_level <= 5) { if ($o->{CONFIG}{AUTONAME}) { $module2 = $module . '_' . substr($o->{INLINE}{md5}, 0, 2 + $auto_level); $auto_level++; } else { $module2 = $module; $auto_level = 6; # Don't loop on non-autoname objects } $o->{API}{module} = $module2; my @modparts = split /::/, $module2; $o->{API}{modfname} = $modparts[-1]; $o->{API}{modpname} = File::Spec->catdir(@modparts); $o->{API}{build_dir} = File::Spec->catdir($o->{INLINE}{DIRECTORY}, 'build',$o->{API}{modpname}); $o->{API}{install_lib} = File::Spec->catdir($o->{INLINE}{DIRECTORY}, 'lib'); my $inl = File::Spec->catfile($o->{API}{install_lib},"auto", $o->{API}{modpname},"$o->{API}{modfname}.inl"); $o->{API}{location} = File::Spec->catfile($o->{API}{install_lib},"auto",$o->{API}{modpname}, "$o->{API}{modfname}.$o->{INLINE}{ILSM_suffix}"); last unless -f $inl; my %inl; { local ($/, *INL); open INL, $inl or croak M31_inline_open_failed($inl); %inl = Inline::denter->new()->undent(); } next unless ($o->{INLINE}{md5} eq $inl{md5}); next unless ($inl{inline_version} ge '0.40'); next unless ($inl{Config}{version} eq $Config::Config{version}); next unless ($inl{Config}{archname} eq $Config::Config{archname}); unless (-f $o->{API}{location}) { warn <{API}{location} For Inline file: $inl END next; } $o->{INLINE}{object_ready} = 1 unless $o->{CONFIG}{FORCE_BUILD}; last; } unshift @::INC, $o->{API}{install_lib}; } #============================================================================== # Set things up so that the extension gets installed into the blib/arch. # Then 'make install' will do the right thing. #============================================================================== sub install { my ($module, $DIRECTORY); my $o = shift; croak M64_install_not_c($o->{API}{language_id}) unless uc($o->{API}{language_id}) =~ /^(C|CPP|Java|Python|Ruby|Lisp|Pdlpp)$/ ; croak M36_usage_install_main() if ($o->{API}{pkg} eq 'main'); croak M37_usage_install_auto() if $o->{CONFIG}{AUTONAME}; croak M38_usage_install_name() unless $o->{CONFIG}{NAME}; croak M39_usage_install_version() unless $o->{CONFIG}{VERSION}; croak M40_usage_install_badname($o->{CONFIG}{NAME}, $o->{API}{pkg}) unless $o->{CONFIG}{NAME} eq $o->{API}{pkg}; # $o->{CONFIG}{NAME} =~ /^$o->{API}{pkg}::\w(\w|::)+$/ # ); my ($mod_name, $mod_ver, $ext_name, $ext_ver) = ($o->{API}{pkg}, $ARGV[0], @{$o->{CONFIG}}{qw(NAME VERSION)}); croak M41_usage_install_version_mismatch($mod_name, $mod_ver, $ext_name, $ext_ver) unless ($mod_ver eq $ext_ver); $o->{INLINE}{INST_ARCHLIB} = $ARGV[1]; $o->{API}{version} = $o->{CONFIG}{VERSION}; $o->{API}{module} = $o->{CONFIG}{NAME}; my @modparts = split(/::/,$o->{API}{module}); $o->{API}{modfname} = $modparts[-1]; $o->{API}{modpname} = File::Spec->catdir(@modparts); $o->{API}{modinlname} = join('-',@modparts).'.inl'; $o->{API}{suffix} = $o->{INLINE}{ILSM_suffix}; $o->{API}{build_dir} = File::Spec->catdir($o->{INLINE}{DIRECTORY},'build', $o->{API}{modpname}); $o->{API}{directory} = $o->{INLINE}{DIRECTORY}; my $cwd = Cwd::cwd(); $o->{API}{install_lib} = File::Spec->catdir($cwd,$o->{INLINE}{INST_ARCHLIB}); $o->{API}{location} = File::Spec->catfile($o->{API}{install_lib},"auto",$o->{API}{modpname}, "$o->{API}{modfname}.$o->{INLINE}{ILSM_suffix}"); unshift @::INC, $o->{API}{install_lib}; $o->{INLINE}{object_ready} = 0; } #============================================================================== # Create the .inl file for an object #============================================================================== sub write_inl_file { my $o = shift; my $inl = File::Spec->catfile($o->{API}{install_lib},"auto",$o->{API}{modpname}, "$o->{API}{modfname}.inl"); open INL, "> $inl" or croak "Can't create Inline validation file $inl: $!"; my $apiversion = $Config{apiversion} || $Config{xs_apiversion}; print INL Inline::denter->new() ->indent(*md5, $o->{INLINE}{md5}, *name, $o->{API}{module}, *version, $o->{CONFIG}{VERSION}, *language, $o->{API}{language}, *language_id, $o->{API}{language_id}, *installed, $o->{CONFIG}{_INSTALL_}, *date_compiled, scalar localtime, *inline_version, $Inline::VERSION, *ILSM, { map {($_, $o->{INLINE}{"ILSM_$_"})} (qw( module suffix type )) }, *Config, { (map {($_,$Config{$_})} (qw( archname osname osvers cc ccflags ld so version ))), (apiversion => $apiversion), }, ); close INL; } #============================================================================== # Get config hints #============================================================================== sub with_configs { my $o = shift; my @configs; for my $mod (@{$o->{CONFIG}{WITH}}) { my $ref = eval { $mod->Inline($o->{API}{language}); }; croak M25_no_WITH_support($mod, $@) if $@; croak M65_WITH_not_lang($mod, $o->{API}{language}) unless $ref; push @configs, %$ref; } return @configs; } #============================================================================== # Blindly untaint tainted fields in %ENV. #============================================================================== sub env_untaint { my $o = shift; warn "In Inline::env_untaint() : Blindly untainting tainted fields in %ENV.\n" unless $o->{CONFIG}{NO_UNTAINT_WARN}; { no warnings ('uninitialized'); # In case $ENV{$_} is set to undef. for (keys %ENV) { ($ENV{$_}) = $ENV{$_} =~ /(.*)/; } } # only accept dirs that are absolute and not world-writable $ENV{PATH} = $^O eq 'MSWin32' ? join ';', grep {not /^\./ and -d $_ } split /;/, $ENV{PATH} : join ':', grep {/^\// and -d $_ and $< == $> ? 1 : not (-W $_ or -O $_) } split /:/, $ENV{PATH}; map {($_) = /(.*)/} @INC; # list cherry-picked from `perldoc perlrun` delete @ENV{qw(PERL5OPT PERL5SHELL PERL_ROOT IFS CDPATH ENV BASH_ENV)}; $ENV{SHELL} = '/bin/sh' if -x '/bin/sh'; $< = $> if $< != $>; # so child processes retain euid - ignore failure } #============================================================================== # Blindly untaint tainted fields in Inline object. #============================================================================== sub obj_untaint { my $o = shift; warn "In Inline::obj_untaint() : Blindly untainting tainted fields in Inline object.\n" unless $o->{CONFIG}{NO_UNTAINT_WARN}; ($o->{INLINE}{ILSM_module}) = $o->{INLINE}{ILSM_module} =~ /(.*)/; ($o->{API}{directory}) = $o->{API}{directory} =~ /(.*)/; ($o->{API}{build_dir}) = $o->{API}{build_dir} =~ /(.*)/; ($o->{CONFIG}{DIRECTORY}) = $o->{CONFIG}{DIRECTORY} =~ /(.*)/; ($o->{API}{install_lib}) = $o->{API}{install_lib} =~ /(.*)/; ($o->{API}{modpname}) = $o->{API}{modpname} =~ /(.*)/; ($o->{API}{modfname}) = $o->{API}{modfname} =~ /(.*)/; ($o->{API}{language}) = $o->{API}{language} =~ /(.*)/; ($o->{API}{pkg}) = $o->{API}{pkg} =~ /(.*)/; ($o->{API}{module}) = $o->{API}{module} =~ /(.*)/; } #============================================================================== # Clean the build directory from previous builds #============================================================================== sub clean_build { use strict; my ($prefix, $dir); my $o = shift; $prefix = $o->{INLINE}{DIRECTORY}; opendir(BUILD, $prefix) or croak "Can't open build directory: $prefix for cleanup $!\n"; while ($dir = readdir(BUILD)) { my $maybedir = File::Spec->catdir($prefix,$dir); if (($maybedir and -d $maybedir) and ($dir =~ /\w{36,}/)) { $o->rmpath($prefix,$dir); } } close BUILD; } #============================================================================== # Apply a list of filters to the source code #============================================================================== sub filter { my $o = shift; my $new_code = $o->{API}{code}; for (@_) { croak M52_invalid_filter($_) unless ref; if (ref eq 'CODE') { $new_code = $_->($new_code); } else { $new_code = $_->filter($o, $new_code); } } return $new_code; } #============================================================================== # User wants to report a bug #============================================================================== sub reportbug { use strict; my $o = shift; return if $o->{INLINE}{reportbug_handled}++; print STDERR < REPORTBUG mode in effect. Your Inline $o->{API}{language_id} code will be processed in the build directory: $o->{API}{build_dir} A perl-readable bug report including your perl configuration and run-time diagnostics will also be generated in the build directory. When the program finishes please bundle up the above build directory with: tar czf Inline.REPORTBUG.tar.gz $o->{API}{build_dir} and send "Inline.REPORTBUG.tar.gz" as an email attachment to the author of the offending Inline::* module with the subject line: REPORTBUG: Inline.pm Include in the email, a description of the problem and anything else that you think might be helpful. Patches are welcome! :-\) <-----------------------End of REPORTBUG Section------------------------------> END my %versions; { no strict 'refs'; %versions = map {eval "use $_();"; ($_, $ {$_ . '::VERSION'})} qw (Digest::MD5 Parse::RecDescent ExtUtils::MakeMaker File::Path FindBin Inline ); } $o->mkpath($o->{API}{build_dir}); open REPORTBUG, "> ".File::Spec->catfile($o->{API}{build_dir},"REPORTBUG") or croak M24_open_for_output_failed (File::Spec->catfile($o->{API}{build_dir},"REPORTBUG")); %Inline::REPORTBUG_Inline_Object = (); %Inline::REPORTBUG_Perl_Config = (); %Inline::REPORTBUG_Module_Versions = (); print REPORTBUG Inline::denter->new() ->indent(*REPORTBUG_Inline_Object, $o, *REPORTBUG_Perl_Config, \%Config::Config, *REPORTBUG_Module_Versions, \%versions, ); close REPORTBUG; } #============================================================================== # Print a small report if PRINT_INFO option is set. #============================================================================== sub print_info { use strict; my $o = shift; print STDERR < Information about the processing of your Inline $o->{API}{language_id} code: END print STDERR <{INLINE}{object_ready}); Your module is already compiled. It is located at: $o->{API}{location} END print STDERR <{INLINE}{object_ready} and $o->{CONFIG}{FORCE_BUILD}); But the FORCE_BUILD option is set, so your code will be recompiled. I\'ll use this build directory: $o->{API}{build_dir} and I\'ll install the executable as: $o->{API}{location} END print STDERR <{INLINE}{object_ready}); Your source code needs to be compiled. I\'ll use this build directory: $o->{API}{build_dir} and I\'ll install the executable as: $o->{API}{location} END eval { print STDERR $o->info; }; print $@ if $@; print STDERR < END } #============================================================================== # Hand off this invocation to Inline::MakeMaker #============================================================================== sub maker_utils { require Inline::MakeMaker; goto &Inline::MakeMaker::utils; } #============================================================================== # Utility subroutines #============================================================================== #============================================================================== # Make a path #============================================================================== sub mkpath { use strict; my ($o, $mkpath) = @_; my($volume,$dirs,$nofile) = File::Spec->splitpath($mkpath,1); my @parts = File::Spec->splitdir($dirs); my @done; foreach (@parts){ push(@done,$_); my $path = File::Spec->catpath($volume,File::Spec->catdir(@done),""); -d $path || _mkdir($path, 0777); } croak M53_mkdir_failed($mkpath) unless -d $mkpath; } #============================================================================== # Nuke a path (nicely) #============================================================================== sub rmpath { use strict; my ($o, $prefix, $rmpath) = @_; # Nuke the target directory _rmtree(File::Spec->catdir($prefix ? ($prefix,$rmpath) : ($rmpath))); # Remove any empty directories underneath the requested one my @parts = File::Spec->splitdir($rmpath); while (@parts){ $rmpath = File::Spec->catdir($prefix ? ($prefix,@parts) : @parts); ($rmpath) = $rmpath =~ /(.*)/ if UNTAINT; rmdir $rmpath or last; # rmdir failed because dir was not empty pop @parts; } } sub _rmtree { my($roots) = @_; $roots = [$roots] unless ref $roots; my($root); foreach $root (@{$roots}) { if ( -d $root ) { my(@names,@paths); if (opendir MYDIR, $root) { @names = readdir MYDIR; closedir MYDIR; } else { croak M21_opendir_failed($root); } my $dot = File::Spec->curdir(); my $dotdot = File::Spec->updir(); foreach my $name (@names) { next if $name eq $dot or $name eq $dotdot; my $maybefile = File::Spec->catfile($root,$name); push(@paths,$maybefile),next if $maybefile and -f $maybefile; push(@paths,File::Spec->catdir($root,$name)); } _rmtree(\@paths); ($root) = $root =~ /(.*)/ if UNTAINT; rmdir($root) or croak M54_rmdir_failed($root); } else { ($root) = $root =~ /(.*)/ if UNTAINT; unlink($root) or croak M55_unlink_failed($root); } } } #============================================================================== # Find the 'Inline' directory to use. #============================================================================== my $TEMP_DIR; sub find_temp_dir { return $TEMP_DIR if $TEMP_DIR; my ($temp_dir, $home, $bin, $cwd, $env); $temp_dir = ''; $env = $ENV{PERL_INLINE_DIRECTORY} || ''; $home = $ENV{HOME} ? abs_path($ENV{HOME}) : ''; if ($env and -d $env and -w $env) { $temp_dir = $env; } elsif ($cwd = abs_path('.') and $cwd ne $home and -d File::Spec->catdir($cwd,".Inline") and -w File::Spec->catdir($cwd,".Inline")) { $temp_dir = File::Spec->catdir($cwd,".Inline"); } else { require FindBin ; if ($bin = $FindBin::Bin and -d File::Spec->catdir($bin,".Inline") and -w File::Spec->catdir($bin,".Inline")) { $temp_dir = File::Spec->catdir($bin,".Inline"); } elsif ($home and -d File::Spec->catdir($home,".Inline") and -w File::Spec->catdir($home,".Inline")) { $temp_dir = File::Spec->catdir($home,".Inline"); } elsif (defined $cwd and $cwd and -d File::Spec->catdir($cwd, $did) and -w File::Spec->catdir($cwd, $did)) { $temp_dir = File::Spec->catdir($cwd, $did); } elsif (defined $bin and $bin and -d File::Spec->catdir($bin, $did) and -w File::Spec->catdir($bin, $did)) { $temp_dir = File::Spec->catdir($bin, $did); } elsif (defined $cwd and $cwd and -d $cwd and -w $cwd and _mkdir(File::Spec->catdir($cwd, $did), 0777)) { $temp_dir = File::Spec->catdir($cwd, $did); } elsif (defined $bin and $bin and -d $bin and -w $bin and _mkdir(File::Spec->catdir($bin, $did), 0777)) { $temp_dir = File::Spec->catdir($bin, $did); } } croak M56_no_DIRECTORY_found() unless $temp_dir; return $TEMP_DIR = abs_path($temp_dir); } sub _mkdir { my $dir = shift; my $mode = shift || 0777; ($dir) = ($dir =~ /(.*)/) if UNTAINT; $dir =~ s|[/\\:]$||; return mkdir($dir, $mode); } #============================================================================== # Error messages #============================================================================== sub M01_usage_use { my ($module) = @_; return < "source-string", config-pair-list; use Inline language => "source-file", config-pair-list; use Inline language => [source-line-list], config-pair-list; use Inline language => 'DATA', config-pair-list; use Inline language => 'Config', config-pair-list; use Inline Config => config-pair-list; use Inline with => module-list; use Inline shortcut-list; END # This is broken ???????????????????????????????????????????????????? $usage .= <bind() function. Valid usages are: Inline->bind(language => "source-string", config-pair-list); Inline->bind(language => "source-file", config-pair-list); Inline->bind(language => [source-line-list], config-pair-list); END $usage .= <catfile(${dir}, $configuration_file); return <catfile(${dir}, $configuration_file); return < '$mod'" but '$mod' does not work with Inline. $err END } sub M26_error_version_without_name { return < 'module1', 'module2', ..., 'moduleN'; END } sub M46_usage_with_bad { my $mod = shift; return < "$mod";'. '$mod' could not be found. END } sub M47_invalid_config_option { my ($option) = @_; return < 1; use Inline Config => DIrECTORY => $TestInlineSetup::DIR, DISABLE => 'WARNINGS'; ok(test2('𝘛𝘩𝘪𝘴 𝘪𝘴 𝘜𝘯𝘪𝘤𝘰𝘥𝘦 𝘵𝘦𝘹𝘵.'), 'UTF-8'); use Inline Foo => ConFig => ENABLE => 'BaR'; use Inline Foo => <<'END_OF_FOO', PAtTERN => 'gogo-'; use utf8; gogo-sub test2 { bar-return $_[0] gogo-eq '𝘛𝘩𝘪𝘴 𝘪𝘴 𝘜𝘯𝘪𝘤𝘰𝘥𝘦 𝘵𝘦𝘹𝘵.'; } END_OF_FOO Inline.pod100644001750001750 12153213605534015 14603 0ustar00ingyingy000000000000Inline-0.86/lib=pod =for comment DO NOT EDIT. This Pod was generated by Swim v0.1.46. See http://github.com/ingydotnet/swim-pm#readme =encoding utf8 =head1 NAME Inline - Write Perl Subroutines in Other Programming Languages =head1 VERSION This document describes L version B<0.86>. =head1 SYNOPSIS use Inline C; print "9 + 16 = ", add(9, 16), "\n"; print "9 - 16 = ", subtract(9, 16), "\n"; __END__ __C__ int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; } =head1 DESCRIPTION The Inline module allows you to put source code from other programming languages directly "inline" in a Perl script or module. The code is automatically compiled as needed, and then loaded for immediate access from Perl. Inline saves you from the hassle of having to write and compile your own glue code using facilities like XS or SWIG. Simply type the code where you want it and run your Perl as normal. All the hairy details are handled for you. The compilation and installation of your code chunks all happen transparently; all you will notice is the delay of compilation on the first run. The Inline code only gets compiled the first time you run it (or whenever it is modified) so you only take the performance hit once. Code that is Inlined into distributed modules (like on the CPAN) will get compiled when the module is installed, so the end user will never notice the compilation time. Best of all, it works the same on both Unix and Microsoft Windows. See L for support information. =head2 Why Inline? Do you want to know "Why would I use other languages in Perl?" or "Why should I use Inline to do it?"? I'll try to answer both. =over =item Why would I use other languages in Perl? The most obvious reason is performance. For an interpreted language, Perl is very fast. Many people will say "Anything Perl can do, C can do faster". (They never mention the development time :-) Anyway, you may be able to remove a bottleneck in your Perl code by using another language, without having to write the entire program in that language. This keeps your overall development time down, because you're using Perl for all of the non-critical code. Another reason is to access functionality from existing API-s that use the language. Some of this code may only be available in binary form. But by creating small subroutines in the native language, you can "glue" existing libraries to your Perl. As a user of the CPAN, you know that code reuse is a good thing. So why throw away those Fortran libraries just yet? If you are using Inline with the C language, then you can access the full internals of Perl itself. This opens up the floodgates to both extreme power and peril. Maybe the best reason is "Because you want to!". Diversity keeps the world interesting. TMTOWTDI! =item Why should I use Inline to do it? There are already two major facilities for extending Perl with C. They are XS and SWIG. Both are similar in their capabilities, at least as far as Perl is concerned. And both of them are quite difficult to learn compared to Inline. There is a big fat learning curve involved with setting up and using the XS environment. You need to get quite intimate with the following docs: =over =item * perlxs =item * perlxstut =item * perlapi =item * perlguts =item * perlmod =item * h2xs =item * xsubpp =item * ExtUtils::MakeMaker =back With Inline you can be up and running in minutes. There is a C Cookbook with lots of short but complete programs that you can extend to your real-life problems. No need to learn about the complicated build process going on in the background. You don't even need to compile the code yourself. Inline takes care of every last detail except writing the C code. Perl programmers cannot be bothered with silly things like compiling. "Tweak, Run, Tweak, Run" is our way of life. Inline does all the dirty work for you. Another advantage of Inline is that you can use it directly in a script. You can even use it in a Perl one-liner. With XS and SWIG, you always set up an entirely separate module. Even if you only have one or two functions. Inline makes easy things easy, and hard things possible. Just like Perl. Finally, Inline supports several programming languages (not just C and C++). As of this writing, Inline has support for C, C++, Java, Python, Ruby, Tcl, Assembler, Basic, Guile, Befunge, Octave, Awk, BC, TT (Template Toolkit), WebChat and even PERL. New Inline Language Support Modules (ILSMs) are regularly being added. See L for details on how to create your own ILSM. =back =head1 USING THE INLINE.PM MODULE Inline is a little bit different than most of the Perl modules that you are used to. It doesn't import any functions into your namespace and it doesn't have any object oriented methods. Its entire interface (with two minor exceptions) is specified through the C<'use Inline ...'> command. This section will explain all of the different ways to C. If you want to begin using C with Inline immediately, see L. =head2 The Basics The most basic form for using Inline is: use Inline X => "X source code"; where 'X' is one of the supported Inline programming languages. The second parameter identifies the source code that you want to bind to Perl. The source code can be specified using any of the following syntaxes: =over =item The DATA Keyword. use Inline Java => 'DATA'; # Perl code goes here ... __DATA__ __Java__ /* Java code goes here ... */ The easiest and most visually clean way to specify your source code in an Inline Perl program is to use the special C keyword. This tells Inline to look for a special marker in your C filehandle's input stream. In this example the special marker is C<__Java__>, which is the programming language surrounded by double underscores. In case you've forgotten, the C pseudo file is comprised of all the text after the C<__END__> or C<__DATA__> section of your program. If you're working outside the C
package, you'd best use the C<__DATA__> marker or else Inline will not find your code. Using this scheme keeps your Perl code at the top, and all the ugly Java stuff down below where it belongs. This is visually clean and makes for more maintainable code. An excellent side benefit is that you don't have to escape any characters like you might in a Perl string. The source code is verbatim. For these reasons, I prefer this method the most. The only problem with this style is that since Perl can't read the C filehandle until runtime, it obviously can't bind your functions until runtime. The net effect of this is that you can't use your Inline functions as barewords (without predeclaring them) because Perl has no idea they exist during compile time. =item The FILE and BELOW keywords. use Inline::Files; use Inline Java => 'file'; # Perl code goes here ... __JAVA__ /* Java code goes here ... */ This is the newest method of specifying your source code. It makes use of the Perl module C written by Damian Conway. The basic style and meaning are the same as for the C keyword, but there are a few syntactic and semantic twists. First, you must say 'use Inline::Files' before you 'use Inline' code that needs those files. The special 'C' keyword is replaced by either 'C' or 'C'. This allows for the bad pun idiom of: use Inline C => 'below'; You can omit the C<__DATA__> tag now. Inline::Files is a source filter that will remove these sections from your program before Perl compiles it. They are then available for Inline to make use of. And since this can all be done at compile time, you don't have to worry about the caveats of the 'DATA' keyword. This module has a couple small gotchas. Since Inline::Files only recognizes file markers with capital letters, you must specify the capital form of your language name. Also, there is a startup time penalty for using a source code filter. At this point Inline::Files is alpha software and use of it is experimental. Inline's integration of this module is also fledgling at the time being. One of things I plan to do with Inline::Files is to get line number info so when an extension doesn't compile, the error messages will point to the correct source file and line number. My best advice is to use Inline::Files for testing (especially as support for it improves), but use DATA for production and distributed/CPAN code. =item Strings use Inline Java => <<'END'; /* Java code goes here ... */ END # Perl code goes here ... You also just specify the source code as a single string. A handy way to write the string is to use Perl's "here document" style of quoting. This is ok for small functions but can get unwieldy in the large. On the other hand, the string variant probably has the least startup penalty and all functions are bound at compile time. If you wish to put the string into a scalar variable, please be aware that the C statement is a compile time directive. As such, all the variables it uses must also be set at compile time, C the 'use Inline' statement. Here is one way to do it: my $code; BEGIN { $code = < $code; # Perl code goes here ... =item The bind() Function An alternative to using the BEGIN block method is to specify the source code at run time using the 'Inline->bind()' method. (This is one of the interface exceptions mentioned above) The C method takes the same arguments as C<'use Inline ...'>. my $code = <bind(Java => $code); You can think of C as a way to C code in other programming languages. Although bind() is a powerful feature, it is not recommended for use in Inline based modules. In fact, it won't work at all for installable modules. See instructions below for creating modules with Inline. =item Other Methods The source code for Inline can also be specified as an external filename, a reference to a subroutine that returns source code, or a reference to an array that contains lines of source code. (Note that if the external source file is in the current directory it must be specified with a leading '.I<' - ie '.>file.ext' instead of simply 'file.ext'.) These methods are less frequently used but may be useful in some situations. For instance, to load your C++ code from a file named the same as your perl module with a swapped file extension, you can use: use Inline CPP => (__FILE__ =~ s/\.pm$/.cpp/r); =item Shorthand If you are using the 'DATA' or 'file' methods described above B there are no extra parameters, you can omit the keyword altogether. For example: use Inline 'Java'; # Perl code goes here ... __DATA__ __Java__ /* Java code goes here ... */ or use Inline::Files; use Inline 'Java'; # Perl code goes here ... __JAVA__ /* Java code goes here ... */ =back =head2 More about the DATA Section If you are writing a module, you can also use the DATA section for POD and AutoLoader subroutines. Just be sure to put them before the first Inline marker. If you install the helper module C, you can even use POD inside your Inline code. You just have to specify a filter to strip it out. You can also specify multiple Inline sections, possibly in different programming languages. Here is another example: # The module Foo.pm package Foo; use AutoLoader; use Inline C; use Inline C => DATA => filters => 'Strip_POD'; use Inline Python; 1; __DATA__ sub marine { # This is an autoloaded subroutine } =head1 External subroutines =cut __C__ /* First C section */ __C__ /* Second C section */ =head1 My C Function Some POD doc. =cut __Python__ """A Python Section""" An important thing to remember is that you need to have one C<< use Inline Foo => 'DATA' >> for each C<__Foo__> marker, and they must be in the same order. This allows you to apply different configuration options to each section. =head2 Configuration Options Inline tries to do the right thing as often as possible. But sometimes you may need to override the default actions. This is easy to do. Simply list the Inline configuration options after the regular Inline parameters. All configuration options are specified as (key, value) pairs. use Inline (C => 'DATA', directory => './inline_dir', libs => '-lfoo', inc => '-I/foo/include', prefix => 'XXX_', warnings => 0, ); You can also specify the configuration options on a separate Inline call like this: use Inline (C => Config => directory => './inline_dir', libs => '-lfoo', inc => '-I/foo/include', prefix => 'XXX_', warnings => 0, ); use Inline C => <<'END_OF_C_CODE'; The special keyword C<'Config'> tells Inline that this is a configuration-only call. No source code will be compiled or bound to Perl. If you want to specify global configuration options that don't apply to a particular language, just leave the language out of the call. Like this: use Inline Config => warnings => 0; The Config options are inherited and additive. You can use as many Config calls as you want. And you can apply different options to different code sections. When a source code section is passed in, Inline will apply whichever options have been specified up to that point. Here is a complex configuration example: use Inline (Config => directory => './inline_dir', ); use Inline (C => Config => libs => '-lglobal', ); use Inline (C => 'DATA', # First C Section libs => ['-llocal1', '-llocal2'], ); use Inline (Config => warnings => 0, ); use Inline (Python => 'DATA', # First Python Section libs => '-lmypython1', ); use Inline (C => 'DATA', # Second C Section libs => [undef, '-llocal3'], ); The first C applies to all subsequent calls. The second C applies to all subsequent C sections (but not C sections). In the first C section, the external libraries C, C and C are used. (Most options allow either string or array ref forms, and do the right thing.) The C section does not use the C library, but does use the same C, and has warnings turned off. The second C section only uses the C library. That's because a value of C resets the additive behavior. The C and C options are generic Inline options. All other options are language specific. To find out what the C options do, see C. =head2 On and Off If a particular config option has value options of 1 and 0, you can use the 'enable' and 'disable' modifiers. In other words, this: use Inline Config => force_build => 1, clean_after_build => 0; could be reworded as: use Inline Config => enable => force_build => disable => clean_after_build; =head2 Playing 'with' Others Inline has a special configuration syntax that tells it to get more configuration options from other Perl modules. Here is an example: use Inline with => 'Event'; This tells Inline to load the module C and ask it for configuration information. Since C has a C API of its own, it can pass Inline all of the information it needs to be able to use C C callbacks seamlessly. That means that you don't need to specify the typemaps, shared libraries, include files and other information required to get this to work. You can specify a single module or a list of them. Like: use Inline with => qw(Event Foo Bar); Currently, modules that works I Inline include C, C, and those that use C. In order to make B module work I Inline in this way, your module needs to provide a class method called C that takes an Inline language as a parameter (e.g. "C"), and returns a reference to a hash with configuration information that is acceptable to the relevant ILSM. For C, see L. E.g.: my $confighashref = Event->Inline('C'); # only supports C in 1.21 # hashref contains keys INC, TYPEMAPS, MYEXTLIB, AUTO_INCLUDE, BOOT If your module uses L version 0.400 or higher, your module only needs this: package Module; use autouse Module::Install::Files => qw(Inline); =head2 Inline Shortcuts Inline lets you set many configuration options from the command line. These options are called 'shortcuts'. They can be very handy, especially when you only want to set the options temporarily, for say, debugging. For instance, to get some general information about your Inline code in the script C, use the command: perl -MInline=info Foo.pl If you want to force your code to compile, even if its already done, use: perl -MInline=force Foo.pl If you want to do both, use: perl -MInline=info -MInline=force Foo.pl or better yet: perl -MInline=info,force Foo.pl =head2 The Inline 'directory' Inline needs a place to build your code and to install the results of the build. It uses a single directory named C<'.Inline/'> under normal circumstances. If you create this directory in your home directory, the current directory or in the directory where your program resides, Inline will find and use it. You can also specify it in the environment variable C or directly in your program, by using the C keyword option. If Inline cannot find the directory in any of these places it will create a C<'_Inline/'> directory in either your current directory or the directory where your script resides. One of the key factors to using Inline successfully, is understanding this directory. When developing code it is usually best to create this directory (or let Inline do it) in your current directory. Remember that there is nothing sacred about this directory except that it holds your compiled code. Feel free to delete it at any time. Inline will simply start from scratch and recompile your code on the next run. If you have several programs that you want to force to recompile, just delete your C<'.Inline/'> directory. It is probably best to have a separate C<'.Inline/'> directory for each project that you are working on. You may want to keep stable code in the <.Inline/> in your home directory. On multi-user systems, each user should have their own C<'.Inline/'> directories. It could be a security risk to put the directory in a shared place like C. =head2 Debugging Inline Errors All programmers make mistakes. When you make a mistake with Inline, like writing bad C code, you'll get a big error report on your screen. This report tells you where to look to do the debugging. Some languages may also dump out the error messages generated from the build. When Inline needs to build something it creates a subdirectory under your C directory. This is where it writes all the components it needs to build your extension. Things like XS files, Makefiles and output log files. If everything goes OK, Inline will delete this subdirectory. If there is an error, Inline will leave the directory intact and print its location. The idea is that you are supposed to go into that directory and figure out what happened. Read the doc for your particular Inline Language Support Module for more information. =head2 The 'config' Registry File Inline keeps a cached file of all of the Inline Language Support Module's meta data in a file called C. This file can be found in your C directory. If the file does not exist, Inline creates a new one. It will search your system for any module beginning with C. It will then call that module's C method to get useful information for future invocations. Whenever you add a new ILSM, you should delete this file so that Inline will auto-discover your newly installed language module. (This should no longer be necessary as of Inline-0.49.) =head1 CONFIGURATION OPTIONS This section lists all of the generic Inline configuration options. For language specific configuration, see the doc for that language. =over =item C The C config option is the directory that Inline uses to both build and install an extension. Normally Inline will search in a bunch of known places for a directory called C<'.Inline/'>. Failing that, it will create a directory called C<'_Inline/'> If you want to specify your own directory, use this configuration option. Note that you must create the C directory yourself. Inline will not do it for you. =item C You can use this option to set the name of your Inline extension object module. For example: use Inline C => 'DATA', name => 'Foo::Bar'; would cause your C code to be compiled in to the object: lib/auto/Foo/Bar/Bar.so lib/auto/Foo/Bar/Bar.inl (The .inl component contains dependency information to make sure the source code is in sync with the executable) If you don't use C, Inline will pick a name for you based on your program name or package name. In this case, Inline will also enable the C option which mangles in a small piece of the MD5 fingerprint into your object name, to make it unique. =item C This option is enabled whenever the C parameter is not specified. To disable it say: use Inline C => 'DATA', disable => 'autoname'; C mangles in enough of the MD5 fingerprint to make your module name unique. Objects created with C will never get replaced. That also means they will never get cleaned up automatically. C is very useful for small throw away scripts. For more serious things, always use the C option. =item C Specifies the version number of the Inline extension object. It is used B for modules, and it must match the global variable $VERSION. Additionally, this option should used if (and only if) a module is being set up to be installed permanently into the Perl sitelib tree using Inline::MakeMaker (NOT used by Inline::Module). Inline will croak if you use it otherwise. The presence of the C parameter is the official way to let Inline know that your code is an installable/installed module. Inline will never generate an object in the temporary cache (C<_Inline/> directory) if C is set. It will also never try to recompile a module that was installed into someone's Perl site tree. So the basic rule is develop without C, and deliver with C. =item C C can also be used as a configuration option instead of using the special 'with' syntax. Do this if you want to use different sections of Inline code I different modules. (Probably a very rare usage) use Event; use Inline C => DATA => with => 'Event'; Modules specified using the config form of C will B be automatically required. You must C them yourself. =item C You can override modules that get used by ILSMs with the C option. This is typically used to override the default parser for L, but might be used by any ILSM for any purpose. use Inline config => using => '::Parser::RecDescent'; use Inline C => '...'; This would tell L to use L. =item C This option is for compiled languages only. It tells Inline to tell DynaLoader to load an object file in such a way that its symbols can be dynamically resolved by other object files. May not work on all platforms. See the C shortcut below. =item C You can use this option whenever you use Perl's C<-T> switch, for taint checking. This option tells Inline to blindly untaint all tainted variables. (This is generally considered to be an appallingly insecure thing to do, and not to be recommended - but the option is there for you to use if you want. Please consider using something other than Inline for scripts that need taint checking.) It also turns on C by default. See the C shortcut below. You will see warnings about blindly untainting fields in both %ENV and Inline objects. If you want to silence these warnings, set the Config option C => 1. There can be some problems untainting Inline scripts where older versions of Cwd, such as those that shipped with early versions of perl-5.8 (and earlier), are installed. Updating Cwd will probably solve these problems. =item safemode Perform extra safety checking, in an attempt to thwart malicious code. This option cannot guarantee security, but it does turn on all the currently implemented checks. (Currently, the only "currently implemented check" is to ensure that the C option has also been used.) There is a slight startup penalty by using C. Also, using C automatically turns this option on. If you need your code to start faster under C<-T> (taint) checking, you'll need to turn this option off manually. Only do this if you are not worried about security risks. See the C shortcut below. =item C Makes Inline build (compile) the source code every time the program is run. The default is 0. See the C shortcut below. =item C Tells ILSMs that they should dump build messages to the terminal rather than be silent about all the build details. =item C Tells ILSMs to print timing information about how long each build phase took. Usually requires C. =item C Tells Inline to clean up the current build area if the build was successful. Sometimes you want to C this for debugging. Default is 1. See the C shortcut below. =item C Tells Inline to clean up the old build areas within the entire Inline C. Default is 0. See the C shortcut below. =item C Tells Inline to print various information about the source code. Default is 0. See the C shortcut below. =item C Tells Inline to print version info about itself. Default is 0. See the C shortcut below. =item C Puts Inline into 'reportbug' mode, which is what you want if you desire to report a bug. =item C Default is 0, but setting C<< rewrite_config_file => 1 >> will mean that the existing configuration file in the Inline C will be overwritten. (This is useful if the existing config file is not up to date as regards supported languages.) =item C This option tells Inline whether to print certain warnings. Default is 1. =back =head1 INLINE CONFIGURATION SHORTCUTS This is a list of all the shortcut configuration options currently available for Inline. Specify them from the command line when running Inline scripts. perl -MInline=noclean inline_script.pl or perl -MInline=info,force,noclean inline_script.pl You can specify multiple shortcuts separated by commas. They are not case sensitive. You can also specify shortcuts inside the Inline program like this: use Inline 'info', 'force', 'noclean'; NOTE: If a C<'use Inline'> statement is used to set shortcuts, it can not be used for additional purposes. =over =item C Tells Inline to remove any build directories that may be lying around in your build area. Normally these directories get removed immediately after a successful build. Exceptions are when the build fails, or when you use the C or C options. =item C Forces the code to be recompiled, even if everything is up to date. =item C Turns on the C option. =item C This is a very useful option when you want to know what's going on under the hood. It tells Inline to print helpful information to C. Among the things that get printed is a list of which Inline functions were successfully bound to Perl. =item C Tells Inline to leave the build files after compiling. =item C Use the C option to print messages during a build. =item C Puts Inline into C mode, which does special processing when you want to report a bug. C also automatically forces a build, and doesn't clean up afterwards. This is so that you can tar and mail the build directory to me. C will print exact instructions on what to do. Please read and follow them carefully. NOTE: C informs you to use the tar command. If your system does not have tar, please use the equivalent C command. =item C Turns C on. C will turn this on automatically. While this mode performs extra security checking, it does not guarantee safety. =item C This parameter used to be used for creating installable Inline modules. It has been removed from Inline altogether and replaced with a much simpler and more powerful mechanism, C. See the section below on how to create modules with Inline. =item C<_testing> Used internally by CI09parser.t and CI10callback.t(in the Inline::C test suite). Setting this option with Inline::C will mean that files named C and C are created in the C<./Inline_test> directory, creating that directory if it doesn't already exist. The files (but not the C<./Inline_test directory>) are cleaned up by calling C. Also used by C to trigger a warning. =item C Turn on C to get extra diagnostic info about builds. =item C Turns C off. Use this in combination with C for slightly faster startup time under C<-T>. Only use this if you are sure the environment is safe. =item C Turn the C option on. Used with C<-T> switch. In terms of secure practices, this is definitely B a recommended way of dealing with taint checking, but it's the B option currently available with Inline. Use it at your own risk. =item C Tells Inline to report its release version. =back =head1 WRITING MODULES WITH INLINE The current preferred way to author CPAN modules with Inline is to use Inline::Module (distributed separately). Inline ships with Inline::MakeMaker, which helps you set up a Makefile.PL that invokes Inline at install time to compile all the code before it gets installed, but the resulting module still depends on Inline and the language support module like Inline::C. In order to avoid this dependency, what you really want to do is convert your distribution to plain XS before uploading it to CPAN. Inline::Module fills that role, and also integrates well with more modern authoring tools. See Inline::Module for details on that approach, or continue reading below for the older Inline::MakeMaker technique. Let's say that you wanted to write a module called C. Start by using the following command: h2xs -PAXn Math::Simple This will generate a bunch of files that form a skeleton of what you need for a distributable module. (Read the h2xs manpage to find out what the options do) Next, modify the C file to look like this: package Math::Simple; $VERSION = '1.23'; use base 'Exporter'; @EXPORT_OK = qw(add subtract); use strict; use Inline C => 'DATA', version => '1.23', name => 'Math::Simple'; # The following Inline->init() call is optional - see below for more info. #Inline->init(); 1; __DATA__ =pod =cut __C__ int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; } The important things to note here are that you B specify a C and C parameter. The C must match your module's package name. The C parameter must match your module's C<$VERSION> variable and they must be considered valid by C. NOTE: These are Inline's sanity checks to make sure you know what you're doing before uploading your code to CPAN. They insure that once the module has been installed on someone's system, the module would not get automatically recompiled for any reason. This makes Inline based modules work in exactly the same manner as XS based ones. Finally, you need to modify the Makefile.PL. Simply change: use ExtUtils::MakeMaker; to use Inline::MakeMaker; And, in order that the module build work correctly in the cpan shell, add the following directive to the Makefile.PL's WriteMakefile(): CONFIGURE_REQUIRES => { 'Inline::MakeMaker' => 0.45, 'ExtUtils::MakeMaker' => 6.52, }, This C directive ensures that the cpan shell will install Inline on the user's machine (if it's not already present) before building your Inline-based module. Specifying of "ExtUtils::MakeMaker => 6.52," is optional, and can be omitted if you like. It ensures only that some harmless warnings relating to the C directive won't be emitted during the building of the module. It also means, of course, that ExtUtils::Makemaker will first be updated on the user's machine unless the user already has version 6.52 or later. If the "Inline->init();" is not done then, having installed Math::Simple, a warning that "One or more DATA sections were not processed by Inline" will appear when (and only when) Math::Simple is loaded by a "require call. It's a harmless warning - and if you're prepared to live with it, then there's no need to make the "Inline->init();" call. When the person installing C does a "C", the generated Makefile will invoke Inline in such a way that the C code will be compiled and the executable code will be placed into the C<./blib> directory. Then when a "C" is done, the module will be copied into the appropriate Perl sitelib directory (which is where an installed module should go). Now all you need to do is: perl Makefile.PL make dist That will generate the file C which is a distributable package. (It will also generate some harmless warnings in relation to C unless the version of your ExtUtils::MakeMaker is 6.52 or later.) That's all there is to it. B: Although the above steps will produce a workable module, you still have a few more responsibilities as a budding new CPAN author. You need to write lots of documentation and write lots of tests. Take a look at some of the better CPAN modules for ideas on creating a killer test harness. Actually, don't listen to me, go read these: =over =item * perldoc perlnewmod =item * L =item * L =back =head1 HOW INLINE WORKS In reality, Inline just automates everything you would need to do if you were going to do it by hand (using XS, etc). Inline performs the following steps: =over =item * Receive the Source Code Inline gets the source code from your script or module with a statements like the following: use Inline C => "Source-Code"; or use Inline; bind Inline C => "Source-Code"; where C is the programming language of the source code, and C is a string, a file name, an array reference, or the special C<'DATA'> keyword. Since Inline is coded in a "C" statement, everything is done during Perl's compile time. If anything needs to be done that will affect the C, it needs to be done in a C block that is I the "C" statement. If you really need to specify code to Inline at runtime, you can use the C method. Source code that is stowed in the C<'DATA'> section of your code, is read in by an C subroutine in Inline. That's because the C filehandle is not available at compile time. =item * Check if the Source Code has been Built Inline only needs to build the source code if it has not yet been built. It accomplishes this seemingly magical task in an extremely simple and straightforward manner. It runs the source text through the C module to produce a 128-bit "fingerprint" which is virtually unique. The fingerprint along with a bunch of other contingency information is stored in a C<.inl> file that sits next to your executable object. For instance, the C code from a script called C might create these files: example_pl_3a9a.so example_pl_3a9a.inl If all the contingency information matches the values stored in the C<.inl> file, then proceed to step 8. (No compilation is necessary) =item * Find a Place to Build and Install At this point Inline knows it needs to build the source code. The first thing to figure out is where to create the great big mess associated with compilation, and where to put the object when it's done. By default Inline will try to build and install under the first place that meets one of the following conditions: =over =item 1. The DIRECTORY= config option; if specified =item 2. The C environment variable; if set =item 3. C<.Inline/> (in current directory); if exists and C<$PWD != $HOME> =item 4. binI<.Inline> (in directory of your script); if exists =item 5. C<~/.Inline/> - if exists =item 6. C<./_Inline/> - if exists =item 7. C - if exists =item 8. Create C<./_Inline/> - if possible =item 9. Create C - if possible =back Failing that, Inline will croak. This is rare and easily remedied by just making a directory that Inline will use. If the C Environment Variable has been set, you will need to make special provision for that if the 'make install' phase of your Inline scripts are to succeed. If the module option is being compiled for permanent installation, then Inline will only use C<./_Inline/> to build in, and the C<$Config{installsitearch}> directory to install the executable in. This action is caused by Inline::MakeMaker, and is intended to be used in modules that are to be distributed on the CPAN, so that they get installed in the proper place. =item * Parse the Source for Semantic Cues Inline::C uses the module C to parse through your chunks of C source code and look for things that it can create run-time bindings to. In C it looks for all of the function definitions and breaks them down into names and data types. These elements are used to correctly bind the C function to a C subroutine. Other Inline languages like Python and Java actually use the C and C modules to parse the Inline code. =item * Create the Build Environment Now Inline can take all of the gathered information and create an environment to build your source code into an executable. Without going into all the details, it just creates the appropriate directories, creates the appropriate source files including an XS file (for C) and a C. =item * Build the Code and Install the Executable The planets are in alignment. Now for the easy part. Inline just does what you would do to install a module. "`perl Makefile.PL && make && make test && make install>". If something goes awry, Inline will croak with a message indicating where to look for more info. =item * Tidy Up By default, Inline will remove all of the mess created by the build process, assuming that everything worked. If the build fails, Inline will leave everything intact, so that you can debug your errors. Setting the C shortcut option will also stop Inline from cleaning up. =item * DynaLoad the Executable For C (and C++), Inline uses the C method to pull your external module into C space. Now you can call all of your external functions like Perl subroutines. Other languages like Python and Java, provide their own loaders. =back =head1 SEE ALSO For information about using Inline with C see L. For sample programs using Inline with C see L. For "Formerly Answered Questions" about Inline, see L. For information on supported languages and platforms see L. For information on writing your own Inline Language Support Module, see L. Inline's mailing list is inline@perl.org To subscribe, send email to inline-subscribe@perl.org =head1 BUGS AND DEFICIENCIES When reporting a bug, please do the following: =over =item * Put "use Inline 'reportbug';" at the top of your code, or use the command line option "perl -MInline=reportbug ...". =item * Run your code. =item * Follow the printed directions. =back =head1 AUTHOR Ingy döt Net Sisyphus fixed some bugs and is current co-maintainer. =head1 COPYRIGHT =over =item * Copyright 2000-2019. Ingy döt Net. =item * Copyright 2008, 2010-2014. Sisyphus. =back This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L =cut 09perl5lib.t100644001750001750 52513605534015 14350 0ustar00ingyingy000000000000Inline-0.86/t#!inc/bin/testml-cpan *perl.derive-minus-i(*paths) == *paths :"Test Inline->derive_minus_I -- +" === TEST 1 - No settings --- perl --- paths === TEST 2 - Add relative paths to @INC --- perl push @INC, qw(doc eg); --- paths doc eg === TEST 3 - Non-existing paths are removed --- perl push @INC, qw(foo doc bar eg baz); --- ^paths Inline000755001750001750 013605534015 13673 5ustar00ingyingy000000000000Inline-0.86/libFoo.pm100644001750001750 360113605534015 15114 0ustar00ingyingy000000000000Inline-0.86/lib/Inlineuse strict; package Inline::Foo; require Inline; our @ISA = qw(Inline); our $VERSION = '0.86'; use Carp; use File::Spec; sub register { return { language => 'Foo', aliases => ['foo'], type => 'interpreted', suffix => 'foo', }; } sub usage_config { my $key = shift; "'$key' is not a valid config option for Inline::Foo\n"; } sub usage_config_bar { "Invalid value for Inline::Foo config option BAR"; } sub validate { my $o = shift; $o->{ILSM}{PATTERN} ||= 'foo-'; $o->{ILSM}{BAR} ||= 0; while (@_) { my ($key, $value) = splice @_, 0, 2; if ($key eq 'PATTERN') { $o->{ILSM}{PATTERN} = $value; next; } if ($key eq 'BAR') { croak usage_config_bar unless $value =~ /^[01]$/; $o->{ILSM}{BAR} = $value; next; } croak usage_config($key); } } sub build { my $o = shift; my $code = $o->{API}{code}; my $pattern = $o->{ILSM}{PATTERN}; $code =~ s/$pattern//g; $code =~ s/bar-//g if $o->{ILSM}{BAR}; { package Foo::Tester; our $VERSION = '0.02'; eval $code; } croak "Foo build failed:\n$@" if $@; my $path = File::Spec->catdir($o->{API}{install_lib},'auto',$o->{API}{modpname}); my $obj = $o->{API}{location}; $o->mkpath($path) unless -d $path; open FOO_OBJ, "> $obj" or croak "Can't open $obj for output\n$!"; binmode(FOO_OBJ, ':utf8'); print FOO_OBJ $code; close \*FOO_OBJ; } sub load { my $o = shift; my $obj = $o->{API}{location}; open FOO_OBJ, "< $obj" or croak "Can't open $obj for output\n$!"; binmode(FOO_OBJ, ':utf8'); my $code = join '', ; close \*FOO_OBJ; eval "package $o->{API}{pkg};\n$code"; croak "Unable to load Foo module $obj:\n$@" if $@; } sub info { my $o = shift; } 1; xt000755001750001750 013605534015 12342 5ustar00ingyingy000000000000Inline-0.86ilsm-test.bash100755001750001750 214413605534015 15266 0ustar00ingyingy000000000000Inline-0.86/xt#!/usr/bin/env bash set -e export PERL5LIB=$PWD/lib ILSM=( ingydotnet/inline-c-pm daoswald/Inline-CPP ) main() { for repo in ${ILSM[@]}; do echo "Testing '$repo'" check-repo || continue ( set -x cd "$repo_path" if [ -e Meta ]; then make test make cpantest make disttest else perl Makefile.PL < /dev/null make test make purge fi ) done echo "All ILSM tests passed!" } check-repo() { repo_path="test/devel/repo/${repo#*/}" if [ ! -e "$repo_path" ]; then mkdir -p test/devel git clone "git@github.com:$repo" "$repo_path" else ( set -x cd "$repo_path" branch="$(git rev-parse --abbrev-ref HEAD)" if [ "$branch" != master ]; then echo "Repo '$repo_path' is not on master" fi git reset --hard git clean -fxd if [ -n "$(git status -s)" ]; then die "Repo '$repo_path' is not clean" fi git pull --rebase origin master ) || return 1 fi return 0 } die() { echo "$@" exit 1 } [ "$BASH_SOURCE" == "$0" ] && main "$@" : TestMLBridge.pm100644001750001750 104213605534015 15132 0ustar00ingyingy000000000000Inline-0.86/tuse strict; use warnings; package TestMLBridge; use base 'TestML::Bridge'; use Inline; use File::Spec::Functions qw(abs2rel catdir); sub derive_minus_i { my ($self, $perl, $paths) = @_; mkdir 'doc'; mkdir 'eg'; local @INC = @INC; eval $perl; my @got = map abs2rel($_), Inline->derive_minus_I; my $out = ''; for my $path (split /\n/, $paths) { $out .= "$path\n" if grep { $path eq $_ } @got; } return $out; } sub eval_catch { my ($self, $perl) = @_; eval $perl; return $@; } 1; FAQ.pod100644001750001750 1763113605534015 15176 0ustar00ingyingy000000000000Inline-0.86/lib/Inline=pod =for comment DO NOT EDIT. This Pod was generated by Swim v0.1.46. See http://github.com/ingydotnet/swim-pm#readme =encoding utf8 =head1 NAME Inline-FAQ - The Inline FAQ =head1 DESCRIPTION Welcome to the official Inline FAQ. In this case, B means: B This is a collection of old, long-winded emails that myself and others have sent to the Inline mailing list. (inline@perl.org) They have been reviewed and edited for general Inline edification. Some of them may be related to a specific language. They are presented here in a traditional FAQ layout. =head1 GENERAL INLINE Since there is only a handful of content so far, all FAQs are currently under this heading. =head2 How disposable is a C<.Inline> or C<_Inline> directory? I probably need to be more emphatic about the role of C<_Inline/> cache directories. Since they are created automatically, they are completely disposable. I delete them all the time. And it is fine to have a different one for each project. In fact as long as you don't have C<~/.Inline/> defined, Inline will create a new C<./_Inline> directory (unless, you've done something to override this automatic process - such as using the DIRECTORY config option, or using the C environment variable). You can move that to C<./.Inline> and it will continue to work if you want togive it more longevity and hide it from view. There is a long complicated list of rules about how C<[_.]Inline/> directories are used/created. But it was designed to give you the most flexibility/ease-of-use. Never be afraid to nuke 'em. They'll just pop right back next time they're needed. :) =head2 What is the best way to package Inline code for CPAN? This distribution includes Inline::MakeMaker, described below, which takes special steps during the installation of your module to make sure the code gets compiled and installed, rather than compiled by users at runtime. But, users of your module need to install Inline and the language support module like Inline::CPP as prerequisites for your module. A better way to distribute your module is with Inline::Module, which takes special steps to remove dependencies on Inline::* and convert it to a plain XS module during the construction of your distribution before you upload it to CPAN. It also integrates easily with Dist::Zilla and other modern authoring tools for a more streamlined authoring experience. =head2 Whatever happened to the C option? C is gone. I was going to leave it in and change the semantics, but thought it better to remove it, so people wouldn't try to use it the old way. There is now C<_INSTALL_> (but you're not supposed to know that :). It works magically through the use of Inline::MakeMaker. I explained this earlier but it's worth going through again because it's the biggest change for 0.40. Here's how to 'permanently' install an Inline extension (Inline based module) with 0.40: =over =item 1. Create a module with Inline. =item 2. Test it using the normal / local C<_Inline/> cache. =item 3. Create a Makefile.PL (like the one produced by h2xs) =item 4. Change 'use ExtUtils::MakeMaker' to 'use Inline::MakeMaker' =item 5. In the Makefile.PL's WriteMakefile() insert: CONFIGURE_REQUIRES => { 'Inline::MakeMaker' => 0.45, 'ExtUtils::MakeMaker' => 6.52, }, (See the "Writing Modules with Inline" section of Inline.pod for an explanation / elaboration.) =item 6. Change your 'use Inline C => DATA' to 'use Inline C => DATA => NAME => Foo =back => VERSION => 1.23' + Make sure NAME matches your package name ('Foo'), or => begins with 'Foo::'. + If you want to quiet a harmless warning that will => appear when the module is loaded via "require", do "Inline->init();". See => "Writing Modules with Inline" in the Inline pod for details. + Make sure => VERSION matches $Foo::VERSION. This must be a string (not a number) => matching C + Do the perl / make / test / install dance => (thanks binkley :) With Inline 0.41 (or thereabouts) you can skip steps 3 & 4, and just say C. This will work for non-Inline modules too. It will become the defacto standard (since there is no easy standard) way of installing a Perl module. It will allow Makefile.PL parameters C and things like that. It will also make use of a MANIFEST if you provide one. =head2 How do I create a binary distribution using Inline? I've figured out how to create and install a PPM binary distribution; with or without distributing the C code! And I've decided to share it with all of you :) NOTE: Future versions of Inline will make this process a one line command. But for now just use this simple recipe. The Inline 0.40 distribution comes with a sample extension module called Math::Simple. Theoretically you could distribute this module on CPAN. It has all the necessary support for installation. You can find it in C. Here are the steps for converting this into a binary distribution B C source code. NOTE: The recipient of this binary distribution will need to have the PPM.pm module installed. This module requires a lot of other CPAN modules. ActivePerl (available for Win32, Linux, and Solaris) has all of these bundled. While ActivePerl isn't required, it makes things (a lot) easier. =over =item 1. cd C =item 2. Divide Simple.pm into two files: ---8<--- (Simple.pm) package Math::Simple; use strict; require Exporter; @Math::Simple::ISA = qw(Exporter); @Math::Simple::EXPORT = qw(add subtract); $Math::Simple::VERSION = '1.23'; use Inline (C => 'src/Simple.c' => NAME => 'Math::Simple', VERSION => '1.23', ); 1; ---8<--- ---8<--- (src/Simple.c) int add (int x, int y) { return x + y; } int subtract (int x, int y) { return x - y; } ---8<--- =item 3. now you have the Perl in one file and the C in the other. The C code must be =back in a subdirectory. + Note that I also changed the term 'DATA' to the name of the C file. This will work just as if the C were still inline. + Run 'perl Makefile.PL' + Run 'make test' + Get the MD5 key from C + Edit C. Change C to C<02c61710cab5b659efc343a9a830aa73> (the MD5 key) =over =item 1. Run 'make ppd' =item 2. Edit 'Math-Simple.ppd'. Fill in AUTHOR and ABSTRACT if you wish. Then =back change: to =over =item 1. Run: tar cvf Math-Simple.tar blib gzip --best Math-Simple.tar =item 2. Run: tar cvf Math-Simple-1.23.tar Math-Simple.ppd Math-Simple.tar.gz gzip --best Math-Simple-1.23.tar =item 3. Distribute Math-Simple-1.23.tar.gz with the following instructions: =over =item 1. Run: gzip -d Math-Simple-1.23.tar.gz tar xvzf Math-Simple-1.23.tar =item 2. Run 'ppm install Math-Simple.ppd' =item 3. Delete Math-Simple.tar and Math-Simple.ppd. =item 4. Test with: perl -MMath::Simple -le 'print add(37, 42)' =back =back That's it. The process should also work with zip instead of tar, but I haven't tried it. The recipient of the binary must have Perl built with a matching architecture. Luckily, ppm will catch this. For a binary dist B C source code, simply omit steps 2, 3, 6, and 7. If this seems too hard, then in a future version you should be able to just type: make ppm =head2 Why does C fail on Cygwin ? It doesn't always fail on Cygwin, but if you find that it produces "unable to remap .... to same address as parent" errors during the build phase, then it's time for you to run rebaseall. See L and, if needed, seek further help from the Cygwin mailing list. =cut API.pod100644001750001750 3274413605534015 15202 0ustar00ingyingy000000000000Inline-0.86/lib/Inline=pod =for comment DO NOT EDIT. This Pod was generated by Swim v0.1.46. See http://github.com/ingydotnet/swim-pm#readme =encoding utf8 =head1 NAME Inline-API - How to bind a programming language to Perl using Inline.pm =head1 SYNOPSIS #!/usr/bin/perl use Inline Foo; say_it('foo'); # Use Foo to print "Hello, Foo" __Foo__ foo-sub say_it { foo-my $foo = foo-shift; foo-print "Hello, $foo\n"; } =head1 DESCRIPTION So you think Inline C is pretty cool, but what you really need is for Perl to work with the brand new programming language "Foo". Well you're in luck. C has support for adding your own Inline Language Support Module (B), like C. Inline has always been intended to work with lots of different programming languages. Many of the details can be shared between implementations, so that C has a similar interface to C. All of the common code is in C. Language specific modules like C are subclasses of C. They can inherit as much of the common behaviour as they want, and provide specific behaviour of their own. This usually comes in the form of Configuration Options and language specific compilation. The Inline C support is probably the best boilerplate to copy from. Since version 0.30 all C support was isolated into the module C and the parsing grammar is further broken out into C. All of these components come with the Inline distribution. This POD gives you all the details you need for implementing an ILSM. For further assistance, contact inline@perl.org See ["SEE ALSO"] below. We'll examine the joke language Inline::Foo which is distributed with Inline. It actually is a full functioning ILSM. I use it in Inline's test harness to test base Inline functionality. It is very short, and can help you get your head wrapped around the Inline API. =head1 A SKELETON For the remainder of this tutorial, let's assume we're writing an ILSM for the ficticious language C. We'll call it C. Here is the entire (working) implementation. package Inline::Foo; use strict; $Inline::Foo::VERSION = '0.01'; @Inline::Foo::ISA = qw(Inline); require Inline; use Carp; #=========================================================== # Register Foo as an Inline Language Support Module (ILSM) #=========================================================== sub register { return { language => 'Foo', aliases => ['foo'], type => 'interpreted', suffix => 'foo', }; } #=========================================================== # Error messages #=========================================================== sub usage_config { my ($key) = @_; "'$key' is not a valid config option for Inline::Foo\n"; } sub usage_config_bar { "Invalid value for Inline::Foo config option BAR"; } #=========================================================== # Validate the Foo Config Options #=========================================================== sub validate { my $o = shift; $o->{ILSM}{PATTERN} ||= 'foo-'; $o->{ILSM}{BAR} ||= 0; while (@_) { my ($key, $value) = splice @_, 0, 2; if ($key eq 'PATTERN') { $o->{ILSM}{PATTERN} = $value; next; } if ($key eq 'BAR') { croak usage_config_bar unless $value =~ /^[01]$/; $o->{ILSM}{BAR} = $value; next; } croak usage_config($key); } } #=========================================================== # Parse and compile Foo code #=========================================================== sub build { my $o = shift; my $code = $o->{API}{code}; my $pattern = $o->{ILSM}{PATTERN}; $code =~ s/$pattern//g; $code =~ s/bar-//g if $o->{ILSM}{BAR}; sleep 1; # imitate compile delay { package Foo::Tester; eval $code; } croak "Foo build failed:\n$@" if $@; my $path = "$o->{API}{install_lib}/auto/$o->{API}{modpname}"; my $obj = $o->{API}{location}; $o->mkpath($path) unless -d $path; open FOO_OBJ, "> $obj" or croak "Can't open $obj for output\n$!"; print FOO_OBJ $code; close \*FOO_OBJ; } #=========================================================== # Only needed for interpreted languages #=========================================================== sub load { my $o = shift; my $obj = $o->{API}{location}; open FOO_OBJ, "< $obj" or croak "Can't open $obj for output\n$!"; my $code = join '', ; close \*FOO_OBJ; eval "package $o->{API}{pkg};\n$code"; croak "Unable to load Foo module $obj:\n$@" if $@; } #=========================================================== # Return a small report about the Foo code. #=========================================================== sub info { my $o = shift; my $text = <<'END'; This is a small report about the Foo code. Perhaps it contains information about the functions the parser found which will be bound to Perl. It will get included in the text produced by the Inline 'INFO' command. END return $text; } 1; Except for C, the subroutines in this code are mandatory for an ILSM. What they do is described below. A few things to note: =over =item * C must be a subclass of Inline. This is accomplished with: @Inline::Foo::ISA = qw(Inline); =item * The line 'C' is not necessary. But it is there to remind you not to say 'C'. This will not work. =item * Remember, it is not valid for a user to say: use Inline::Foo; C will detect such usage for you in its C method, which is automatically inherited since C is a subclass. =item * In the build function, you normally need to parse your source code. Inline::C uses Parse::RecDescent to do this. Inline::Foo simply uses eval. (After we strip out all occurrences of 'foo-'). An alternative parsing method that works well for many ILSMs (like Java and Python) is to use the language's compiler itself to parse for you. This works as long as the compiler can be made to give back parse information. =back =head1 THE INLINE API This section is a more formal specification of what functionality you'll need to provide to implement an ILSM. When Inline determines that some C code needs to be compiled it will automatically load your ILSM module. It will then call various subroutines which you need to supply. We'll call these subroutines "callbacks". You will need to provide the following 5 callback subroutines. =head2 The register() Callback This subroutine receives no arguments. It returns a reference to a hash of ILSM meta-data. Inline calls this routine only when it is trying to detect new ILSM-s that have been installed on a given system. Here is an example of the has ref you would return for Foo: { language => 'Foo', aliases => ['foo'], type => 'interpreted', suffix => 'foo', }; The meta-data items have the following meanings: =over =item language This is the proper name of the language. It is usually implemented as C for a given language 'X'. =item aliases This is a reference to an array of language name aliases. The proper name of a language can only contain word characters. L An alias can contain any characters except whitespace and quotes. This is useful for names like 'C++' and 'C#'. =item type Must be set to 'compiled' or 'interpreted'. Indicates the category of the language. =item suffix This is the file extension for the cached object that will be created. For 'compiled' languages, it will probably be 'so' or 'dll'. The appropriate value is in C. For interpreted languages, this value can be whatever you want. Python uses C. Foo uses C. =back =head2 The validate() Callback This routine gets passed all configuration options that were not already handled by the base Inline module. The options are passed as key/value pairs. It is up to you to validate each option and store its value in the Inline object (which is also passed in). If a particular option is invalid, you should croak with an appropriate error message. Note that all the keywords this routine receives will be converted to upper- case by C, whatever case the program gave. =head2 The build() Callback This subroutine is responsible for doing the parsing and compilation of the Foo source code. The Inline object is passed as the only argument. All pertinent information will be stored in this object. C is required to create a cache object of a specific name, or to croak with an appropriate error message. This is the meat of your ILSM. Since it will most likely be quite complicated, it is probably best that you study an existing ILSM like C. =head2 The load() Callback This method only needs to be provided for interpreted languages. It's responsibility is to start the interpreter. For compiled languages, the load routine from C is called which uses C to load the shared object or DLL. =head2 The info() Callback This method is called when the user makes use of the C shortcut. You should return a string containing a small report about the Inlined code. =head1 THE INLINE OBJECT C creates a hash based Perl object for each section of Inlined source code it receives. This object contains lots of information about the code, the environment, and the configuration options used. This object is a hash that is broken into several subhashes. The only two subhashes that an ILSM should use at all are $o->{API} and $o->{ILSM}. The first one contains all of the information that Inline has gather for you in order for you to create/load a cached object of your design. The second one is a repository where your ILSM can freely store data that it might need later on. This section will describe all of the Inline object "API" attributes. =over =item The code Attribute This the actual source code passed in by the user. It is stored as one long string. =item The language Attribute The proper name of the language being used. =item The language_id Attribute The language name specified by the user. Could be 'C++' instead of 'CPP'. =item The module Attribute This is the shared object's file name. =item The modfname Attribute This is the shared object's file name. =item The modpname Attribute This is the shared object's installation path extension. =item The version Attribute The version of C being used. =item The pkg Attribute The Perl package from which this invocation pf Inline was called. =item The install_lib Attribute This is the directory to write the shared object into. =item The build_dir Attribute This is the directory under which you should write all of your build related files. =item The script Attribute This is the name of the script that invoked Inline. =item The location Attribute This is the full path name of the executable object in question. =item The suffix Attribute This is the shared library extension name. (Usually 'so' or 'dll'). =back =head2 derive_minus_I Method ILSMs may need to run Perl subprocesses with a similar environment to the current one - particularly C<@INC>. This method can be called to return a list of absolute paths to pass to a Perl interpreter to recreate that environment. You will need to prepend C<-I> to each one. This method omits from that list any paths that occur in C<$ENV{PERL5LIB}> or the Perl default libraries since those will be available already. =head1 THE INLINE NAMESPACE C has been set up so that anyone can write their own language support modules. It further allows anyone to write a different implementation of an existing Inline language, like C for instance. You can distribute that module on the CPAN. If you have plans to implement and distribute an Inline module, I would ask that you please work with the Inline community. We can be reached at the Inline mailing list: inline@perl.org (Send mail to inline-subscribe@perl.org to subscribe). Here you should find the advice and assistance needed to make your module a success. The Inline community will decide if your implementation of COBOL will be distributed as the official C or should use an alternate namespace. In matters of dispute, I (Ingy döt Net) retain final authority. (and I hope not to need use of it :-) Actually modules@perl.org retains the B authority. But even if you want to work alone, you are free and welcome to write and distribute Inline language support modules on CPAN. You'll just need to distribute them under a different package name. =head1 SEE ALSO For generic information about Inline, see L. For information about using Inline with C see L. For information on supported languages and platforms see L. Inline's mailing list is inline@perl.org To subscribe, send email to inline-subscribe@perl.org =head1 AUTHOR Ingy döt Net =head1 COPYRIGHT Copyright 2000-2019. Ingy döt Net. Copyright 2008, 2010, 2011. Sisyphus. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L =cut bin000755001750001750 013605534015 13230 5ustar00ingyingy000000000000Inline-0.86/inctestml-cpan100644001750001750 55513605534015 15527 0ustar00ingyingy000000000000Inline-0.86/inc/bin#!/usr/bin/perl use lib 't', 'inc/lib'; use TestML::Run::TAP; my $testml_file = $ARGV[-1]; my $test_file = $testml_file; $test_file =~ s/(.*)\.t$/inc\/$1.tml.lingy/ or die "Error with '$testml_file'. testml-cpan only works with *.t files."; -e $test_file or die "TestML file '$testml_file' not compiled as '$test_file'"; TestML::Run::TAP->run($test_file); denter.pm100644001750001750 2363613605534015 15704 0ustar00ingyingy000000000000Inline-0.86/lib/Inlinepackage Inline::denter; use strict; use Carp; sub new { my $class = shift; bless {width => 4, comma => " : ", level => 0, tabwidth => 8, }, $class; } # Prevent a taint exception being thrown by AutoLoader.pm. # Serves no other purpose. sub DESTROY { } sub undent { local $/ = "\n"; my ($o, $text) = @_; my ($comma) = $o->{comma}; my $package = caller; $package = caller(1) if $package eq 'Inline::denter'; %{$o->{xref}} = (); @{$o->{objects}} = (); @{$o->{context}} = (); my $glob = ''; chomp $text; @{$o->{lines}} = split $/, $text; $o->{level} = 0; $o->{line} ||= 1; $o->_setup_line; while (not $o->{done}) { if ($o->{level} == 0 and $o->{content} =~ /^(\w+)\s*$comma\s*(.*)$/) { $o->{content} = $2; no strict 'refs'; push @{$o->{objects}}, "$1"; } push @{$o->{objects}}, $o->_undent_data; } return @{$o->{objects}}; } sub _undent_data { my $o = shift; my ($obj, $class) = ('', ''); my @refs; my %refs; while ($o->{content} =~ s/^\\(?:\((\w+)\))?((\%|\@|\$|\\).*)/$2/) { push @refs, $1; $refs{$1} = scalar @refs; } if ($o->{content} =~ /^([\%\@\$]) (\w(?:\w|::)*)? \s*$/x ) { my $foo; $obj = ($1 eq '%') ? {} : ($1 eq '@') ? [] : \$foo; $class = $2 || ''; if ($1 eq '%') { %$obj = $o->_undent_hash; } elsif ($1 eq '@') { @$obj = $o->_undent_array; } else { $$obj = $o->_undent_scalar; } bless $obj, $class if length $class; } elsif ($o->{content} =~ /^\?\s*$/) { $obj = $o->_undent_undef; } else { $obj = $o->_undent_value; } while (@refs) { my $ref = pop @refs; my $copy = $obj; $obj = \ $copy; $o->{xref}{$ref} = $obj if $ref; } return $obj; } sub _undent_value { my $o = shift; my $value = ''; if ($o->{content} =~ /^\<\<(\w+)(\-?)\s*$/) { my ($marker, $chomp) = ($1, $2); my $line = $o->{line}; $o->_next_line; while (not $o->{done} and $o->{lines}[0] ne $marker) { $value .= $o->{lines}[0] . "\n"; $o->_next_line; } croak M03_no_value_end_marker($marker, $line) if $o->{done}; chomp $value if $chomp; } elsif ($o->{content} =~ /^\"/) { croak $o->M04_mismatched_quotes unless $o->{content} =~ /^\".*\"\s*$/; ($value = $o->{content}) =~ s/^\"|\"\s*$//g; } else { $value = $o->{content}; } $o->_next_line; $o->_setup_line; return $value; } sub _undent_hash { my @values; my $o = shift; my $level = $o->{level} + 1; $o->_next_line; $o->_setup_line; while ($o->{level} == $level) { my ($key, $value) = split $o->{comma}, $o->{content}; croak $o->M05_invalid_key_value unless (defined $key and defined $value); $o->{content} = $value; push @values, $o->_get_key($key), $o->_undent_data;; } croak $o->M06_invalid_indent_level if $o->{level} > $level; return @values; } sub _get_key { my ($o, $key) = @_; return $key unless $key =~ /^\<\<(\w+)(\-?)/; my ($marker, $chomp) = ($1, $2); $key = ''; my $line = $o->{line}; $o->_next_line; while (not $o->{done} and $o->{lines}[0] ne $marker) { $key .= $o->{lines}[0] . "\n"; $o->_next_line; } croak M02_no_key_end_marker($marker, $line) if $o->{done}; chomp $key if $chomp; $o->_next_line; $o->_setup_line; return $key; } sub _undent_array { my @values; my $o = shift; my $level = $o->{level} + 1; $o->_next_line; $o->_setup_line; while ($o->{level} == $level) { push @values, $o->_undent_data; } croak $o->M06_invalid_indent_level if $o->{level} > $level; return @values; } sub _undent_scalar { my $values; my $o = shift; my $level = $o->{level} + 1; $o->_next_line; $o->_setup_line; croak $o->M06_invalid_indent_level if $o->{level} != $level; croak $o->M07_invalid_scalar_value if $o->{content} =~ /^[\%\@\$\\]/; return $o->_undent_undef if $o->{content} =~ /^\?/; return $o->_undent_value; } sub _undent_undef { my $o = shift; $o->_next_line; $o->_setup_line; return undef; } sub _next_line { my $o = shift; $o->{done}++, $o->{level} = -1, return unless @{$o->{lines}}; local $_ = shift @{$o->{lines}}; $o->{line}++; } sub _setup_line { my $o = shift; $o->{done}++, $o->{level} = -1, return unless @{$o->{lines}}; my ($width, $tabwidth) = @{$o}{qw(width tabwidth)}; while (1) { local $_ = $o->{lines}[0]; # expand tabs in leading whitespace; $o->next_line, next if /^(\s*$|\#)/; # skip comments and blank lines while (s{^( *)(\t+)} {' ' x (length($1) + length($2) * $tabwidth - length($1) % $tabwidth)}e){} croak $o->M01_invalid_indent_width unless /^(( {$width})*)(\S.*)$/; $o->{level} = length($1) / $width; $o->{content} = $3; last; } } sub indent { my $o = shift; my $package = caller; $package = caller(1) if $package eq 'Inline::denter'; my $stream = ''; $o->{key} = ''; while (@_) { local $_ = shift; $stream .= $o->indent_name($_, shift), next if (/^\*$package\::\w+$/); $stream .= $o->indent_data($_); } return $stream; } sub indent_data { my $o = shift; local $_ = shift; return $o->indent_undef($_) if not defined; return $o->indent_value($_) if (not ref); return $o->indent_hash($_) if (ref eq 'HASH' and not /=/ or /=HASH/); return $o->indent_array($_) if (ref eq 'ARRAY' and not /=/ or /=ARRAY/); return $o->indent_scalar($_) if (ref eq 'SCALAR' and not /=/ or /=SCALAR/); return $o->indent_ref($_) if (ref eq 'REF'); return "$_\n"; } sub indent_value { my ($o, $data) = @_; my $stream; if ($data =~ /\n/) { my $marker = 'EOV'; $marker++ while $data =~ /^$marker$/m; my $chomp = ($data =~ s/\n\Z//) ? '' : '-'; $stream = "<<$marker$chomp\n"; $stream .= $o->{key}, $o->{key} = '' if $o->{key}; $stream .= "$data\n$marker\n"; } elsif ($data =~ /^[\s\%\@\$\\?\"]|\s$/ or $data =~ /\Q$o->{comma}\E/ or $data =~ /[\x00-\x1f]/ or $data eq '') { $stream = qq{"$data"\n}; $stream .= $o->{key}, $o->{key} = '' if $o->{key}; } else { $stream = "$data\n"; $stream .= $o->{key}, $o->{key} = '' if $o->{key}; } return $stream; } sub indent_hash { my ($o, $data) = @_; my $stream = $o->_print_ref($data, '%', 'HASH'); return $$stream if ref $stream; my $indent = ++$o->{level} * $o->{width}; for my $key (sort keys %$data) { my $key_out = $key; if ($key =~ /\n/ or $key =~ /\Q$o->{comma}\E/) { my $marker = 'EOK'; $marker++ while $key =~ /^$marker$/m; my $chomp = (($o->{key} = $key) =~ s/\n\Z//m) ? '' : '-'; $o->{key} .= "\n$marker\n"; $key_out = "<<$marker$chomp"; } elsif ($data =~ /^[\s\%\@\$\\?\"]|\s$/) { $key_out = qq{"$key"}; } $stream .= ' ' x $indent . $key_out . $o->{comma}; $stream .= $o->indent_data($data->{$key}); } $o->{level}--; return $stream; } sub indent_array { my ($o, $data) = @_; my $stream = $o->_print_ref($data, '@', 'ARRAY'); return $$stream if ref $stream; my $indent = ++$o->{level} * $o->{width}; for my $datum (@$data) { $stream .= ' ' x $indent; $stream .= $o->indent_data($datum); } $o->{level}--; return $stream; } sub indent_scalar { my ($o, $data) = @_; my $stream = $o->_print_ref($data, q{$}, 'SCALAR'); return $$stream if ref $stream; my $indent = ($o->{level} + 1) * $o->{width}; $stream .= ' ' x $indent; $stream .= $o->indent_data($$data); return $stream; } sub indent_ref { my ($o, $data) = @_; my $stream = $o->_print_ref($data, '\\', 'SCALAR'); return $$stream if ref $stream; chomp $stream; return $stream . $o->indent_data($$data); } sub indent_undef { my ($o, $data) = @_; my $stream = "?\n"; $stream .= $o->{key}, $o->{key} = '' if $o->{key}; return $stream; } sub indent_name { my ($o, $name, $value) = @_; $name =~ s/^.*:://; my $stream = $name . $o->{comma}; $stream .= $o->indent_data($value); return $stream; } sub _print_ref { my ($o, $data, $symbol, $type) = @_; $data =~ /^(([\w:]+)=)?$type\(0x([0-9a-f]+)\)$/ or croak "Invalid reference: $data\n"; my $stream = $symbol; $stream .= $2 if defined $2; $o->{xref}{$3}++; croak "Inline::denter does not handle duplicate references" if $o->{xref}{$3} > 1; $stream .= "\n"; $stream .= $o->{key}, $o->{key} = '' if $o->{key}; return $stream; } # Undent error messages sub M01_invalid_indent_width { my $o = shift; "Invalid indent width detected at line $o->{line}\n"; } sub M02_no_key_end_marker { my ($marker, $line) = @_; "No terminating marker '$marker' found for key at line $line\n"; } sub M03_no_value_end_marker { my ($marker, $line) = @_; "No terminating marker '$marker' found for value at line $line\n"; } sub M04_mismatched_quotes { my $o = shift; "Mismatched double quotes for value at line $o->{line}\n"; } sub M05_invalid_key_value { my $o = shift; "Missing or invalid hash key/value pair at $o->{line}\n"; } sub M06_invalid_indent_level { my $o = shift; "Invalid indentation level at $o->{line}\n"; } sub M07_invalid_scalar_value { my $o = shift; "Invalid value for scalar ref context at $o->{line}\n"; } 1; __END__ 06rewrite_config.t100644001750001750 122313605534015 15651 0ustar00ingyingy000000000000Inline-0.86/tBEGIN { if($] < 5.007) { print "1..1\n"; warn "Skipped for perl 5.6.x\n"; print "ok 1\n"; exit(0); } }; use warnings; use strict; use lib -e 't' ? 't' : 'test'; use Test::More tests => 2; use Test::Warn; use TestInlineSetup; use Inline Config => DIRECTORY => $TestInlineSetup::DIR; eval q{use Inline 'Bogus' => 'code';}; # Suppress "Set up gcc environment ..." warning. # (Affects ActivePerl only.) $ENV{ACTIVEPERL_CONFIG_SILENT} = 1; my $w = 'config file removal successful'; warnings_like {require_rewrite()} [qr/$w/], 'warn_test'; sub require_rewrite { my $t = -d 't' ? 't' : 'test'; require "./$t/06rewrite_config.p"; } 06rewrite_config.p100644001750001750 37013605534015 15627 0ustar00ingyingy000000000000Inline-0.86/tInline->init() ; use Inline Config => DIRECTORY => $TestInlineSetup::DIR, _TESTING => 1, REWRiTE_COnFIG_FILE => 1; use Inline 'Foo'; is(add(3, 7), 10, 'foo test'); 1; __DATA__ __Foo__ foo-sub add { foo-return $_[0] + $_[1]; } TestInlineSetup.pm100644001750001750 115113605534015 15745 0ustar00ingyingy000000000000Inline-0.86/tuse strict; use warnings; package TestInlineSetup; our $DIAG = eval { require diagnostics; diagnostics->import(); 1; }; use File::Path; use File::Spec; sub import { my ($package, $option) = @_; $option ||= ''; } our $DIR; BEGIN { ($_, $DIR) = caller(2); $DIR =~ s/.*?(\w+)\.t$/$1/ or die; $DIR = "_Inline_$DIR.$$"; rmtree($DIR) if -d $DIR; mkdir($DIR) or die "$DIR: $!\n"; } my $absdir = File::Spec->rel2abs($DIR); ($absdir) = $absdir =~ /(.*)/; # untaint my $startpid = $$; END { if($$ == $startpid) { # only when original process exits rmtree($absdir); } } 1; 07rewrite2_config.t100644001750001750 112113605534015 15731 0ustar00ingyingy000000000000Inline-0.86/tBEGIN { if($] < 5.007) { print "1..1\n"; warn "Skipped for perl 5.6.x\n"; print "ok 1\n"; exit(0); } }; use strict; use warnings; use lib -e 't' ? 't' : 'test'; use TestInlineSetup; use Test::More tests => 2; use Test::Warn; # Suppress "Set up gcc environment ..." warning. # (Affects ActivePerl only.) $ENV{ACTIVEPERL_CONFIG_SILENT} = 1; my $w = 'config file removed'; warnings_like {require_rewrite()} [qr/$w/], 'warn_test'; ok($@, '"Inline Bogus" test'); sub require_rewrite { my $t = -d 't' ? 't' : 'test'; eval {require "./$t/07rewrite2_config.p";}; } 07rewrite2_config.p100644001750001750 21713605534015 15712 0ustar00ingyingy000000000000Inline-0.86/tInline->init() ; use Inline Config => DIRECTORY => $TestInlineSetup::DIR, _TEsTING => 1; use Inline Bogus => <<'EOB'; foo(){} EOB TestML000755001750001750 013605534015 14376 5ustar00ingyingy000000000000Inline-0.86/inc/libRun.pm100644001750001750 3474013605534015 15670 0ustar00ingyingy000000000000Inline-0.86/inc/lib/TestMLuse strict; use warnings; package TestMLFunction; sub new { my ($class, $func) = @_; return bless {func => $func}, $class; } package TestML::Run; use JSON::PP; use utf8; use TestML::Boolean; use Scalar::Util; # use XXX; my $vtable = { '==' => 'assert_eq', '~~' => 'assert_has', '=~' => 'assert_like', '!==' => 'assert_not_eq', '!~~' => 'assert_not_has', '!=~' => 'assert_not_like', '.' => 'exec_dot', '%' => 'each_exec', '%<>' => 'each_pick', '<>' => 'pick_exec', '&' => 'call_func', '"' => 'get_str', ':' => 'get_hash', '[]' => 'get_list', '*' => 'get_point', '=' => 'set_var', '||=' => 'or_set_var', }; my $types = { '=>' => 'func', '/' => 'regex', '!' => 'error', '?' => 'native', }; #------------------------------------------------------------------------------ sub new { my ($class, %params) = @_; my $testml = $params{testml}; return bless { file => $params{file}, ast => $params{testml}, bridge => $params{bridge}, stdlib => $params{stdlib}, vars => {}, block => undef, warned_only => false, error => undef, thrown => undef, }, $class; } sub from_file { my ($self, $file) = @_; $self->{file} = $file; open INPUT, $file or die "Can't open '$file' for input"; $self->{ast} = decode_json do { local $/; }; return $self; } sub test { my ($self) = @_; $self->testml_begin; for my $statement (@{$self->{ast}{code}}) { $self->exec_expr($statement); } $self->testml_end; return; } #------------------------------------------------------------------------------ sub exec { my ($self, $expr) = @_; $self->exec_expr($expr)->[0]; } sub exec_expr { my ($self, $expr, $context) = @_; $context = [] unless defined $context; return [$expr] unless $self->type($expr) eq 'expr'; my @args = @$expr; my @ret; my $name = shift @args; my $opcode = $name; if (my $call = $vtable->{$opcode}) { $call = $call->[0] if ref($call) eq 'ARRAY'; @ret = $self->$call(@args); } else { unshift @args, $_ for reverse @$context; if (defined(my $value = $self->{vars}{$name})) { if (@args) { die "Variable '$name' has args but is not a function" unless $self->type($value) eq 'func'; @ret = $self->exec_func($value, \@args); } else { @ret = ($value); } } elsif ($name =~ /^[a-z]/) { @ret = $self->call_bridge($name, @args); } elsif ($name =~ /^[A-Z]/) { @ret = $self->call_stdlib($name, @args); } else { die "Can't resolve TestML function '$name'"; } } return [@ret]; } sub exec_func { my ($self, $function, $args) = @_; $args = [] unless defined $args; my ($op, $signature, $statements) = @$function; if (@$signature > 1 and @$args == 1 and $self->type($args) eq 'list') { $args = $args->[0]; } die "TestML function expected '${\scalar @$signature}' arguments, but was called with '${\scalar @$args}' arguments" if @$signature != @$args; my $i = 0; for my $v (@$signature) { $self->{vars}{$v} = $self->exec($args->[$i++]); } for my $statement (@$statements) { $self->exec_expr($statement); } return; } #------------------------------------------------------------------------------ sub call_bridge { my ($self, $name, @args) = @_; if (not $self->{bridge}) { my $bridge_module = $ENV{TESTML_BRIDGE} || 'TestMLBridge'; if (my $code = $self->{ast}{bridge}{perl5}) { eval <<"..." or die $@; use strict; use warnings; package TestMLBridge; use base 'TestML::Bridge'; $code; 1; ... } else { eval "require $bridge_module; 1" or die $@; } $self->{bridge} = $bridge_module->new; } (my $call = $name) =~ s/-/_/g; die "Can't find bridge function: '$name'" unless $self->{bridge} and $self->{bridge}->can($call); @args = map {$self->uncook($self->exec($_))} @args; my @ret = $self->{bridge}->$call(@args); return unless @ret; $self->cook($ret[0]); } sub call_stdlib { my ($self, $name, @args) = @_; if (not $self->{stdlib}) { require TestML::StdLib; $self->{stdlib} = TestML::StdLib->new($self); } my $call = lc $name; die "Unknown TestML Standard Library function: '$name'" unless $self->{stdlib}->can($call); @args = map {$self->uncook($self->exec($_))} @args; $self->cook($self->{stdlib}->$call(@args)); } #------------------------------------------------------------------------------ sub assert_eq { my ($self, $left, $right, $label, $not) = @_; my $got = $self->{vars}{Got} = $self->exec($left); my $want = $self->{vars}{Want} = $self->exec($right); my $method = $self->get_method('assert_%s_eq_%s', $got, $want); $self->$method($got, $want, $label, $not); return; } sub assert_str_eq_str { my ($self, $got, $want, $label, $not) = @_; $self->testml_eq($got, $want, $self->get_label($label), $not); } sub assert_num_eq_num { my ($self, $got, $want, $label, $not) = @_; $self->testml_eq($got, $want, $self->get_label($label), $not); } sub assert_bool_eq_bool { my ($self, $got, $want, $label, $not) = @_; $self->testml_eq($got, $want, $self->get_label($label), $not); } sub assert_has { my ($self, $left, $right, $label, $not) = @_; my $got = $self->exec($left); my $want = $self->exec($right); my $method = $self->get_method('assert_%s_has_%s', $got, $want); $self->$method($got, $want, $label, $not); return; } sub assert_str_has_str { my ($self, $got, $want, $label, $not) = @_; $self->{vars}{Got} = $got; $self->{vars}{Want} = $want; $self->testml_has($got, $want, $self->get_label($label), $not); } sub assert_str_has_list { my ($self, $got, $want, $label, $not) = @_; for my $str (@{$want->[0]}) { $self->assert_str_has_str($got, $str, $label, $not); } } sub assert_list_has_str { my ($self, $got, $want, $label, $not) = @_; $self->{vars}{Got} = $got; $self->{vars}{Want} = $want; $self->testml_list_has($got->[0], $want, $self->get_label($label), $not); } sub assert_list_has_list { my ($self, $got, $want, $label, $not) = @_; for my $str (@{$want->[0]}) { $self->assert_list_has_str($got, $str, $label, $not); } } sub assert_like { my ($self, $left, $right, $label, $not) = @_; my $got = $self->exec($left); my $want = $self->exec($right); my $method = $self->get_method('assert_%s_like_%s', $got, $want); $self->$method($got, $want, $label, $not); return; } sub assert_str_like_regex { my ($self, $got, $want, $label, $not) = @_; $self->{vars}{Got} = $got; $self->{vars}{Want} = "/${\ $want->[1]}/"; $want = $self->uncook($want); $self->testml_like($got, $want, $self->get_label($label), $not); } sub assert_str_like_list { my ($self, $got, $want, $label, $not) = @_; for my $regex (@{$want->[0]}) { $self->assert_str_like_regex($got, $regex, $label, $not); } } sub assert_list_like_regex { my ($self, $got, $want, $label, $not) = @_; for my $str (@{$got->[0]}) { $self->assert_str_like_regex($str, $want, $label, $not); } } sub assert_list_like_list { my ($self, $got, $want, $label, $not) = @_; for my $str (@{$got->[0]}) { for my $regex (@{$want->[0]}) { $self->assert_str_like_regex($str, $regex, $label, $not); } } } sub assert_not_eq { my ($self, $got, $want, $label) = @_; $self->assert_eq($got, $want, $label, true); } sub assert_not_has { my ($self, $got, $want, $label) = @_; $self->assert_has($got, $want, $label, true); } sub assert_not_like { my ($self, $got, $want, $label) = @_; $self->assert_like($got, $want, $label, true); } #------------------------------------------------------------------------------ sub exec_dot { my ($self, @args) = @_; my $context = []; delete $self->{error}; for my $call (@args) { if (not $self->{error}) { eval { if ($self->type($call) eq 'func') { $self->exec_func($call, $context->[0]); $context = []; } else { $context = $self->exec_expr($call, $context); } }; if ($@) { if ($ENV{TESTML_DEVEL}) { require Carp; Carp::cluck($@); } $self->{error} = $self->call_stdlib('Error', "$@"); } elsif ($self->{thrown}) { $self->{error} = $self->cook(delete $self->{thrown}); } } else { if ($call->[0] eq 'Catch') { $context = [delete $self->{error}]; } } } die "Uncaught Error: ${\ $self->{error}[1]{msg}}" if $self->{error}; return @$context; } sub each_exec { my ($self, $list, $expr) = @_; $list = $self->exec($list); $expr = $self->exec($expr); for my $item (@{$list->[0]}) { $self->{vars}{_} = [$item]; if ($self->type($expr) eq 'func') { if (@{$expr->[1]} == 0) { $self->exec_func($expr); } else { $self->exec_func($expr, [$item]); } } else { $self->exec_expr($expr); } } } sub each_pick { my ($self, $list, $expr) = @_; for my $block (@{$self->{ast}{data}}) { $self->{block} = $block; $self->exec_expr(['<>', $list, $expr]); } delete $self->{block}; return; } sub pick_exec { my ($self, $list, $expr) = @_; my $pick = 1; if (my $when = $self->{block}{point}{WHEN}) { if ($when =~ /^Env:(\w+)$/) { $pick = 0 unless $ENV{$1}; } } if ($pick) { for my $point (@$list) { if ( ($point =~ /^\*/ and not exists $self->{block}{point}{substr($point, 1)}) or ($point =~ /^!*/) and exists $self->{block}{point}{substr($point, 2)} ) { $pick = 0; last; } } } if ($pick) { if ($self->type($expr) eq 'func') { $self->exec_func($expr); } else { $self->exec_expr($expr); } } return; } sub call_func { my ($self, $func) = @_; my $name = $func->[0]; $func = $self->exec($func); die "Tried to call '$name' but is not a function" unless defined $func and $self->type($func) eq 'func'; $self->exec_func($func); } sub get_str { my ($self, $string) = @_; $self->interpolate($string); } sub get_hash { my ($self, $hash, $key) = @_; $hash = $self->exec($hash); $key = $self->exec($key); $self->cook($hash->[0]{$key}); } sub get_list { my ($self, $list, $index) = @_; $list = $self->exec($list); return [] if not @{$list->[0]}; $self->cook($list->[0][$index]); } sub get_point { my ($self, $name) = @_; $self->getp($name); } sub set_var { my ($self, $name, $expr) = @_; $self->setv($name, $self->exec($expr)); return; } sub or_set_var { my ($self, $name, $expr) = @_; return if defined $self->{vars}{$name}; if ($self->type($expr) eq 'func') { $self->setv($name, $expr); } else { $self->setv($name, $self->exec($expr)); } return; } #------------------------------------------------------------------------------ sub getp { my ($self, $name) = @_; return unless $self->{block}; my $value = $self->{block}{point}{$name}; $self->exec($value) if defined $value; } sub getv { my ($self, $name) = @_; $self->{vars}{$name}; } sub setv { my ($self, $name, $value) = @_; $self->{vars}{$name} = $value; return; } #------------------------------------------------------------------------------ sub type { my ($self, $value) = @_; return 'null' if not defined $value; if (not ref $value) { return 'num' if Scalar::Util::looks_like_number($value); return 'str'; } return 'bool' if isBoolean($value); if (ref($value) eq 'ARRAY') { return 'none' if @$value == 0; return $_ if $_ = $types->{$value->[0]}; return 'list' if ref($value->[0]) eq 'ARRAY'; return 'hash' if ref($value->[0]) eq 'HASH'; return 'expr'; } require XXX; XXX::ZZZ("Can't determine type of this value:", $value); } sub cook { my ($self, @value) = @_; return [] if not @value; my $value = $value[0]; return undef if not defined $value; return $value if not ref $value; return [$value] if ref($value) =~ /^(?:HASH|ARRAY)$/; return $value if isBoolean($value); return ['/', $value] if ref($value) eq 'Regexp'; return ['!', $value] if ref($value) eq 'TestMLError'; return $value->{func} if ref($value) eq 'TestMLFunction'; return ['?', $value]; } sub uncook { my ($self, $value) = @_; my $type = $self->type($value); return $value if $type =~ /^(?:str|num|bool|null)$/; return $value->[0] if $type =~ /^(?:list|hash)$/; return $value->[1] if $type =~ /^(?:error|native)$/; return TestMLFunction->new($value) if $type eq 'func'; if ($type eq 'regex') { return ref($value->[1]) eq 'Regexp' ? $value->[1] : qr/${\ $value->[1]}/; } return () if $type eq 'none'; require XXX; XXX::ZZZ("Can't uncook this value of type '$type':", $value); } #------------------------------------------------------------------------------ sub get_method { my ($self, $pattern, @args) = @_; my $method = sprintf $pattern, map $self->type($_), @args; die "Method '$method' does not exist" unless $self->can($method); return $method; } sub get_label { my ($self, $label_expr) = @_; $label_expr = '' unless defined $label_expr; my $label = $self->exec($label_expr); $label ||= $self->getv('Label') || ''; my $block_label = $self->{block} ? $self->{block}{label} : ''; if ($label) { $label =~ s/^\+/$block_label/; $label =~ s/\+$/$block_label/; $label =~ s/\{\+\}/$block_label/; } else { $label = $block_label; $label = '' unless defined $label; } return $self->interpolate($label, true); } sub interpolate { my ($self, $string, $label) = @_; # XXX Hack to see input file in label: $self->{vars}{File} = $ENV{TESTML_FILEVAR}; $string =~ s/\{([\-\w]+)\}/$self->transform1($1, $label)/ge; $string =~ s/\{\*([\-\w]+)\}/$self->transform2($1, $label)/ge; return $string; } sub transform { my ($self, $value, $label) = @_; my $type = $self->type($value); if ($label) { if ($type =~ /^(?:list|hash)$/) { return encode_json($value->[0]); } if ($type eq 'regex') { return "$value->[1]"; } $value =~ s/\n/␤/g; return "$value"; } else { if ($type =~ /^(?:list|hash)$/) { return encode_json($value->[0]); } else { return "$value"; } } } sub transform1 { my ($self, $name, $label) = @_; my $value = $self->{vars}{$name}; return '' unless defined $value; $self->transform($value, $label); } sub transform2 { my ($self, $name, $label) = @_; return '' unless $self->{block}; my $value = $self->{block}{point}{$name}; return '' unless defined $value; $self->transform($value, $label); } 1; author-pod-syntax.t100644001750001750 45413605534015 16070 0ustar00ingyingy000000000000Inline-0.86/t#!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); Support.pod100644001750001750 733713605534015 16225 0ustar00ingyingy000000000000Inline-0.86/lib/Inline=pod =for comment DO NOT EDIT. This Pod was generated by Swim v0.1.46. See http://github.com/ingydotnet/swim-pm#readme =encoding utf8 =head1 NAME Inline-Support - Support Information for Inline.pm and related modules. =head1 DESCRIPTION This document contains all of the latest support information for C and the recognized Inline Language Support Modules (ILSMs) available on CPAN. =head1 SUPPORTED LANGUAGES The most important language that Inline supports is C. That is because Perl itself is written in C. By giving a your Perl scripts access to C, you in effect give them access to the entire glorious internals of Perl. (Caveat scriptor :-) As of this writing, Inline also supports: =over =item * C++ =item * Java =item * Python =item * Tcl =item * Assembly =item * CPR =item * And even Inline::Foo! :) =back Projects that I would most like to see happen in the year 2001 are: =over =item * Fortran =item * Ruby =item * Lisp =item * Guile =item * Bash =item * Perl4 =back =head1 SUPPORTED PLATFORMS C should work anywhere that CPAN extension modules (those that use XS) can be installed, using the typical install format of: perl Makefile.PL make make test make install It has been tested on many Unix and Windows variants. B: C requires Perl 5.005 or higher because C requires it. (Something to do with the C operator) Inline has been successfully tested at one time or another on the following platforms: =over =item * Linux =item * Solaris =item * SunOS =item * HPUX =item * AIX =item * FreeBSD =item * OpenBSD =item * BeOS =item * OS X =item * WinNT =item * Win2K =item * WinME =item * Win98 =item * Cygwin =back The Microsoft tests deserve a little more explanation. I used the following: =over =item * Windows NT 4.0 (service pack 6) =item * Perl 5.005_03 (ActiveState build 522) =item * MS Visual C++ 6.0 =item * The "nmake" make utility (distributed w/ Visual C++) =back C pulls all of its base configuration (including which C utility to use) from C. Since your MSWin32 version of Perl probably came from ActiveState (as a binary distribution) the C will indicate that C is the system's C utility. That is because ActiveState uses Visual C++ to compile Perl. To install C (or any other CPAN module) on MSWin32 w/ Visual C++, use these: perl Makefile.PL nmake nmake test nmake install Inline has also been made to work with Mingw32/gcc on all Windows platforms. This is a free compiler for Windows. You must also use a perl built with that compiler. The "Cygwin" test was done on a Windows 98 machine using the Cygwin Unix/Win32 porting layer software from Cygnus. The C binary on this machine was also compiled using the Cygwin tool set (C). This software is freely available from L If you get Inline to work on a new platform, please send me email email. If it doesn't work, let me know as well and I'll see what can be done. =head1 SEE ALSO For general information about Inline see L. For information about using Inline with C see L. For sample programs using Inline with C see L. For information on writing your own Inline Language Support Module, see L. Inline's mailing list is inline@perl.org To subscribe, send email to inline-subscribe@perl.org =head1 AUTHOR ingy döt Net =head1 COPYRIGHT Copyright 2000-2019. Ingy döt Net. Copyright 2008, 2010, 2011. Sisyphus. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L =cut MakeMaker.pm100644001750001750 667413605534015 16243 0ustar00ingyingy000000000000Inline-0.86/lib/Inlinepackage Inline::MakeMaker; use strict; use base 'Exporter'; use ExtUtils::MakeMaker(); use Carp; use version; our @EXPORT = qw(WriteMakefile WriteInlineMakefile); our $VERSION = '0.86'; sub WriteInlineMakefile { carp <parse_version($args{VERSION_FROM}) or croak "Can't determine version for $name\n"; } croak "Invalid 'version.pm' version '$version' for '$name'.\n" unless version::is_lax($version); # Provide a convenience rule to clean up Inline's messes $args{clean} = { FILES => "_Inline *.inl " } unless defined $args{clean}; # Add Inline to the dependencies $args{PREREQ_PM}{Inline} = '0.44' unless defined $args{PREREQ_PM}{Inline}; my $mm = &ExtUtils::MakeMaker::WriteMakefile(%args); my (@objects, @obj_rules); if (@{$mm->{PMLIBDIRS}} && $mm->{PM}) { # Sort them longest first so we'll match subdirectories before their parents my @libdirs = sort { length($b) <=> length($a) } @{$mm->{PMLIBDIRS}}; for my $path (keys %{$mm->{PM}}) { for my $lib (@libdirs) { if (index($path,$lib) == 0) { my ($vol, $dirs, $file) = File::Spec->splitpath(substr($path, length($lib)+1)); my @dirs = File::Spec->splitdir($dirs); pop @dirs unless length($dirs[$#dirs]); next unless ($file =~ /.pm$/); $file =~ s/\.[^.]+$//; push @objects, join('::', @dirs, $file); push @obj_rules, join('-', @dirs, "$file.inl"); last; } croak "Failed to find module path for '$path'"; } } } else { # no modules found in PMLIBDIRS so assume we've just got $name to do @objects = $name; $name =~ s/::/-/g; @obj_rules = ("$name.inl"); } if (@objects) { open MAKEFILE, '>> Makefile' or croak "Inline::MakeMaker::WriteMakefile can't append to Makefile:\n$!"; print MAKEFILE < '$obj_rules[$_]', module => '$objects[$_]'); my %S = (API => \\%A); Inline::satisfy_makefile_dep(\\%S);" $version \$(INST_ARCHLIB) MAKEFILE } print MAKEFILE "\ndynamic :: ",join(' ',@obj_rules),"\n"; print MAKEFILE < \&test, no_chdir => 1, }, 'lib'; done_testing; Bridge.pm100644001750001750 15713605534015 16253 0ustar00ingyingy000000000000Inline-0.86/inc/lib/TestMLuse strict; use warnings; package TestML::Bridge; sub new { my $class = shift; bless {@_}, $class; } 1; StdLib.pm100644001750001750 470213605534015 16260 0ustar00ingyingy000000000000Inline-0.86/inc/lib/TestMLuse strict; use warnings; package TestML::StdLib; use TestML::Boolean(); sub new { my ($class, $run) = @_; bless {run => $run}, $class; } sub argv { [@ARGV]; } sub block { my ($self, $selector) = @_; return $self->{run}{block} if not defined $selector; for my $block (@{$self->{run}{ast}{data}}) { if ($block->{label} eq $selector) { return $block; } } return undef; } sub blocks { my ($self) = @_; [@{$self->{run}{ast}{data}}]; } sub bool { my ($self, $value) = @_; (defined($value) and not TestML::Boolean::isFalse($value)) ? TestML::Boolean::true : TestML::Boolean::false; } sub cat { my ($self, @strings) = @_; my $strings = ref($strings[0]) eq 'ARRAY' ? $strings[0] : [@strings]; CORE::join '', @$strings; } sub count { my ($self, $list) = @_; scalar @$list; } sub env { \%ENV; } sub error { my ($self, $msg) = (@_, ''); TestMLError->new($msg); } sub false { TestML::Boolean::false(); } sub fromjson { my ($self, $value) = @_; $self->_json->decode($value); } sub join { my ($self, $list, $separator) = @_; $separator = ' ' unless defined $separator; CORE::join $separator, @$list; } sub lines { my ($self, $text) = @_; chomp $text; [split "\n", $text]; } sub msg { my ($self, $error) = (@_); $error->msg; } sub none { return (); } sub null { undef; } sub split { my ($self, $string, $delim, $limit) = @_; $delim ||= ' '; $limit ||= -1; [split $delim, $string, $limit]; } sub sum { my ($self, @list) = @_; my $list = ref($list[0]) eq 'ARRAY' ? $list[0] : [@list]; require List::Util; List::Util::sum(@$list); } sub text { my ($self, $list) = @_; CORE::join "\n", @$list, ''; } sub tojson { my ($self, $value) = @_; $self->_json->encode($value); } sub throw { my ($self, $msg) = @_; $self->{run}{thrown} = TestMLError->new($msg); return 0; } sub type { my ($self, @value) = @_; return 'none' unless @value; $self->{run}->type($self->{run}->cook($value[0])); } sub true { TestML::Boolean::true(); } #------------------------------------------------------------------------------ my $json; sub _json { require JSON::PP; $json ||= JSON::PP->new ->pretty ->indent_length(2) ->canonical(1) ->allow_nonref; } #------------------------------------------------------------------------------ package TestMLError; sub new { my ($class, $msg) = @_; return bless { msg => $msg }, $class; } sub msg { $_[0]->{msg} } 1; t000755001750001750 013605534015 12723 5ustar00ingyingy000000000000Inline-0.86/inc03errors.tml.lingy100644001750001750 207113605534015 16401 0ustar00ingyingy000000000000Inline-0.86/inc/t{ "testml": "0.3.0", "code": [ ["%<>",["*perl","*error-patterns"], ["=~", [".", ["*","perl"], ["eval-catch"]], ["*","error-patterns"]]]], "data": [ { "label": "Bad first parameter", "point": { "perl": "use Inline Bogus => 'code';\n", "error-patterns": [[ ["/","You have specified 'Bogus' as an Inline programming language."], ["/","I currently only know about the following languages:"]]]}}, { "label": "Bad shortcut", "point": { "perl": "use Inline 'force', 'hocum';\n", "error-patterns": [[ ["/","Invalid shortcut 'hocum' specified."], ["/","Valid shortcuts are:"], ["/","VERSION, INFO, FORCE, NOCLEAN, CLEAN, UNTAINT, SAFE, UNSAFE,"], ["/","GLOBAL, NOISY and REPORTBUG"]]]}}, { "label": "Bad config option", "point": { "perl": "use Inline Foo => 'xxx' => ENABLE => 'BOgUM';\n", "error-patterns": [[ ["/","'BOGUM' is not a valid config option for Inline::Foo"]]]}}]} Boolean.pm100644001750001750 234113605534015 16453 0ustar00ingyingy000000000000Inline-0.86/inc/lib/TestML# Copied/modified from boolean.pm use strict; use warnings; package TestML::Boolean; our $VERSION = '0.46'; my ($true, $false); use overload '""' => sub { ${$_[0]} }, '!' => sub { ${$_[0]} ? $false : $true }, fallback => 1; use base 'Exporter'; @TestML::Boolean::EXPORT = qw(true false isTrue isFalse isBoolean); my ($true_val, $false_val, $bool_vals); BEGIN { my $t = 1; my $f = 0; $true = do {bless \$t, 'TestML::Boolean'}; $false = do {bless \$f, 'TestML::Boolean'}; $true_val = overload::StrVal($true); $false_val = overload::StrVal($false); $bool_vals = {$true_val => 1, $false_val => 1}; } # refaddrs change on thread spawn, so CLONE fixes them up sub CLONE { $true_val = overload::StrVal($true); $false_val = overload::StrVal($false); $bool_vals = {$true_val => 1, $false_val => 1}; } sub true() { $true } sub false() { $false } sub isTrue($) { not(defined $_[0]) ? false : (overload::StrVal($_[0]) eq $true_val) ? true : false; } sub isFalse($) { not(defined $_[0]) ? false : (overload::StrVal($_[0]) eq $false_val) ? true : false; } sub isBoolean($) { not(defined $_[0]) ? false : (exists $bool_vals->{overload::StrVal($_[0])}) ? true : false; } 1; Run000755001750001750 013605534015 15142 5ustar00ingyingy000000000000Inline-0.86/inc/lib/TestMLTAP.pm100644001750001750 1047013605534015 16306 0ustar00ingyingy000000000000Inline-0.86/inc/lib/TestML/Runuse strict; use warnings; package TestML::Run::TAP; use base 'TestML::Run'; sub run { my ($class, $file) = @_; $class->new->from_file($file)->test; return; } sub new { my ($class, @params) = @_; my $self = $class->SUPER::new(@params); ##### TODO $self->{count} = 0; return $self; } sub testml_begin { my ($self) = @_; $self->{checked} = 0; $self->{planned} = 0; } sub testml_end { my ($self) = @_; $self->tap_done unless $self->{planned}; } sub testml_eq { my ($self, $got, $want, $label, $not) = @_; $self->check_plan; if (not $not and $got ne $want and $want =~ /\n/ and (not defined $self->getv('Diff') or $self->getv('Diff')) and not($ENV{TESTML_NO_DIFF}) and eval { require Text::Diff } ) { $self->tap_ok(0, $label ? ($label) : ()); my $diff = Text::Diff::diff( \$want, \$got, { FILENAME_A => 'want', FILENAME_B => 'got', } ); $self->tap_diag($diff); } elsif ($not) { $self->tap_isnt($got, $want, $label ? ($label) : ()); } else { $self->tap_is($got, $want, $label ? ($label) : ()); } } sub testml_like { my ($self, $got, $want, $label, $not) = @_; $self->check_plan; if ($not) { $self->tap_unlike($got, $want, $label); } else { $self->tap_like($got, $want, $label); } } sub testml_has { my ($self, $got, $want, $label, $not) = @_; $self->check_plan; my $index = index($got, $want); if ($not ? ($index == -1) : ($index != -1)) { $self->tap_ok(1, $label); } else { $self->tap_ok(0, $label); my $verb = $not ? ' does' : "doesn't"; $self->tap_diag(" this string: '$got'\n $verb contain: '$want'"); } } sub testml_list_has { my ($self, $got, $want, $label) = @_; $self->check_plan; for my $str (@$got) { next if ref $str; if ($str eq $want) { $self->tap_ok(1, $label); return; } } $self->tap_ok(0, $label); $self->tap_diag(" this list: @$got\n doesn't contain: $want"); } sub check_plan { my ($self) = @_; return if $self->{checked}; $self->{checked} = 1; if (my $plan = $self->{vars}{Plan}) { $self->{planned} = 1; $self->tap_plan($plan); } } sub tap_plan { my ($self, $plan) = @_; $self->out("1..$plan"); } sub tap_pass { my ($self, $label) = @_; $label = '' unless defined $label; $label = " - $label" if $label; $self->out("ok ${\ ++$self->{count}}$label"); return; } sub tap_fail { my ($self, $label) = @_; $label = '' unless defined $label; $label = " - $label" if $label; $self->out("not ok ${\ ++$self->{count}}$label"); return; } sub tap_ok { my ($self, $ok, $label) = @_; if ($ok) { $self->tap_pass($label); } else { $self->tap_fail($label); } } sub tap_is { my ($self, $got, $want, $label) = @_; my $ok = $got eq $want; if ($ok) { $self->tap_pass($label); } else { $self->tap_fail($label); $self->show_error( ' got:', $got, ' expected:', $want, $label, ); } } sub tap_isnt { my ($self, $got, $want, $label) = @_; my $ok = $got ne $want; if ($ok) { $self->tap_pass($label); } else { $self->tap_fail($label); $self->show_error( ' got:', $got, ' expected:', 'anything else', $label, ); } } sub tap_like { my ($self, $got, $want, $label) = @_; if ($got =~ $want) { $self->tap_pass($label); } else { $self->tap_fail($label); } } sub tap_unlike { my ($self, $got, $want, $label) = @_; if ($got !~ $want) { $self->tap_pass($label); } else { $self->tap_fail($label); } } sub tap_diag { my ($self, $msg) = @_; my $str = $msg; $str =~ s/^/# /mg; $self->err($str); } sub tap_done { my ($self) = @_; $self->out("1..${\ $self->{count}}"); } sub show_error { my ($self, $got_prefix, $got, $want_prefix, $want, $label) = @_; if ($label) { $self->err("# Failed test '$label'"); } else { $self->err("# Failed test"); } if (not ref $got) { $got = "'$got'" } $self->tap_diag("$got_prefix $got"); if (not ref $want) { $want = "'$want'" } $self->tap_diag("$want_prefix $want"); } sub out { my ($self, $str) = @_; local $| = 1; binmode STDOUT, ':utf8'; print STDOUT "$str$/"; } sub err { my ($self, $str) = @_; binmode STDERR, ':utf8'; print STDERR "$str$/"; } 1; 09perl5lib.tml.lingy100644001750001750 123113605534015 16606 0ustar00ingyingy000000000000Inline-0.86/inc/t{ "testml": "0.3.0", "code": [ ["%<>",["*perl","*paths"], ["==", [".", ["*","perl"], ["derive-minus-i", ["*","paths"]]], ["*","paths"], "Test Inline->derive_minus_I -- +"]]], "data": [ { "label": "TEST 1 - No settings", "point": { "perl": "", "paths": ""}}, { "label": "TEST 2 - Add relative paths to @INC", "point": { "perl": "push @INC, qw(doc eg);\n", "paths": "doc\neg\n"}}, { "label": "TEST 3 - Non-existing paths are removed", "point": { "perl": "push @INC, qw(foo doc bar eg baz);\n", "paths": "doc\neg\n"}}]} MakeMaker000755001750001750 013605534015 15530 5ustar00ingyingy000000000000Inline-0.86/lib/InlineChanges100644001750001750 753213605534015 17172 0ustar00ingyingy000000000000Inline-0.86/lib/Inline/MakeMakerRevision history for Perl extension Inline::MakeMaker. ---version 0.55_03 date Mon 23 Jun 2014 Version updated to 0.55_03 ---version 0.55_02 date Sun 22 Jun 2014 Version updated to 0.55_02 and released to CPAN ---version 0.55_01 date Thurs 19 Jun 2014 Version 0.55_01 released to CPAN ---version 0.55_01 date Tues 17 Jun 2014 Enable building of Inline module bundles (Ticket #95809 - thanks Jason McCarver.) ---version 0.55_01 date Mon 5 May 2014 Update version number to 0.55_01 ---version 0.55 date Mon 28 Apr 2014 Version 0.55 released to CPAN ---version 0.54_05 date Tues 15 Apr 2014 Version 0.54_05 released to CPAN ---version 0.54_05 date Sun 13 Apr 2014 Update version number to 0.54_05 ---version 0.54_04 date Wed 10 Apr 2014 Released to CPAN.(No changes from 0.54_03) ---version 0.54_03 date Wed 9 Apr 2014 Released to CPAN. (No changes from 0.54_01.) --- version 0.54_01 date Mon 31 Mar 2014 Update version number to 0.54_01 --- version 0.54 date Sat 29 Mar 2014 Update version number to 0.54 Release version 0.54 to CPAN --- version 0.53_02 date Fri 7 Mar 2014 Update version number to 0.53_02 --- version 0.53_01 date Thurs 6 Mar 2014 version 0.53_01 released to CPAN --- version 0.53_01 date Thurs 12 Sep 2013 Update version number to 0.53_01 --- version 0.53 date Wed 1 May 2013 version 0.53 released to CPAN --- version 0.52_02 date Wed 24 Apr 2013 version 0.52_02 released to CPAN --- version 0.52_01 date Thurs 11 Apr 2013 version 0.52_01 released to CPAN --- version 0.52 date Thurs 07 Mar 2013 version 0.52 released to CPAN --- version 0.51_03 date: Wed 28 Nov 2012 Version 0.51_03 released to CPAN. --- version 0.51_02 date: Tues 20 Nov 2012 Version 0.51_02 released to CPAN. --- version 0.51_01 date: Tues 20 Nov 2012 Version 0.51_01 released to CPAN. --- version 0.51 date: Sat 13 Oct 2012 Version 0.51 released to CPAN. --- version 0.50_03 date: Mon 8 Oct 2012 Version 0.50_03 released to CPAN. --- version 0.50_02 date: Thur 24 May 2012 Version 0.50_02 released to CPAN. --- version: 0.50_02 date: Tues 14 Feb 2012 MakeMaker.pm - Bump version number to 0.50_02 --- version: 0.50_01 date: Sun 12 Feb 2012 Version 0.50_01 released to CPAN. --- version: 0.50_01 date: Wed 8 Feb 2012 Makemaker.pm - Bump version number to 0.50_01 --- version: 0.50 date: Tues 7 Feb 2012 Version 0.50 released to CPAN Makemaker.pm - Bump version number to 0.50 --- version: 0.49_02 date: Fri 3 Feb 2012 - Bring version numbering into line with recommendations made in http://perldoc.perl.org/perlmodstyle.html#Version-numbering --- version: 0.44 date: Tue Oct 8 11:54:10 PDT 2002 changes: - Made Inline module builds be noisy (show all compiler messages). --- version: 0.44 date: Tue Oct 8 11:54:10 PDT 2002 changes: - Rewrote the whole module. Much simpler and flexible now. 0.41 Tue Jun 5 02:59:53 PDT 2001 - Made dependencies more make like. Works very nice in trees. 0.41 Sun Jun 3 20:34:49 PDT 2001 - Fixed bug. Needed to stack versions as well as names. 0.41 Sun Jun 3 20:34:49 PDT 2001 - Allow MY::postamble in non Inline Makefile.PLs Thanks David Coppit 0.41 Sat Jun 2 19:53:58 PDT 2001 - Fixed to work properly in Makefile.PL hierarchies. Thanks Brett. 0.40 Sun May 13 23:30:02 PDT 2001 - First version of Inline::MakeMaker. Supports installing Inline extensions like regular XS ones. 0.01 Mon May 7 22:30:09 2001 - original version; created by h2xs 1.21 with options -PAXn Inline::MakeMaker t000755001750001750 013605534015 16352 5ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01boo.t100755001750001750 157113605534015 17465 0ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01/tuse warnings; use Boo; use Boo::Far; use Boo::Far::Faz; print "1..6\n"; my $str = Boo::boo(); if($str eq "Hello from Boo") {print "ok 1\n"} else { warn "\n\$str: $str\n"; print "not ok 1\n"; } $str = Boo::Far::boofar(); if($str eq "Hello from Boo::Far") {print "ok 2\n"} else { warn "\n\$str: $str\n"; print "not ok 2\n"; } $str = Boo::Far::Faz::boofarfaz(); if($str eq "Hello from Boo::Far::Faz") {print "ok 3\n"} else { warn "\n\$str: $str\n"; print "not ok 3\n"; } if($Boo::VERSION eq '2.01') {print "ok 4\n"} else { warn "\$Boo::VERSION: $Boo::VERSION\n"; print "not ok 4\n"; } if($Boo::Far::VERSION eq '2.01') {print "ok 5\n"} else { warn "\$Boo::Far::VERSION: $Boo::Far::VERSION\n"; print "not ok 5\n"; } if($Boo::Far::Faz::VERSION eq '2.01') {print "ok 6\n"} else { warn "\$Boo::Far::Faz::VERSION: $Boo::Far::Faz::VERSION\n"; print "not ok 6\n"; } Boo-2.01000755001750001750 013605534015 16107 5ustar00ingyingy000000000000Inline-0.86/example/modulesMANIFEST100755001750001750 16413605534015 17364 0ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01lib/Boo.pm lib/Boo/Far.pm lib/Boo/Far/Faz.pm Makefile.PL MANIFEST This list of files t/boo.t lib000755001750001750 013605534015 16655 5ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01Boo.pm100755001750001750 12213605534015 20050 0ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01/libpackage Boo; $Boo::VERSION = '2.01'; sub boo { return "Hello from Boo"; } 1; Makefile.PL100755001750001750 23313605534015 20202 0ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01use Inline::MakeMaker; WriteMakefile( NAME => 'Boo', VERSION_FROM => 'lib/Boo.pm', clean => { FILES => '_Inline *.inl' }, ); Boo000755001750001750 013605534015 17374 5ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01/libFar.pm100755001750001750 32213605534015 20562 0ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01/lib/Boopackage Boo::Far; $Boo::Far::VERSION = '2.01'; use Inline Config => NAME => 'Boo::Far' => VERSION => '2.01'; use Inline C => <<'EOC'; SV * boofar() { return(newSVpv("Hello from Boo::Far", 0)); } EOC 1; Math-Simple-1.23000755001750001750 013605534015 17513 5ustar00ingyingy000000000000Inline-0.86/example/modulesChanges100755001750001750 17413605534015 21133 0ustar00ingyingy000000000000Inline-0.86/example/modules/Math-Simple-1.23Revision history for Perl extension Math::Simple. 1.23 Sun May 6 22:07:57 2001 - Sample CPAN module using Inline test.pl100755001750001750 30613605534015 21151 0ustar00ingyingy000000000000Inline-0.86/example/modules/Math-Simple-1.23use strict; use Test; BEGIN { plan(tests => 2, todo => [], onfail => sub {}, ); } use Math::Simple qw(add subtract); ok(add(5, 7) == 12); ok(subtract(5, 7) == -2); MANIFEST100755001750001750 5713605534015 20751 0ustar00ingyingy000000000000Inline-0.86/example/modules/Math-Simple-1.23Changes MANIFEST Makefile.PL Simple.pm test.pl Simple.pm100755001750001750 47013605534015 21426 0ustar00ingyingy000000000000Inline-0.86/example/modules/Math-Simple-1.23package Math::Simple; $VERSION = '1.23'; use base 'Exporter'; @EXPORT_OK = qw(add subtract); use strict; use Inline C => 'DATA', VERSION => '1.23', NAME => 'Math::Simple'; 1; __DATA__ __C__ int add (int x, int y) { return x + y; } int subtract (int x, int y) { return x - y; } Far000755001750001750 013605534015 20104 5ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01/lib/BooFaz.pm100755001750001750 35113605534015 21304 0ustar00ingyingy000000000000Inline-0.86/example/modules/Boo-2.01/lib/Boo/Farpackage Boo::Far::Faz; $Boo::Far::Faz::VERSION = '2.01'; use Inline Config => NAME => 'Boo::Far::Faz' => VERSION => '2.01'; use Inline C => <<'EOC'; SV * boofarfaz() { return(newSVpv("Hello from Boo::Far::Faz", 0)); } EOC 1; Makefile.PL100755001750001750 17313605534015 21611 0ustar00ingyingy000000000000Inline-0.86/example/modules/Math-Simple-1.23use Inline::MakeMaker; WriteMakefile( NAME => 'Math::Simple', VERSION_FROM => 'Simple.pm', );