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

📄 ch31.htm

📁 《Perl 5 Unreleased》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
&quot;,$len;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;printf EncD &quot;\nstrncat((STRPTR )(&amp;buffer[%d]),tempbuffer,%d);&quot;,

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$from-1,$len;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

&nbsp;&nbsp;&nbsp;&nbsp;if ($vtype =~ /int/) {<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($len == 1)

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf

EncD &quot;\nsp-&gt;%s %%= 10;&quot;, $vname;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf

EncD &quot;\ntempbuffer[%d] = (char)('0' + sp-&gt;%s);&quot;,

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$from-1,$vname;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf

EncD &quot;\ntempbuffer[%d] = 0; &quot;,$from;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf EncD &quot;\nsprintf(tempbuffer,\&quot;%%d%d\&quot;,(sp-&gt;%s));&quot;,$len,$vname;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf EncD &quot;\ntempbuffer[%d]=

0; &quot;,$len;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf EncD &quot;\nstrncat((STRPTR

)(&amp;buffer[%d]),tempbuffer,%d);&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$from-1,$len;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

} # end of subroutine.</FONT></TT>

</BLOCKQUOTE>

<H2><A NAME="WritingtheDecoder"><B><FONT SIZE=5 COLOR=#FF0000>Writing

the Decoder</FONT></B></A></H2>

<P>

The decoder source file is created in almost exactly the same

way that the encoder file is created. The preamble for the decoder

file includes the <TT><FONT FACE="Courier">#include</FONT></TT>

statement for the <TT><FONT FACE="Courier">P286.h</FONT></TT>

header file, which is also being created. It also makes a reference

to the <TT><FONT FACE="Courier">padTo80</FONT></TT> function in

the encoder file (should this extra function be required).

<P>

The decoder file also generates code to extract a substring from

another string given the offset and length to extract. The function

may be used on systems that have a broken <TT><FONT FACE="Courier">strncpy</FONT></TT>

(just like my old, in-house version of the C compiler for a Motorola

6809E microprocessor).

<P>

Here's the code to generate the decoder source file preamble:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">sub startDecoderFile {<BR>

print (DECD &quot;\/**\n* C source file to decode records.&quot;,

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot; \nDon't edit this file\n &quot;,

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;*/\n&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;'#include &quot;p286.h&quot; ',<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\n&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\n/* The outgoing buffer must be

81 chars! */&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\nextern void padTo80(STRPTR buffer);

\n&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\n&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\n/* The outgoing buffer must also

be 81 chars! */&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\nvoid substr(STRPTR buffer,STRPTR

cut,int offset, int len)\n{\n&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;int i,j; \nj = offset;\n&quot;,

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;for(i=len;i&lt;80;i++) cut[i] =

buffer[j]; \n &quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;cut[len] = 0; /* NULL terminate

the string*/&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\n} /* end of padding function */\n&quot;,

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&quot;\n&quot;);<BR>

}</FONT></TT>

</BLOCKQUOTE>

<P>

Each <TT><FONT FACE="Courier">RECORD</FONT></TT> and <TT><FONT FACE="Courier">ENDREC</FONT></TT>

pair in the input file causes a call to the Perl subroutines <TT><FONT FACE="Courier">startDecoderFunction()</FONT></TT>

and <TT><FONT FACE="Courier">closeDecoderFunction()</FONT></TT>,

respectively. The first subroutine creates the preamble to decode

a string into a structure. The second subroutine prints the closing

brace for a function. The code for the two functions is shown

here:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">sub startDecoderFunction {<BR>

&nbsp;&nbsp;&nbsp;&nbsp;my($vname) = @_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#

Pick up name of record.<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;\n/*: &quot;;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;\n** Generated by Perl

script -- Avoid editing &quot;;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;\n** The outgoing buffer

must also be 81 chars!&quot;;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;\n*/\n&quot;;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;printf DECD&nbsp;&nbsp;&quot;void decode_%s_type(P286_%s_PTR

sp,STRPTR buffer)\n{&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$vname, $vname;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;\nSTRPTR cp; \n&quot;;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;register int i; \n&quot;;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;char tempbuffer[80];\n&quot;;

<BR>

}<BR>

