⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch24_05.htm

📁 编程珍珠,里面很多好用的代码,大家可以参考学习呵呵,
💻 HTM
字号:
<html><head><title>Program Generation (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly &amp; Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Program Generation"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch24_04.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="ch24_01.htm">Chapter 24: Common Practices</a></td><td align="right" valign="top" width="172"><a href="ch25_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">24.5. Program Generation</h2><p><a name="INDEX-4284"></a><a name="INDEX-4285"></a>Almost from the time people first figured out that they could writeprograms, they started writing programs that write other programs.  Weoften call these <em class="emphasis">program generators</em>.  (If you'rea history buff, you might know that RPG stood for Report ProgramGenerator long before it stood for Role Playing Game.)  Nowadaysthey'd probably be called "program factories", but the generatorpeople got there first, so they got to name it.</p><p>Now, anyone who has written a program generator knows that it can makeyour eyes go crossed even when you're wide awake.  The problem issimply that much of your program's data looks like real code, but isn't(at least not yet).  The same text file contains both stuff that doessomething and similar looking stuff that doesn't.  Perl has variousfeatures that make it easy to mix Perl together with other languages,textually speaking.</p><p>(Of course, these features also make it easier to write Perl in Perl, butthat's rather to be expected by now, we should think.)</p><h3 class="sect2">24.5.1. Generating Other Languages in Perl</h3><p><a name="INDEX-4286"></a><a name="INDEX-4287"></a>Perl is (among other things) a text-processing language, and most computerlanguages are textual.  Beyond that, Perl's lack of arbitrary limitstogether with the various quoting and interpolation mechanisms make it easy to visually isolate the code of the other language you'respitting out. For example, here is a small chunk of <em class="emphasis">s2p</em>, the<em class="emphasis">sed</em>-to-<em class="emphasis">perl</em> translator:<blockquote><pre class="programlisting">print &amp;q(&lt;&lt;"EOT");:       #!$bin/perl:       eval 'exec $bin/perl -S \$0 \${1+"\$@"}':               if \$running_under_some_shell;:       EOT</pre></blockquote>Here the enclosed text happens to be legal in two languages, both Perland <em class="emphasis">sh</em>.  We've used an idiom right off the batthat will preserve your sanity in the writing of a program generator:the trick of putting a "noise" character and a tab on the front ofevery quoted line, which visually isolates the enclosed code, so youcan tell at a glance that it's not the code that is actually beingexecuted.  One variable, <tt class="literal">$bin</tt>, is interpolated inthe multiline quote in two places, and then the string is passedthrough a function to strip the colon and tab.</p><p>Of course, you aren't required to use multiline quotes.  One oftensees CGI scripts containing millions of <tt class="literal">print</tt>statements, one per line. It seems a bit like driving to church in anF-16, but hey, if it gets you there... (We will admit that a columnof <tt class="literal">print</tt> statements has its own form of visualdistinctiveness.)</p><p>When you are embedding a large, multiline quote containing some otherlanguage (such as HTML), it's often helpful to pretend you'reprogramming inside-out, enclosing Perl into the other languageinstead, much as you might do with overtly everted languages such asPHP:<blockquote><pre class="programlisting">print &lt;&lt;"XML";    &lt;stuff&gt;    &lt;nonsense&gt;    blah blah blah @{[ scalar <em class="emphasis">EXPR</em> ]} blah blah blah    blah blah blah @{[ <em class="emphasis">LIST</em> ]} blah blah blah    &lt;/nonsense&gt;    &lt;/stuff&gt;XML</pre></blockquote>You can use either of those two tricks to interpolate the values ofarbitrarily complicated expressions into the long string.</p><p>Some program generators don't look much like program generators,depending on how much of their work they hide from you.  In <a href="ch22_01.htm">Chapter 22, "CPAN"</a>, we saw how a small<em class="emphasis">Makefile.PL</em> program could be used to write a<em class="emphasis">Makefile</em>.  The <em class="emphasis">Makefile</em> caneasily be 100 times bigger than the <em class="emphasis">Makefile.PL</em>that produced it.  Think how much wear and tear that saves yourfingers.  Or don't think about it--that's the point, after all.</p><a name="ch24-sect-gen"></a><h3 class="sect2">24.5.2. Generating Perl in Other Languages</h3><p><a name="INDEX-4288"></a><a name="INDEX-4289"></a>It's easy to generate other languages in Perl, but the converse is alsotrue.  Perl can easily be generated in other languages because it'sboth concise and malleable.  You can pick your quotes not to interferewith the other language's quoting mechanisms.  You don't have to worryabout indentation, or where you put your line breaks, or whether tobackslash your backslashes Yet Again.  You aren't forced to define apackage as a single string in advance, since you can slide into yourpackage's namespace repeatedly, whenever you want to evaluate more codein that package.</p><p><a name="INDEX-4290"></a><a name="INDEX-4291"></a><a name="INDEX-4292"></a><a name="INDEX-4293"></a>Another thing that makes it easy to write Perl in other languages(including Perl) is the <tt class="literal">#line</tt> directive.  Perlknows how to process these as special directives that reconfigure itsidea of the current filename and line number.  This can be useful inerror or warning messages, especially for strings processed with<tt class="literal">eval</tt> (which, when you think about it, is just Perlwriting Perl).  The syntax for this mechanism is the one used by the Cpreprocessor: when Perl encounters a <tt class="literal">#</tt> symbol andthe word <tt class="literal">line</tt>, followed by a number and a filename,it sets <tt class="literal">__LINE__</tt> to the number and<tt class="literal">__FILE__</tt> to the filename.<a href="#FOOTNOTE-3">[3]</a></p><blockquote class="footnote"><a name="FOOTNOTE-3"></a><p>[3]Technically, it matches the pattern<tt class="literal">/^#\s*line\s+(\d+)\s*(?:\s"([^"]+)")?\s*$/</tt>, with<tt class="literal">$1</tt> providing the line number for the next line, and<tt class="literal">$2</tt> providing the optional filename specified withinquotes.  (A null filename leaves <tt class="literal">__FILE__</tt>unchanged.)</p></blockquote><p><a name="INDEX-4294"></a><a name="INDEX-4295"></a><a name="INDEX-4296"></a><a name="INDEX-4297"></a><a name="INDEX-4298"></a>Here are some examples that you can test by typing into <em class="emphasis">perl</em>directly.  We've used a Control-D to indicate end-of-file, which istypical on Unix.  DOS/Windows and VMS users can type Control-Z.  If your shelluses something else, you'll have to use that to tell <em class="emphasis">perl</em> you'redone.  Alternatively, you can always type in <tt class="literal">__END__</tt> to tell the compilerthere's nothing left to parse.</p><p>Here, Perl's built-in <tt class="literal">warn</tt> function prints out the new filename andline number:<blockquote><pre class="programlisting">% <tt class="userinput"><b>perl# line 2000 "Odyssey"# the "#" on the previous line must be the first char on linewarn "pod bay doors";  # or die^D</b></tt>pod bay doors at Odyssey line 2001.</pre></blockquote>And here, the exception raised by <tt class="literal">die</tt> within the <tt class="literal">eval</tt> found itsway into the <tt class="literal">$@</tt> (<tt class="literal">$EVAL_ERROR</tt>) variable, along with thetemporary new filename and line:<blockquote><pre class="programlisting"><tt class="userinput"><b># line 1996 "Odyssey"eval qq{#line 2025 "Hal"    die "pod bay doors";};print "Problem with $@";warn "I'm afraid I can't do that";^D</b></tt>Problem with pod bay doors at Hal line 2025.I'm afraid I can't do that at Odyssey line 2001.</pre></blockquote>This shows how a <tt class="literal">#line</tt> directive affects only the currentcompilation unit (file or <tt class="literal">eval</tt><em class="replaceable">STRING</em>), and that when that unitis done being compiled, the previous settings are automaticallyrestored.  This way you can set up your own messages inside an <tt class="literal">eval</tt><em class="replaceable">STRING</em> or <tt class="literal">do</tt><em class="replaceable">FILE</em> without affecting the rest of yourprogram.</p><p>Perl has a <span class="option">-P</span> switch that invokes the C preprocessor, which emits<tt class="literal">#line</tt> directives.  The C preprocessor was the original impetus forimplementing <tt class="literal">#line</tt>, but it is seldom used these days, since thereare usually better ways to do what we used to rely on it for.  Perl hasa number of other preprocessors, however, including the <tt class="literal">AutoSplit</tt>module.  The JPL (Java Perl Lingo) preprocessor turns <em class="emphasis">.jpl</em> filesinto <em class="emphasis">.java</em>, <em class="emphasis">.pl</em>, <em class="emphasis">.h</em>, and <em class="emphasis">.c</em> files.  It makes use of<tt class="literal">#line</tt> to keep the error messages accurate.</p><p><a name="INDEX-4299"></a><a name="INDEX-4300"></a><a name="INDEX-4301"></a>One of the very first Perl preprocessors was the <em class="emphasis">sed</em>-to-<em class="emphasis">perl</em>translator, <em class="emphasis">s2p</em>.  In fact, Larry delayed the initial release of Perlin order to complete <em class="emphasis">s2p</em> and <em class="emphasis">awk</em>-to-<em class="emphasis">perl</em> (<em class="emphasis">a2p</em>), because hethought they'd improve the acceptance of Perl.  Hmm, maybe they did.</p><p>See the online docs for more on these, as well as the <em class="emphasis">find2perl</em>translator.</p><h3 class="sect2">24.5.3. Source Filters</h3><p><a name="INDEX-4302"></a><a name="INDEX-4303"></a><a name="INDEX-4304"></a><a name="INDEX-4305"></a>If you can write a program to translate random stuff into Perl, thenwhy not have a way of invoking that translator from within Perl?</p><p>The notion of a source filter started with the idea that a script ormodule should be able to decrypt itself on the fly, like this:<blockquote><pre class="programlisting">#!/usr/bin/perluse MyDecryptFilter;@*x$]`0uN&amp;k^Zx02jZ^X{.?s!(f;9Q/^A^@~~8H]|,%@^P:q-=...</pre></blockquote>But the idea grew from there, and now a source filter can be defined todo any transformation on the input text you like.Put that together with the notion of the <span class="option">-x</span> switch mentioned in<a href="ch19_01.htm">Chapter 19, "The Command-Line Interface"</a>, and you have a generalmechanism for pulling any chunk of program out of a message andexecuting it, regardless of whether it's written in Perl or not.</p><p>Using the <tt class="literal">Filter</tt> module from CPAN, one can now even do things likeprogramming Perl in <em class="emphasis">awk</em>:<blockquote><pre class="programlisting">#!/usr/bin/perluse Filter::exec "a2p";         # the awk-to-perl translator1,30 { print $1 }</pre></blockquote>Now that's definitely what you might call idiomatic.  But we won't pretendfor a moment that it's common practice.</p><a name="INDEX-4306"></a><a name="INDEX-4307"></a><!-- BOTTOM NAV BAR --><hr width="515" align="left"><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch24_04.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="index.htm"><img src="../gifs/txthome.gif" alt="Home" border="0"></a></td><td align="right" valign="top" width="172"><a href="ch25_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">24.4. Fluent Perl</td><td align="center" valign="top" width="171"><a href="index/index.htm"><img src="../gifs/index.gif" alt="Book Index" border="0"></a></td><td align="right" valign="top" width="172">25. Portable Perl</td></tr></table></div><hr width="515" align="left"><!-- LIBRARY NAV BAR --><img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p><font size="-1"><a href="copyrght.htm">Copyright &copy; 2001</a> O'Reilly &amp; Associates. All rights reserved.</font></p><map name="library-map"> <area shape="rect" coords="2,-1,79,99" href="../index.htm"><area shape="rect" coords="84,1,157,108" href="../perlnut/index.htm"><area shape="rect" coords="162,2,248,125" href="../prog/index.htm"><area shape="rect" coords="253,2,326,130" href="../advprog/index.htm"><area shape="rect" coords="332,1,407,112" href="../cookbook/index.htm"><area shape="rect" coords="414,2,523,103" href="../sysadmin/index.htm"></map><!-- END OF BODY --></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -