File: implement_indentation.html

package info (click to toggle)
funnelweb-doc 3.2b-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 3,084 kB
  • ctags: 6
  • sloc: perl: 241; makefile: 41
file content (302 lines) | stat: -rw-r--r-- 10,567 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">

<HTML>
<!--
***********************************************************************
FUNNELWEB MANUAL WEB PAGE
=========================
Copyright (c) Ross N. Williams 1995-1999. All rights reserved.

Permission is granted to make and distribute verbatim copies of this
FunnelWeb manual provided that all notices (including, without
limitation, the copyright notice, this permission notice, any record
of modification, and all legal notices) are preserved on all copies.
Modified versions of this manual, including translations to other
languages, may be distributed under the same terms, provided that each
modification made to the manual since its original release by Ross N.
Williams (www.ross.net) is identified on the page on which it occurs,
and the front page of the manual carries a notice notifying the reader
that changes have been made, and referring the reader to the official
FunnelWeb website at www.ross.net/funnelweb/.

To the extent permitted by law there is ABSOLUTELY NO WARRANTY.

***********************************************************************
-->

<HEAD>
<TITLE>3.5 Implementing Text Indentation</TITLE>
<STYLE TYPE="text/css"> <!-- A {text-decoration: none} // --> </STYLE>
</HEAD>
<BODY BACKGROUND="binary/background.gif"
      BGCOLOR="#FFFFFF"
      TEXT="#000000"
      VLINK="#660000"
      LINK="#FF0000"
      ALINK="#CC0000">

<TABLE WIDTH="590">
<TR>
<TD WIDTH="130" VALIGN="top">
<IMG SRC="binary/d_clear.gif" ALT="" WIDTH="130" HEIGHT="1"><BR>

<FONT SIZE="2">
<BR>

<A HREF="http://www.ross.net/"
 TARGET="rosshome"
 onClick="window.open('','rosshome','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
>
 <IMG SRC="binary/rossnet_logo.gif"
  WIDTH="64" HEIGHT="32"
  BORDER="0" ALT="RossNet"
  HSPACE="0" VSPACE="1"></A><BR>
<BR>

<A HREF="../index.shtml"
 TARGET="funnelweb"
 onClick="window.open('','funnelweb','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
>
 <IMG SRC="binary/linklogo.gif"
  WIDTH="64" HEIGHT="32"
  BORDER="0" ALT="FunnelWeb"
  HSPACE="0" VSPACE="1"></A><BR>
<BR>
<A HREF="../reference/index.html"
 TARGET="funnelwebreference"
 onClick="window.open('','funnelwebreference','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
><FONT COLOR="#FFFFFF"><B>Reference</B></FONT></A><BR>
<BR>
<A HREF="../tutorial/index.html"
 TARGET="funnelwebtutorial"
 onClick="window.open('','funnelwebtutorial','location,status,menubar,scrollbars,resizable',false).focus(); return true;"
><FONT COLOR="#FFFFFF"><B>Tutorial</B></FONT></A><BR>
<BR>
<A HREF="index.html"><FONT COLOR="#FFFFFF"><B>Developer</B></FONT></A><BR>
<A HREF="compile.html"><FONT COLOR="#FFFFFF">1 Compile</FONT></A><BR>
<A HREF="design.html"><FONT COLOR="#FFFFFF">2 Design</FONT></A><BR>
<A HREF="implement.html"><FONT COLOR="#FFFFFF">3 Implement</FONT></A><BR>
<A HREF="modify.html"><FONT COLOR="#FFFFFF">4 Modify</FONT></A><BR>
<A HREF="misc.html"><FONT COLOR="#FFFFFF">5 Misc</FONT></A><BR>
<A HREF="gpl.html"><FONT COLOR="#FFFFFF">6 Licence</FONT></A><BR>

<BR>
<A HREF="search.html"><FONT COLOR="#FFFFFF"><B>SEARCH</B></FONT></A><BR>
</FONT>


</TD>
<TD WIDTH="460" VALIGN="top">
<FONT SIZE="3">


<A HREF="index.html"><IMG SRC="binary/title.gif"
 WIDTH="316" HEIGHT="24"
 BORDER="0" ALT="FunnelWeb Developer Manual"
 HSPACE="0" VSPACE="0"></A>
<P><FONT SIZE="5">3.5 Implementing Text Indentation</FONT><BR>



<P>At one point during the development of FunnelWeb, text
indentation was fully implemented. However, it was
subsequently removed because it was considered a dangerous
feature. This section records the way in which text
indentation was implemented so that if the feature ever has
to be put back, this technique can be used again.

<P>1. Create a new field in the <SAMP>sc_t</SAMP> record call
<SAMP>sc_postn</SAMP>.

<P>
<PRE>
      char *sc_postn; /* Pointer in the range [sc_first,sc_last+1].           */
                      /* It is the minimum possible value of sc_postn for     */
                      /* which EOL does not appear in *sc_postn..*sc_last.    */
                      /* i.e. Points to the byte following the first EOL in   */
                      /* the scrap or sc_first if EOL does not appear.        */
</PRE>

<P>2. Modify the scanner so that it generates this field.
Sendtext should be modified so that
it accepts an argument for the <SAMP>p_postn</SAMP> value.

<P>
<PRE>
LOCAL void sendtext P_((p_ps_t,char *,char *,char *,bool));
LOCAL void sendtext(p_tkps,p_first,p_last,p_postn,is_white)
/* Appends a text token to the end of the token list.                         */
/* IN: p_ps is a pointer to a position structure giving the position of the   */
/*     first character of the token.                                          */
/* IN: p_first and p_last point to the first and last byte of the text scrap. */
/* IN: p_postn has the same definition as sc_postn (see fwdata.h).            */
/* IN: is_white should be set to TRUE iff scrap is entirely whitespace.       */
p_ps_t p_tkps;
char  *p_first;
char  *p_last;
char  *p_postn;
bool   is_white;
{
 tk_t token;

 /* Empty text scraps should never be generated. */
 assert(p_first&lt;=p_last,"sendtext: Text scrap bounds are bad.");

 /* If ch=EOL then we should be scanning more text, not shipping it! */
 assert(ch!=EOL,"senttext: Shipping text while still more to scan.");

 /* Check that p_postn is in range. See definition in fwdata.h. */
 assert(p_first&lt;=p_postn && p_postn&lt;=p_last+1,
        "sendtext: p_postn is out of range.");

 /* Debug: Check the p_postn field using a brute force check. */
 {
  char *i,*j;
  j=p_first;
  for (i=p_first;i&lt;=p_last;i++)
     if (*i==EOL)
        j=i+1;
  assert(j==p_postn,"sendtext: sc_postn field is incorrect.");
 }

 /* Load the text token. */
 token.tk_kind        = TK_TEXT;
 ASSIGN(token.tk_ps,*p_tkps);
 token.tk_sc.sc_first = p_first;
 token.tk_sc.sc_last  = p_last;
 token.tk_sc.sc_postn = p_postn;
 token.tk_white       = is_white;
 token.tk_parno       = 0;
 ls_add(token_list,PV &token);
}
</PRE>

<P>Then all the calls to sendtext have to be changed:

<PRE>
/* @ instructs FunnelWeb to replace the special construct with the */
/* special character. Luckily one appears just before the @ !!     */
/* Note: FALSE is OK because space is not a legal specialch.       */
/* Note: Setting parameter p_postn to p_ch-1 is OK as EOL is not a */
/*       legal specialch.                                          */
sendtext(ps_spec,p_ch-1,p_ch-1,p_ch-1,FALSE);
break;

/* + instructs FunnelWeb to insert an EOL. We can't look to the end of */
/* the previous line to find an EOL as this might be the first line.   */
/* Running ahead to the end of the line is expensive, and having the   */
/* liner mini-package maintain a variable for it would be extra        */
/* housekeeping. Instead of all this, we just point to a static.       */
{CONST static char stateol = EOL;
 sendtext(&ps_spec,&stateol,&stateol,(&stateol)+1,TRUE);}
break;

/* If we hit something that ends a text token */
/* then we can transmit a white text token.   */
if (ch==specialch || ch==EOFCH)
   {sendtext(&ps_start,p_first,p_ch-1,MAX(p_sol,p_first),TRUE); return;}