<BR>

sub closeDecoderFunction {<BR>

&nbsp;&nbsp;&nbsp;&nbsp;print DECD &quot;\n} /* End of decoding

function */ \n&quot;;<BR>

}</FONT></TT>

</BLOCKQUOTE>

<P>

Finally, the <TT><FONT FACE="Courier">decodeVariable</FONT></TT>

function is called when a variable is encountered. The type of

variable dictates how to read the value from a substring in the

incoming buffer. The name of the variable is set to be a scalar

or the member of an array before the call is made. Therefore,

the Perl subroutine simply uses the value of <TT><FONT FACE="Courier">$vname</FONT></TT>

verbatim:

<BLOCKQUOTE>

<TT><FONT FACE="Courier">sub decodeVariable {<BR>

&nbsp;&nbsp;&nbsp;&nbsp;my ($vname,$vtype,$from,$to,$fmt) = @_;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;my&nbsp;&nbsp;$len = $to - $from + 1;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\n&quot;;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;if ($vtype =~ /char/)<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\nstrncpy(sp-&gt;%s,(STRPTR

)(&amp;buffer[%d]),%d);&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$vname,$from-1,$len;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\nsp-&gt;%s[%d]=

0; &quot;,$vname,$len;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

&nbsp;&nbsp;&nbsp;&nbsp;if ($vtype =~ /double/)<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\nstrncpy(tempbuffer,(STRPTR

)(&amp;buffer[%d]),%d);&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$from-1,$len;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\ntempbuffer[%d]=

0; &quot;,$len;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\nsscanf(tempbuffer,\&quot;%%%sf\&quot;,&amp;(sp-&gt;%s));&quot;,

$fmt,$vname;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

&nbsp;&nbsp;&nbsp;&nbsp;if ($vtype =~ /int/)<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\nstrncpy(tempbuffer,(STRPTR

)(&amp;buffer[%d]),%d);&quot;,<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$from-1,$len;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\ntempbuffer[%d]=

0; &quot;,$len;<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf DECD &quot;\nsscanf(tempbuffer,\&quot;%%%dd\&quot;,&amp;(sp-&gt;%s));&quot;,$len,$vname;

<BR>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>

}</FONT></TT>

</BLOCKQUOTE>

<H2><A NAME="PuttingItTogether"><B><FONT SIZE=5 COLOR=#FF0000>Putting

It Together</FONT></B></A></H2>

<P>

Here are the input and output files generated from the code fragments

shown previously. The input file shown here has only five records

in it. The actual file had 52 record types, and I applied the

same methodology to three types of similar formats. Here is a

breakdown of the listings:

<UL>

<LI><FONT COLOR=#000000>Listing 31.2. The header file generated

from Perl.</FONT>

<LI><FONT COLOR=#000000>Listing 31.3. The encoder file </FONT><TT><FONT FACE="Courier">P286enc.c</FONT></TT>.

<LI><FONT COLOR=#000000>Listing 31.4. The encoder file </FONT><TT><FONT FACE="Courier">P286dec.c</FONT></TT>.

<LI><FONT COLOR=#000000>Listing 31.5. The full listing for the

code generator.</FONT>

</UL>

<P>

<HR>

<BLOCKQUOTE>

<B>Listing 31.2. The </B><TT><B><FONT FACE="Courier">P286.h</FONT></B></TT><B>

header file.<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;1 #ifndef P286_HDRS<BR>

&nbsp;2 #define P286_HDRS 1<BR>

&nbsp;3 #define STRPTR&nbsp;&nbsp; char *<BR>

&nbsp;4<BR>

&nbsp;5 #define P286_H0001_RECTYPE 0<BR>

&nbsp;6<BR>

&nbsp;7 typedef struct p286_H0001_type {<BR>

&nbsp;8&nbsp;&nbsp;char SurveyType[53]; /* 29 80 */<BR>

&nbsp;9 }P286_H0001_TYPE,*P286_H0001_PTR;<BR>

10<BR>

11 #define P286_H0010_RECTYPE 1<BR>

12<BR>

13 typedef struct p286_H0010_type {<BR>

14&nbsp;&nbsp;int numPatterns; /* 6 7 */<BR>

15&nbsp;&nbsp;int sblInUse; /* 8 8 */<BR>

16&nbsp;&nbsp;int sattInUse; /* 9 9 */<BR>

17&nbsp;&nbsp;int numVessels; /* 10 10 */<BR>

18&nbsp;&nbsp;int numDatum; /* 11 11 */<BR>

19&nbsp;&nbsp;int offsetMode; /* 12 12 */<BR>

20 }P286_H0010_TYPE,*P286_H0010_PTR;<BR>

21<BR>

22 #define P286_H011_RECTYPE 2<BR>

23<BR>

24 typedef struct p286_H011_type {<BR>

25&nbsp;&nbsp;int datumId; /* 5 5 */<BR>

26&nbsp;&nbsp;char spheroidName[19]; /* 6 23 */<BR>

27&nbsp;&nbsp;char datumName[19]; /* 24 41 */<BR>

28&nbsp;&nbsp;double semimajorAxis; /* 42 53 */<BR>

29&nbsp;&nbsp;double conversionFactor; /* 66 77 */<BR>

30&nbsp;&nbsp;double inverseFlattening; /* 66 77 */<BR>

31 }P286_H011_TYPE,*P286_H011_PTR;<BR>

32<BR>

33 #define P286_E3100_RECTYPE 3<BR>

34<BR>

35 typedef struct p286_E3100_type {<BR>

36&nbsp;&nbsp;double velprop; /* 6 12 */<BR>

37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int srcNdx[5]; /* from 13 15 */

<BR>

38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int dstNdx[5]; /* from 16 18 */

<BR>

39&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;double slant[5]; /* from 19 25

*/<BR>

40 }P286_E3100_TYPE,*P286_E3100_PTR;<BR>

41<BR>

42 #endif</FONT></TT>

</BLOCKQUOTE>

<HR>

<HR>

<BLOCKQUOTE>

<B>Listing 31.3. The encoder file </B><TT><B><FONT FACE="Courier">P286enc.c</FONT></B></TT><B>.

<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><FONT FACE="Courier">&nbsp;&nbsp;1 /*** C source file to encode

records.<BR>

&nbsp;&nbsp;2 Don't edit this file<BR>

&nbsp;&nbsp;3&nbsp;&nbsp;*/<BR>

&nbsp;&nbsp;4 #include &quot;p286.h&quot;<BR>

&nbsp;&nbsp;5<BR>

&nbsp;&nbsp;6 /* The incoming buffer must be 81 chars! */<BR>

&nbsp;&nbsp;7 void padTo80(STRPTR buffer)<BR>

&nbsp;&nbsp;8 {<BR>

&nbsp;&nbsp;9 int i,ln;<BR>

&nbsp;10 ln = strlen(buffer);<BR>

&nbsp;11 for(i=ln;i&lt;80;i++) buffer[i] = ' ';<BR>

&nbsp;12&nbsp;&nbsp;buffer[81] = 0; /* NULL terminate the string*/

<BR>

&nbsp;13 } /* end of padding function */<BR>

&nbsp;14<BR>

&nbsp;15<BR>

&nbsp;16 /*:<BR>

&nbsp;17 ** Generated by Perl script -- Avoid editing<BR>

&nbsp;18 */<BR>

&nbsp;19 void encode_H0001_type(STRPTR buffer,P286_H0001_PTR sp)

<BR>

&nbsp;20 {<BR>

&nbsp;21 STRPTR ncp;<BR>

&nbsp;22<BR>

&nbsp;23 STRPTR cp;<BR>

&nbsp;24 register int i;<BR>

&nbsp;25 char tempbuffer[80];<BR>

&nbsp;26<BR>

&nbsp;27<BR>

&nbsp;28 /* Encode:char,SurveyType,29,80,52, */<BR>

&nbsp;29 cp = (STRPTR )&amp;(buffer[28]);<BR>

&nbsp;30 for (i=0; i&lt; 52;i++)<BR>

&nbsp;31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer[28 + i] = sp-&gt;SurveyType[i];

<BR>

⌨️ 快捷键说明

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