/* Otherwise we have some more (non-white) text to scan. */
/* We can then send a non-white text token.              */
while (ch!=specialch && ch!=EOFCH)
   NEXTCH;
sendtext(&ps_start,p_first,p_ch-1,MAX(p_sol,p_first),FALSE);
</PRE>

The dump code needs to be changed too!

<PRE>
        wf_str(p_wf,"\"");
assert(token-&gt;tk_sc.sc_first !=NULL,"dm_tkls: NULL ptr1.");
assert(token-&gt;tk_sc.sc_last  !=NULL,"dm_tkls: NULL ptr2.");
for (i=token-&gt;tk_sc.sc_first; i&lt;=token-&gt;tk_sc.sc_last; i++)
  {
   if (i==token-&gt;tk_sc.sc_postn)
      wf_str(p_wf,"&lt;postn&gt;");
   if (*i=='\n')
      wf_wl(p_wf,"");
   else
      dm_byte(p_wf,*((ubyte_ *) i));
  }
if (i==token-&gt;tk_sc.sc_postn)
   wf_str(p_wf,"&lt;postn&gt;");
wf_str(p_wf,"\"");
}
</PRE>

<P>3. Over in the Tangle module, create a massive array of
pointers to scraps to be used as a stack. Maintain pointers
into the stack called <SAMP>current</SAMP> and <I>base</I>&nbsp;
(similar to the blank indentation variables). Implement the
following:

<P>
<UL>

<LI> To write out a scrap, scan it byte by byte. Output
each byte. When you hit an EOL, pop the stack back to
<SAMP>base</SAMP>. Then write out an EOL followed by the stack
contents but writing each scrap only from <SAMP>postn</SAMP> to
end end of each scrap. When you have finished the new scrap,
push it on the stack.

<LI> When you hit a new macro to expand, save
<SAMP>base</SAMP>. Restore it later.

</UL>

<P>The <SAMP>postn</SAMP> field solves the big problem of how
to cope with something like this:

<P>
<PRE>
The rain in Spain
falls mainly @&lt;on the plain@&gt;
</PRE>

<P>The trouble is that we want to text indent the lines in
<SAMP>@&lt;on the plain@&gt;</SAMP> with just "<TT>falls
                                                   mainly&nbsp;</TT>". However, this string is only part of a scrap. The
solution is to get the scanner to record, in the
<SAMP>postn</SAMP> field of each scrap, the position of the
first byte with a EOL-free run to the end of the scrap.

<P>This scheme is very efficient because all we are doing
is pushing and popping pointers to scraps on a stack array.
The main disadvantage is that the array must necessarily be
finite and would impose a limit on the depth of indentation
nesting.


<P>
<TABLE WIDTH="100%">
<TR>
<TD ALIGN="left"   VALIGN="bottom"><A HREF="implement_memory.html"><IMG SRC="binary/fw_left.gif" HEIGHT="32" WIDTH="32" BORDER="0" ALT="Prev"></A></TD>
<TD ALIGN="center" VALIGN="bottom"><A HREF="implement.html"><IMG SRC="binary/fw_up.gif" HEIGHT="32" WIDTH="32" BORDER="0" ALT="Up"></A></TD>
<TD ALIGN="right"  VALIGN="bottom"><A HREF="implement.html"><IMG SRC="binary/fw_up.gif" HEIGHT="32" WIDTH="32" BORDER="0" ALT="Up"></A></TD>
</TR>
</TABLE>



<P>
<HR>
<FONT SIZE="2">
<A HREF="mailto:webmaster@ross.net">Webmaster</A>&nbsp;&nbsp;&nbsp;
<A HREF="copyright.html">Copyright &copy; Ross N. Williams 1992,1999. All rights reserved.</A><BR>
</FONT>

</FONT>
</TD>
</TR>
</TABLE>


</BODY>

<!-- *********************************************************************** -->
<!--      End Of A FunnelWeb Manual Web Page (www.ross.net/funnelweb/)       -->
<!-- *********************************************************************** -->

</HTML>