| SM Ryan 2007-04-21, 4:13 am |
| \f3\b0 (;;) \{\
\f2\b if
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ==META) \{\
\f2\b while
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 'adEOI
\f6 \uc0\u8743
\f3
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 'adATEM)\
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b if
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ==ATEM)
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\}
\f2\b else
\f3\b0
\f2\b if
\f3\b0 (Tcl_UniCharIsSpace(
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 )) \{\
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\}
\f2\b else
\f3\b0 \
\f2\b break
\f3\b0 ;\
\}\
\f2\b if
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ==
\f7\i startdelimiter
\f3\i0 )
\f7\i startparameters
\f3\i0 =
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b else
\f7\i\b0 macrodef
\f3\i0 = 0;\
\}\
\}\
\f2\b if
\f3\b0 (
\f7\i macrodef
\f3\i0 ) \{\
\
\f4\i This is a macro name with no parameters or the openning bracket has\
been found. Push the macro on the stack of partially parsed macros;\
once the call is completed it will be popped and expanded.\
\f3\i0 \
\f2\b Stack
\f3\b0
\f7\i t
\f3\i0 = heap(
\f2\b struct
\f3\b0
\f2\b Stack
\f3\b0 );
\f7\i t
\f6\i0 \uc0\u8594
\f7\i under
\f3\i0 =
\f7\i sp
\f3\i0 ;
\f2\b
\f7\i\b0 sp
\f3\i0 =
\f7\i t
\f3\i0 ;\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 = incr(Tcl_NewListObj(1, &
\f7\i macrodef
\f6\i0 \uc0\u8594
\f7\i name
\f3\i0 ));
\f2\b \
\f3\b0
\f2\b int
\f7\i\b0 nsep
\f3\i0 ;
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i separator
\f3\i0 = Tcl_GetUnicodeFromObj(
\f7\i macrodef
\f6\i0 \uc0\u8594
\f7\i separators
\f3\i0 , &
\f7\i nsep
\f3\i0 );
\f2\b \
\f3\b0
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i depth
\f3\i0 = 0;\
\f2\b if
\f3\b0 (
\f7\i nsep
\f3\i0 ) \{\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i begin
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i separator
\f3\i0 [0];
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i end
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i separator
\f3\i0 [
\f7\i nsep
\f3\i0 -1];\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i separator
\f3\i0 += 1;\
\}
\f2\b else
\f3\b0
\f7\i \
\f3\i0
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i begin
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i end
\f3\i0 = 0;\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startname
\f3\i0 =
\f7\i startname
\f3\i0 ;
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startgap
\f3\i0 =
\f7\i startgap
\f3\i0 ;\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startparameters
\f3\i0 =
\f7\i startparameters
\f3\i0 ;\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i parameter
\f3\i0 =
\f7\i source
\f3\i0 ;\
\}\
\}\
\f2\b <>
\f3\b0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f1 \cf0 \
After that it needs to find all the argument separators in order up to the closing delimiter. Whilst recognising a argument, the only characters which are signficant are terminating character of the parameter and the opening and closing characters of the
interface which must be properly nested.\
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b <
\f3\b0 separateParametersOfAMacroCall
\f2\b >\
\f3\b0
\f2\b if
\f3\b0 (
\f7\i sp
\f6\i0 \uc0\u8743
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc==sp
\f6\i0 \uc0\u8594
\f7\i separator
\f3\i0 [0]
\f6 \uc0\u8743
\f3
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i depth
\f3\i0 ==0) \{\
\f2\b Obj
\f3\b0
\f7\i parameter
\f3\i0 = substring(
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i parameter, source
\f3\i0 ,
\f2\b false
\f3\b0 );\
\f2\b Obj
\f3\b0
\f7\i stripped
\f3\i0 = substring(
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i parameter, source
\f3\i0 ,
\f2\b true
\f3\b0 );\
Tcl_ListObjAppendElement(0,
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 ,
\f7\i parameter
\f3\i0 ); decr(
\f7\i parameter
\f3\i0 );\
Tcl_ListObjAppendElement(0,
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 ,
\f7\i stripped
\f3\i0 ); decr(
\f7\i stripped
\f3\i0 );\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i parameter = source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i separator
\f3\i0 += 1;\
\}
\f2\b else if
\f3\b0 (
\f7\i sp
\f6\i0 \uc0\u8743
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc==sp
\f6\i0 \uc0\u8594
\f7\i begin
\f3\i0 ) \{\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i depth
\f3\i0 += 1;
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\}
\f2\b else if
\f3\b0 (
\f7\i sp
\f6\i0 \uc0\u8743
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc==sp
\f6\i0 \uc0\u8594
\f7\i end
\f3\i0 ) \{\
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i depth
\f3\i0 -= 1;
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\}\
\f2\b <>
\f3\b0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f1 \cf0 \
That macro body is then called with a temporary, empty accumulation area. Whatever it leaves in the accumulation area is taken as the macro expansion. If the macro returns an error, the error message is embedded in its expansion. If the macro returns norm
ally, the returned value is ignored. Since the macro body can include Tcl commands, any Tcl code can be evaluated as part of that macro expansion.\
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b <
\f3\b0 expandAMacroCall
\f2\b >\
if
\f3\b0 (
\f7\i sp
\f3\i0
\f6 \uc0\u8743
\f3
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i separator
\f3\i0 [0]==0) \{\
\f2\b
\f3\b0 expandAMacroCallTraceBeforeExpansion;\
\
\f4\i Call the macro expansion proc. If expansion is limitted and the limit\
exceeded, this is replaced instead with an error.
\f1\i0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\cf0
\f3 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\cf0
\f2\b int
\f7\i\b0 macrocount0
\f3\i0 =
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i macrocount
\f3\i0 ;
\f2\b \
\f3\b0
\f2\b int
\f3\b0
\f7\i rc
\f3\i0 =
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i limitted
\f3\i0
\f6 \uc0\u8743
\f3 --(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i limit
\f3\i0 )<0\
? (Tcl_SetResult(
\f7\i intr
\f3\i0 , "macro expansion iteration limit", TCL_STATIC), TCL_ERROR)\
: Tcl_EvalObjEx(
\f7\i intr
\f3\i0 ,
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 , TCL_EVAL_DIRECT);\
\f2\b AttrString
\f3\b0
\f7\i replacement
\f3\i0 = first(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 );\
\f2\b AttrString
\f3\b0
\f7\i endreplacement
\f3\i0 = last(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i output
\f3\i0 );\
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 = 0;
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i output
\f3\i0 = 0;\
\
\f4\i If the expansion is an error, embed the Tcl error in the accumulation buffer\
as an embedded error directive.
\f1\i0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\cf0
\f3 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\cf0
\f2\b if
\f3\b0 (
\f7\i rc
\f3\i0 ==TCL_ERROR) \{\
\f2\b AttrString
\f3\b0
\f7\i first
\f3\i0 =
\f7\i replacement
\f3\i0 ?
\f7\i replacement
\f3\i0 :
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startname
\f3\i0 ;\
\f2\b Obj
\f3\b0
\f7\i e
\f3\i0 = oprintf(0, "%Merror %s", Tcl_GetStringResult(
\f7\i intr
\f3\i0 ));\
\f2\b AttrString
\f3\b0
\f7\i E
\f3\i0 = attrstring(0,
\f7\i first
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 ,
\f7\i e
\f3\i0 ,0,0); decr(
\f7\i e
\f3\i0 );\
cat(last(
\f7\i E
\f3\i0 ),
\f7\i replacement
\f3\i0 );\
\f7\i replacement
\f3\i0 =
\f7\i E
\f3\i0 ;\
\f2\b if
\f3\b0 ('c2
\f7\i endreplacement
\f3\i0 )
\f7\i endreplacement
\f3\i0 = last(
\f7\i E
\f3\i0 );\
\}\
Tcl_ResetResult(
\f7\i intr
\f3\i0 );\
expandAMacroCallTraceAfterExpansion;\
\
\f4\i Set the inclusion bracket styles on the first and last characters.\
Create an misbrackettings.
\f1\i0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\cf0
\f3 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\cf0
\f2\b if
\f3\b0 (
\f7\i replacement
\f3\i0 ) \{\
\f2\b AttrString
\f3\b0
\f7\i c
\f3\i0 =
\f7\i replacement
\f3\i0 ;
\f2\b int
\f3\b0
\f7\i n
\f3\i0 = 0;
\f2\b while
\f3\b0 (
\f7\i c
\f3\i0 ) \{
\f7\i c
\f3\i0 =
\f7\i c
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;
\f7\i n
\f3\i0 ++;\}\
\f7\i replacement
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 =
\f7\i replacement
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 & ~styleExclude | styleInclude;\
\f2\b AttrString
\f3\b0
\f7\i S
\f3\i0 [
\f7\i n
\f3\i0 +1];
\f2\b int
\f7\i\b0 s
\f3\i0 = -1;\
\f2\b if
\f3\b0 (
\f7\i replacement
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ) \{\
\f2\b for
\f3\b0 (
\f7\i c
\f3\i0 =
\f7\i replacement
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;
\f7\i c
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;
\f7\i c
\f3\i0 =
\f7\i c
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ) \{\
\f2\b if
\f3\b0 (
\f7\i c
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 &styleInclude) \{\
\f7\i S
\f3\i0 [++
\f7\i s
\f3\i0 ] =
\f7\i c
\f3\i0 ;\
\}
\f2\b \
\f3\b0
\f2\b if
\f3\b0 (
\f7\i c
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 &styleExclude) \{\
\f2\b if
\f3\b0 (
\f7\i s
\f3\i0 <0)
\f7\i c
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 &= ~styleExclude;
\f2\b else
\f3\b0 --
\f7\i s
\f3\i0 ;\
\}\
\}\
\f2\b while
\f3\b0 (
\f7\i s
\f3\i0 >=0) \{
\f7\i S
\f3\i0 [
\f7\i s
\f3\i0 ]
\f6 \uc0\u8594
\f7\i style
\f3\i0 &= ~styleInclude;
\f7\i s
\f3\i0 --;\}\
\f2\b if
\f3\b0 (
\f7\i c
\f3\i0 'ad
\f7\i replacement
\f3\i0 )
\f7\i c
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 &= ~styleInclude;\
\f7\i c
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 |= styleExclude;\
\}
\f2\b else
\f3\b0 \{\
\f7\i replacement
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 |= styleExclude;\
\}\
\}\
\
\f4\i Slice the accumulated buffer and then splice back together with the\
expansion text. The string in front of the original macro name is \
invariant across this splice; enclosing macro calls have not been modified\
since the top macro call was pushed, and so not have string offset that\
are before the current expansion; therefore this expansion does not\
invalidate any stacked macro calls and they can be resumed at the\
beginning of the replacing expansion text. (Except as below with\
macrocount0.)
\f1\i0 \
\f3 \
\f2\b AttrString
\f3\b0
\f7\i begincall
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startname
\f3\i0 ;\
\f2\b AttrString
\f3\b0
\f7\i beforecall
\f3\i0 = head(
\f7\i begincall
\f3\i0 );\
\f2\b AttrString
\f3\b0
\f7\i aftercall
\f3\i0 =
\f7\i source
\f3\i0 ;\
\f0\b AttrString
\f1\b0
\f4\i endcall
\f1\i0 =
\f3 head(
\f7\i source
\f3\i0 );\
\f2\b AttrString
\f3\b0
\f7\i startparameters
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startparameters
\f3\i0 ;\
\f2\b if
\f3\b0 (
\f7\i startparameters
\f6\i0 \uc0\u8743
\f7\i startparameters
\f6\i0 \uc0\u8594
\f7\i pre'adsp
\f6\i0 \uc0\u8594
\f7\i startgap
\f3\i0 ) \{\
\f2\b AttrString
\f3\b0
\f7\i startgap
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startgap
\f3\i0 ;\
\f7\i startparameters
\f3\i0 =
\f7\i startparameters
\f6\i0 \uc0\u8594
\f7\i pre
\f3\i0 ;\
\f2\b AttrString
\f3\b0
\f7\i endmacroname
\f3\i0 = head(
\f7\i startgap
\f3\i0 );\
\f2\b AttrString
\f3\b0
\f7\i endstartgap
\f3\i0 = head(
\f7\i startparameters
\f3\i0 );\
cat(
\f7\i endmacroname
\f3\i0 ,
\f7\i startparameters
\f3\i0 );\
cat(
\f7\i endstartgap
\f3\i0 ,
\f7\i replacement
\f3\i0 );\
\f7\i replacement
\f3\i0 =
\f7\i startgap
\f3\i0 ;\
\}\
\f2\b if
\f3\b0 (
\f7\i replacement
\f3\i0 ) \{\
\f7\i beforecall
\f3\i0 = cat(
\f7\i beforecall
\f3\i0 ,
\f7\i replacement
\f3\i0 );\
\f7\i endreplacement
\f3\i0 = cat(
\f7\i endreplacement
\f3\i0 ,
\f7\i aftercall
\f3\i0 );\
\}
\f2\b else
\f3\b0 \{\
\f7\i beforecall
\f3\i0 =
\f7\i endreplacement
\f3\i0 = cat(
\f7\i beforecall
\f3\i0 ,
\f7\i aftercall
\f3\i0 );\
\}\
freeattrstring(
\f7\i begincall
\f3\i0 );\
\f2\b if
\f3\b0 (
\f7\i beforecall
\f3\i0 ) \{\
\f2\b if
\f3\b0 (
\f7\i beforecall
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ) \{\
\f7\i source
\f3\i0 =
\f7\i beforecall
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\}
\f2\b else
\f3\b0 \{\
\f7\i source
\f3\i0 =
\f7\i beforecall
\f3\i0 ;\
\}\
\}
\f2\b else
\f3\b0 \{\
\f7\i source
\f3\i0 =
\f7\i endreplacement
\f3\i0 ;\
\}\
\
\f2\b if
\f3\b0 (
\f7\i macrocount0
\f3\i0 'ad
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i macrocount
\f3\i0 ) \{\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f4\i \cf0 \
The macro definitions were changed. Because the stack does not record\
all names in the source string, the stack cannot determine if the macro\
change invalidates the stack. The safest way (without keeping track of\
all names) of dealing with this is to assume the entire stack is invalid\
and restart the macro call parse at the beginning of the accumulated\
buffer.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3\i0 \cf0 \
\f7\i source
\f3\i0 = first(
\f7\i source
\f3\i0 );\
\f2\b while
\f3\b0 (
\f7\i sp
\f3\i0 ) \{decr(
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 );
\f2\b Stack
\f3\b0
\f7\i t
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i under
\f3\i0 ; dispose(
\f7\i sp
\f3\i0 );
\f7\i sp
\f3\i0 =
\f7\i t
\f3\i0 ;\}\
\}
\f2\b else
\f3\b0 \{\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f4\i \cf0 \
The stack is valid. Resume parsing at the innermost enclosing call.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3\i0 \cf0 \
decr(
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 );
\f2\b Stack
\f3\b0
\f7\i t
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i under
\f3\i0 ; dispose(
\f7\i sp
\f3\i0 );
\f7\i sp
\f3\i0 =
\f7\i t
\f3\i0 ;\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f4\i \cf0 \
Back up if gluing names together.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3\i0 \cf0 \
\f2\b if
\f3\b0 (isname(
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 )) \{\
\f2\b while
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i pre
\f3\i0
\f6 \uc0\u8743
\f3 isname(
\f7\i source
\f6\i0 \uc0\u8594
\f7\i pre
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 )\
\f6 \uc0\u8743
\f3
\f7\i source
\f6\i0 \uc0\u8594
\f7\i pre
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 ==
\f7\i source
\f6\i0 \uc0\u8594
\f7\i style\
\f3\i0 )
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i pre
\f3\i0 ;\
\}\
\}\
\}\
\f2\b <>
\f3\b0 \
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f4\i \cf0 The following code is only used for tracing macro expansion, not for\
the expansion itself.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3\i0 \cf0 \
\f2\b <
\f3\b0 expandAMacroCallTraceBeforeExpansion
\f2\b >\
\f3\b0
\f2\b Obj
\f3\b0
\f7\i precedingobj
\f3\i0 = 0,
\f7\i followingobj
\f3\i0 = 0;\
\f2\b char
\f3\b0 *
\f7\i precedingstr
\f3\i0 = "",
\f7\i
\f3\i0 *
\f7\i followingstr
\f3\i0 = "";\
\f2\b char
\f3\b0 *
\f7\i precedingand
\f3\i0 = "",
\f7\i
\f3\i0 *
\f7\i followingand
\f3\i0 = "";\
\f2\b if
\f3\b0 (trace("?", "R")) \{\
\f2\b AttrString
\f3\b0
\f7\i x
\f3\i0 ;
\f2\b int
\f3\b0
\f7\i k
\f3\i0 ;\
\f7\i x
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startname
\f6\i0 \uc0\u8594
\f7\i pre
\f3\i0 ;\
\f2\b if
\f3\b0 (
\f7\i x
\f3\i0 ) \{\
\f2\b for
\f3\b0 (
\f7\i k
\f3\i0 =60;
\f7\i x
\f6\i0 \uc0\u8594
\f7\i pre
\f3\i0
\f6 \uc0\u8743
\f3
\f7\i k
\f3\i0 >0;
\f7\i k
\f3\i0 --)
\f7\i x
\f3\i0 =
\f7\i x
\f6\i0 \uc0\u8594
\f7\i pre
\f3\i0 ;\
\f7\i precedingobj
\f3\i0 = substring(
\f7\i x
\f3\i0 ,
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startname
\f3\i0 ,
\f2\b true
\f3\b0 );\
\f7\i precedingstr
\f3\i0 = Tcl_GetString(
\f7\i precedingobj
\f3\i0 );\
\f2\b if
\f3\b0 (
\f7\i k
\f3\i0 ==0)
\f7\i precedingand
\f3\i0 = "...";\
\}\
\f7\i x
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b if
\f3\b0 (
\f7\i x
\f3\i0 ) \{\
\f2\b for
\f3\b0 (
\f7\i k
\f3\i0 =60;
\f7\i x
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 'adEOI
\f6 \uc0\u8743
\f3
\f7\i k
\f3\i0 >0;
\f7\i k
\f3\i0 --)
\f7\i x
\f3\i0 =
\f7\i x
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f7\i followingobj
\f3\i0 = substring(
\f7\i source
\f3\i0 ,
\f7\i x
\f3\i0 ,
\f2\b true
\f3\b0 );\
\f7\i followingstr
\f3\i0 = Tcl_GetString(
\f7\i followingobj
\f3\i0 );\
\f2\b if
\f3\b0 (
\f7\i k
\f3\i0 ==0)
\f7\i followingand
\f3\i0 = "...";\
\}\
\}\
\f2\b static
\f3\b0
\f2\b int
\f3\b0
\f7\i sid
\f3\i0 = 0;
\f2\b int
\f3\b0
\f7\i lid
\f3\i0 = ++
\f7\i sid
\f3\i0 ;\
trace("R%+%d#%s%s<[ %s ]>%s%s",\
\f7\i lid
\f3\i0 ,
\f7\i precedingand
\f3\i0 ,
\f7\i precedingstr
\f3\i0 ,\
Tcl_GetString(
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 ),\
\f7\i followingstr
\f3\i0 ,
\f7\i followingand
\f3\i0 )\
\f2\b <>
\f3\b0 \
\f2\b <
\f3\b0 expandAMacroCallTraceAfterExpansion
\f2\b >\
\f3\b0
\f2\b if
\f3\b0 (
\f7\i rc
\f3\i0 ==TCL_OK) \{\
\f2\b Obj
\f3\b0
\f7\i r
\f3\i0 = substring(
\f7\i replacement
\f3\i0 , 0,
\f2\b true
\f3\b0 );\
trace("R%-%d#%s%s<\{ %s \}>%s%s",\
\f7\i lid
\f3\i0 ,
\f7\i precedingand
\f3\i0 ,
\f7\i precedingstr
\f3\i0 ,\
\f7\i replacement
\f3\i0 ? Tcl_GetString(
\f7\i r
\f3\i0 ) : "",\
\f7\i followingstr
\f3\i0 ,
\f7\i followingand
\f3\i0 );\
decr(
\f7\i r
\f3\i0 );\
\}
\f2\b else
\f3\b0 \{\
trace("R%-%d#%s%s<!\{ %s \}!>%s%s",\
\f7\i lid
\f3\i0 ,
\f7\i precedingand
\f3\i0 ,
\f7\i precedingstr
\f3\i0 ,\
Tcl_GetStringResult(
\f7\i intr
\f3\i0 ),\
\f7\i followingstr
\f3\i0 ,
\f7\i followingand
\f3\i0 );\
\}\
decr(
\f7\i precedingobj
\f3\i0 ); decr(
\f7\i followingobj
\f3\i0 )\
\f2\b <>\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f1\b0 \cf0 \
If the end of the string or an unbalanced end delimiter is reached without completing the call, abandon the call and resume the parameter parsing of the enclosing call.\
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b <
\f3\b0 abandonAnIncompleteMacroCall
\f2\b >\
\f3\b0
\f2\b if
\f3\b0 (
\f7\i sp
\f3\i0
\f6 \uc0\u8743
\f3 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ==EOI
\f6 \uc0\u8744
\f3
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i depth
\f3\i0 <0)) \{\
\f7\i source
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i startgap
\f3\i0 ;\
decr(
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i call
\f3\i0 );
\f2\b Stack
\f3\b0
\f7\i t
\f3\i0 =
\f7\i sp
\f6\i0 \uc0\u8594
\f7\i under
\f3\i0 ; dispose(
\f7\i sp
\f3\i0 );
\f7\i sp
\f3\i0 =
\f7\i t
\f3\i0 ;\
\}\
\f2\b <>
\f3\b0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f1 \cf0 \
If at the end of the accumulation buffer and no macro calls, the expansion is completed.\
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b <
\f3\b0 completedMacroExpansion
\f2\b >\
\f3\b0
\f2\b if
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ==EOI) \{\
\f2\b break
\f3\b0 ;\
\}\
\f2\b <>
\f3\b0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f1 \cf0 \
Embedded directives. \
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b <
\f3\b0 embeddedCommandsInMacroRecognition
\f2\b >\
\f3\b0
\f2\b if
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ==META) \{\
\f2\b while
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 'adEOI
\f6 \uc0\u8743
\f3
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 'adATEM)\
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b if
\f3\b0 (
\f7\i source
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ==ATEM)
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\}\
\f2\b <>
\f3\b0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f1 \cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b priv func
\f3\b0
\f2\b void
\f3\b0 expandMacrosInAccumulatedEmissions(
\f2\b Intr
\f3\b0
\f7\i intr
\f3\i0 ,
\f2\b MacroContext
\f3\b0
\f7\i cx
\f3\i0 )
\f2\b is
\f3\b0 \{\
\
\f4\i Do not even bother if at the expansion limit.
\f3\i0 \
\
\f2\b if
\f3\b0 (
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i limitted
\f3\i0
\f6 \uc0\u8743
\f3
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i limit
\f3\i0 <0)
\f2\b return
\f3\b0 ;\
\
\f4\i The cx->output accumulation buffer will be used by macro expansion. The\
buffer contents are saved to the local variable source and the global buffer\
is cleared.\
\
expandMacrosInAccumulatedEmissions can be called recursively, with\
accumulation buffers stacked by saving in the protocol stack, the cx->output\
variable being the top of stack. However unless a macro expansion proc itself\
calls expandMacrosInAccumulatedEmissions, it will not be called recursively:\
nested macro calls are parsed with a stack in this function rather than\
recursing this function.
\f3\i0 \
\
\f2\b AttrString
\f7\i\b0 source
\f3\i0 = first(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 )
\f7\i ;\
\f3\i0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f4\i \cf0 Append an EOI to the string so the end can be detected without\
running off the end.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3\i0 \cf0 \
\{\
\f2\b AttrString
\f7\i\b0 end
\f3\i0 = cat(last(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i output
\f3\i0 )
\f7\i
\f3\i0 , newchar(0, 0, EOI));\
\f2\b if
\f3\b0 ('c2
\f7\i source
\f3\i0 )
\f7\i source
\f3\i0 = first(
\f7\i end
\f3\i0 );\
\}\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f7\i \cf0 cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 = 0;
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i output
\f3\i0 = 0;\
\
macroParseStack;\
\
\f4\i Scan the accumulated buffer for all macro calls.
\f3\i0 \
\
\f2\b for
\f3\b0 (;;)\
abandonAnIncompleteMacroCall \
\f2\b else
\f3\b0 completedMacroExpansion\
\f2\b else
\f3\b0 expandAMacroCall\
\f2\b else
\f3\b0 recogniseAMacroName
\f2\b \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3\b0 \cf0
\f2\b else
\f3\b0 separateParametersOfAMacroCall
\f2\b \
\f3\b0
\f2\b else
\f3\b0 embeddedCommandsInMacroRecognition\
\f2\b else
\f3\b0
\f7\i source
\f3\i0 =
\f7\i source
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\
\f4\i The source variable has been repeatedly sliced and diced by macro calls;\
it now contains the finally expansion of the accumulated buffer on input\
and is stored on buffer on output.
\f3\i0 \
\
freeattrstring(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 );\
\f2\b AttrString
\f7\i\b0 eoi
\f3\i0 = last(
\f7\i source
\f3\i0 );
\f2\b \
\f3\b0
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i output
\f3\i0 = head(
\f7\i eoi
\f3\i0 );\
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 = first(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i output
\f3\i0 );\
freeattrstring(
\f7\i eoi
\f3\i0 );\
\}\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f0\b \cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\qr\pardirnatural
\fs28 \cf0 8 Write Output Buffer to Files\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f8\fs24 \cf0 Flush macro accumulation area to output
\f9\b0 .\
The macro expansions can include directives to write expanded text to various files. Expansion text not written to another file is written to stdout. The directives give a file path and file region number. If the file path is relative, it is relative to t
he output directory
\f8\b -o
\f9\b0
\f10\i folder
\f9\i0 . All text written to the same region number is gatherred in the order in the accumulation area. Then the regions are written to their files in ascending region number with all their gatherred text. This allows text to be added to the accumulation
area in pretty much any desired order and then resorted and written to files in a completely different order. Any spaces at the beginning and end of a file are skipped before writing.
\f8\b\fs26 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\qr\pardirnatural
\f0 \cf0 \
8.1 Line Numbers\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f1\b0\fs24 \cf0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\cf0 Most of the complexity of this code is in writing line numbers that the gnu preprocessor can deal with. The nice thing about gnu cpp is that handles nested line numbers; the nasty thing about gnu cpp is that handles nested line numbers with little fl
exibility. Gnu cpp uses nested line numbers when an error occurs in an include file to indicate the actual error and the inclusion nest backs to source;
\f0\b renee
\f1\b0 co-opts this to show the nesting of expanded macros on error.\
\
The macro translator attaches line numbers to emitted text. Expanded macro are bracketted in inclusion and exclusion styles; if the text inside an include/exclude bracket has a different line number than the text outside,
\f0\b renee
\f1\b0 can report it with nested line numbers.\
\
The gnu cpp line number schemes is explained (somewhat) in {\field{\*\fldinst{HYPERLINK "http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html#Preprocessor-Output"}}{\fldrslt Preprocessor Output - The C Preprocessor}}. More completely, assume a stack
of (
\f4\i linenumber
\f1\i0 ,
\f4\i filename
\f1\i0 ). The stack is never empty and the bottom entry refers to source program. The line directives are\
\
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\cf0 #
\f4\i linenumber filename
\f1\i0 Set top of stack to (
\f4\i linenumber
\f1\i0 ,
\f4\i filename
\f1\i0 ).\
\
#
\f4\i linenumber filename
\f1\i0 1 Push (
\f4\i linenumber
\f1\i0 ,
\f4\i filename
\f1\i0 ) on the stack.\
\
#
\f4\i linenumber filename
\f1\i0 2 Pop the stack. The top entry must become (
\f4\i somenumber
\f1\i0 ,
\f4\i filename
\f1\i0 ) and is set to (
\f4\i linenumber
\f1\i0 ,
\f4\i filename
\f1\i0 ); the file name of the directive and popped to stack entry must match; the line number can be different and it is updated.\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f0\b \cf0 \
\f1\b0 (
\f0\b renee
\f1\b0 does not use flags 3 or 4.) On error, the compiler or preprocessor reports the stack as nested includes with top of stack as the innermost include and the bottom stack as the source program.
\f0\b renee
\f1\b0 does not create an #ident directive.\
\
Line numbers are reported at line breaks in the original program. Any line number changes and includes/excludes that only occur within one line are lost.
\f0\b\fs26 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1\b0\fs24 \cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 priv structure
\f3\b0 *
\f2\b PositionChain is
\f3\b0 \{\
\f2\b Pos
\f3\b0
\f7\i pos
\f3\i0 ;
\f4\i Position from attributed character.
\f3\i0 \
\f2\b int
\f3\b0
\f7\i flag
\f3\i0 ;
\f4\i 1 for push, 2 for pop.
\f3\i0 \
\f2\b PositionChain
\f3\b0
\f7\i link
\f3\i0 ;\
\f2\b
\f3\b0 \};\
\f2\b \
func PositionChain
\f3\b0 pushPos(
\f2\b Pos
\f3\b0
\f7\i pos
\f3\i0 ,
\f2\b int
\f3\b0
\f7\i flag
\f3\i0 ,
\f2\b PositionChain
\f3\b0
\f7\i pc
\f3\i0 )
\f2\b is
\f3\b0 \{\
\f2\b PositionChain
\f3\b0
\f7\i t
\f3\i0 = heap(
\f2\b struct
\f3\b0
\f2\b PositionChain
\f3\b0 );\
\f2\b
\f3\b0 *
\f7\i t
\f3\i0 = ((
\f2\b struct
\f3\b0
\f2\b PositionChain
\f3\b0 )\{
\f7\i pos
\f3\i0 ,
\f7\i flag
\f3\i0 ,
\f7\i pc
\f3\i0 \});\
\f2\b return
\f3\b0
\f7\i t
\f3\i0 ; \
\f2\b
\f3\b0 \}\
\f2\b \
func PositionChain
\f3\b0 popPos(
\f2\b PositionChain
\f3\b0
\f7\i pc
\f3\i0 )
\f2\b is
\f3\b0 \{\
\f2\b PositionChain
\f3\b0
\f7\i t
\f3\i0 =
\f7\i pc
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 ;\
\f2\b
\f3\b0 dispose(
\f7\i pc
\f3\i0 );\
\f2\b return
\f3\b0
\f7\i t
\f3\i0 ; \
\f2\b
\f3\b0 \}\
\f2\b \
func PositionChain
\f3\b0 revPos(
\f2\b PositionChain
\f3\b0
\f7\i pc
\f3\i0 )
\f2\b is
\f3\b0 \{\
\f2\b PositionChain
\f3\b0
\f7\i prev
\f3\i0 ,
\f7\i curr
\f3\i0 ,
\f7\i next
\f3\i0 ;\
\f2\b for
\f3\b0 (
\f7\i prev
\f3\i0 =0,
\f7\i curr
\f3\i0 =
\f7\i pc
\f3\i0 ;
\f7\i curr
\f3\i0 ;
\f7\i prev=curr
\f3\i0 ,
\f7\i curr
\f3\i0 =
\f7\i next
\f3\i0 ) \{\
\f2\b
\f7\i\b0 next = curr
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 ;
\f7\i curr
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 =
\f7\i prev
\f3\i0 ;\
\f2\b
\f3\b0 \}\
\f2\b return
\f3\b0
\f7\i prev
\f3\i0 ; \
\f2\b
\f3\b0 \}\
\f2\b \
<
\f3\b0 positionStackVariable
\f2\b >\
PositionChain
\f3\b0
\f7\i ps
\f3\i0 = 0\
\f2\b <>
\f3\b0 \
\f2\b <
\f3\b0 positionBufferVariable
\f2\b >\
PositionChain
\f3\b0
\f7\i pb
\f3\i0 = 0,
\f7\i xs;
\f2\i0\b Pos
\f7\i\b0 lp
\f3\i0 = 0\
\f2\b <>
\f3\b0 \
\f2\b \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1\b0 \cf0 'c7
\f0\b on
\f1\b0 'c8 Turn line numberring on.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b <
\f3\b0 onOffFileNumberringVariable
\f2\b >\
\f3\b0
\f2\b int
\f3\b0
\f7\i showing
\f3\i0 = 1
\f4\i Counts on-off.
\f3\i0 \
\f2\b <>\
\f3\b0
\f2\b <
\f3\b0 turnLineNumberGenerationOn
\f2\b >
\f3\b0 \
\f2\b if
\f3\b0 (++
\f7\i showing
\f3\i0 ==1) \{\
\f2\b for
\f3\b0 (
\f7\i xs
\f3\i0 =
\f7\i ps
\f3\i0 =revPos(
\f7\i ps
\f3\i0 );
\f7\i xs
\f3\i0 ;
\f7\i xs
\f3\i0 =
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 ) \{\
\f7\i pb
\f3\i0 = pushPos(
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 ,
\f7\i xs
\f3\i0 'ad
\f7\i ps
\f3\i0 ,
\f7\i pb
\f3\i0 );\
\}\
\f7\i ps
\f3\i0 = revPos(
\f7\i ps
\f3\i0 );\
\}\
trace("Q#on");\
\f2\b <>
\f3\b0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1 \cf0 \
'c7
\f0\b off
\f1\b0 'c8 Turn line numberring off. Line numbers are inserted in the accumulation area regardless: this controls the output of line numbers not their accumulation.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 <
\f3\b0 turnLineNumberGenerationOff
\f2\b >
\f3\b0 \
\f2\b if
\f3\b0 (
\f7\i showing--
\f3\i0 ==1) \{\
\f2\b for
\f3\b0 (
\f7\i xs
\f3\i0 =
\f7\i ps
\f3\i0 ?
\f7\i ps
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 :0;
\f7\i xs
\f3\i0 ;
\f7\i xs
\f3\i0 =
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 ) \{\
\f2\b
\f7\i\b0 pb
\f3\i0 = pushPos(
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 , 2,
\f7\i pb
\f3\i0 );\
\f2\b
\f3\b0 \}\
\f2\b
\f3\b0 \}\
\f2\b
\f3\b0 trace("Q#off");\
\f2\b <>
\f3\b0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1 \cf0 \
A flag in the character styles where a macro expansion began.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 <
\f3\b0 pushPosition
\f2\b >\
if
\f3\b0 (
\f7\i showing
\f3\i0 >0) \{\
\f7\i pb
\f3\i0 = pushPos(
\f7\i pos
\f3\i0 ,
\f7\i ps
\f3\i0 'ad0,
\f7\i pb
\f3\i0 );\
\}\
\f2\b
\f7\i\b0 ps
\f3\i0 = pushPos(
\f7\i pos
\f3\i0 , 0,
\f7\i ps
\f3\i0 );\
\f7\i lp
\f3\i0 =
\f7\i pos;
\f3\i0 \
\f2\b
\f3\b0 trace("Q%+#INC");\
\f2\b <>
\f3\b0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1 \cf0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li1080\ql\qnatural\pard
irnatural
\cf0 File position (line number and file name) is attached to each character, trying to show original location of the character. If line numberring is on, this becomes a C pre-parser #line directive.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 <
\f3\b0 updatePosition
\f2\b >\
if
\f3\b0 (
\f7\i showing
\f3\i0 'b20) \{\
;
\f2\b \
\f3\b0 \}
\f2\b else if
\f3\b0 (
\f7\i pb
\f3\i0 ) \{\
\f2\b if (
\f7\i\b0 pb
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 'ad
\f7\i pos
\f3\i0 ) trace("Q#line");\
\f7\i pb
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 =
\f7\i pos
\f3\i0 ;
\f2\b \
\f3\b0 \}
\f2\b else if
\f3\b0 (
\f7\i pos
\f3\i0 'ad
\f7\i lp
\f3\i0 ) \{\
\f2\b
\f3\b0 trace("Q#line");\
\f7\i pb
\f3\i0 = pushPos(
\f7\i pos
\f3\i0 , 0,
\f7\i pb
\f3\i0 );\
\}\
\f2\b if
\f3\b0 (
\f7\i ps
\f3\i0 )
\f7\i ps
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 =
\f7\i pos
\f3\i0 ;
\f2\b else
\f7\i\b0 ps
\f3\i0 = pushPos(
\f7\i pos
\f3\i0 , 0,
\f7\i ps
\f3\i0 );\
\f7\i lp
\f3\i0 =
\f7\i pos;
\f3\i0 \
\f2\b <>
\f3\b0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1 \cf0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li1080\ql\qnatural\pard
irnatural
\cf0 A flag in the character styles where a macro expansion end. With line numberring on, inclusion and exclusion are used to create gnu pre-parser nested line numbers used by gcc to indicate include files.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 <
\f3\b0 popPosition
\f2\b >\
if
\f3\b0 (
\f7\i showing
\f3\i0 >0) \{
\f2\b \
if
\f3\b0 (
\f7\i pb
\f3\i0
\f6 \uc0\u8743
\f3
\f7\i pb
\f6\i0 \uc0\u8594
\f7\i flag
\f3\i0 ==0) \{\
\f7\i pb
\f3\i0 = popPos(
\f7\i pb
\f3\i0 );\
\}\
\f2\b if
\f3\b0 (
\f7\i pb
\f3\i0
\f6 \uc0\u8743
\f7\i pb
\f6\i0 \uc0\u8594
\f7\i flag
\f3\i0 ==1) \{\
\f7\i pb
\f3\i0 = popPos(
\f7\i pb
\f3\i0 );\
\}
\f2\b else
\f3\b0 \{\
\f7\i pb
\f3\i0 = pushPos(
\f7\i ps
\f3\i0 ? ps
\f6 \uc0\u8594
\f7\i pos
\f3\i0 :
\f7\i pos
\f3\i0 , 2,
\f7\i pb
\f3\i0 );\
\}\
\f2\b
\f3\b0 \}\
\f2\b if
\f3\b0 (
\f7\i ps
\f3\i0 )
\f7\i ps
\f3\i0 = popPos(
\f7\i ps
\f3\i0 );\
\f2\b
\f3\b0 trace("Q%-#EXC");\
\f2\b <>
\f3\b0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1 \cf0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li1080\ql\qnatural\pard
irnatural
\cf0 Append the line number buffer to the current region\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 <
\f3\b0 printPositionsToTheRegion
\f2\b >\
for
\f3\b0 (
\f7\i pb
\f3\i0 =revPos(
\f7\i pb
\f3\i0 );
\f7\i pb
\f3\i0 ;
\f7\i pb
\f3\i0 =popPos(
\f7\i pb
\f3\i0 )) \{\
\f2\b
\f7\i\b0 lp
\f3\i0 =
\f7\i pb
\f6\i0 \uc0\u8594
\f3 pos;\
\f2\b
\f3\b0 trace("Q# %s %d",displayPosition(
\f7\i lp
\f3\i0 ),
\f7\i pb
\f6\i0 \uc0\u8594
\f7\i flag
\f3\i0 );\
\f2\b int
\f3\b0
\f7\i line
\f3\i0 =
\f7\i lp
\f3\i0 / xcLpIncr;\
\f2\b int
\f3\b0
\f7\i fileindex
\f3\i0 =
\f7\i lp
\f3\i0 % xcLpIncr;\
\f2\b int
\f7\i\b0 nf
\f3\i0 ;
\f2\b chars
\f3\b0
\f7\i file
\f3\i0 = Tcl_GetStringFromObj(
\f7\i included
\f3\i0 [
\f7\i fileindex
\f3\i0 ], &
\f7\i nf
\f3\i0 );\
\f2\b static
\f3\b0
\f2\b char
\f3\b0 TXTrtf[] = "/TXT.rtf";
\f2\b enum
\f3\b0 \{nt = (
\f2\b sizeof
\f3\b0 TXTrtf)-1\};\
\f2\b if
\f3\b0 (
\f7\i nf
\f3\i0 >
\f7\i nt
\f3\i0
\f6 \uc0\u8743
\f3 strcmp(TXTrtf,
\f7\i file
\f3\i0 +
\f7\i nf
\f3\i0 -
\f7\i nt
\f3\i0 )==0)
\f7\i nf
\f3\i0 -=
\f7\i nt
\f3\i0 ;
\f2\b \
\f3\b0 oprintf(
\f7\i region
\f3\i0 , "# %d \\"",
\f7\i line
\f3\i0 );\
\f2\b while
\f3\b0 (*
\f7\i file
\f3\i0
\f6 \uc0\u8743
\f3
\f7\i nf
\f3\i0 -->0)\
\f2\b if
\f3\b0 (*
\f7\i file
\f3\i0 <' '
\f6 \uc0\u8744
\f3 127'b2*
\f7\i file
\f3\i0 ) oprintf(
\f7\i region
\f3\i0 , "\\\\x%02X", 0xFF&*
\f7\i file
\f3\i0 ++);\
\f2\b else
\f3\b0
\f2\b if
\f3\b0 (*
\f7\i file
\f3\i0 =='\''
\f6 \uc0\u8744
\f3 *
\f7\i file
\f3\i0 =='\\"'
\f6 \uc0\u8744
\f3 *
\f7\i file
\f3\i0 =='\\\') oprintf(
\f7\i region
\f3\i0 , "\\\\%c", *
\f7\i file
\f3\i0 ++);\
\f2\b else
\f3\b0 oprintf(
\f7\i region
\f3\i0 , "%c", *
\f7\i file
\f3\i0 ++);\
\f2\b
\f3\b0 oprintf(
\f7\i region
\f3\i0 , "\\"");\
\f2\b if
\f3\b0 (
\f7\i pb
\f6\i0 \uc0\u8594
\f7\i flag
\f3\i0 ) oprintf(
\f7\i region
\f3\i0 , " %d",
\f7\i pb
\f6\i0 \uc0\u8594
\f7\i flag
\f3\i0 );\
\f2\b
\f3\b0 oprintf(
\f7\i region
\f3\i0 , "\\n");\
\f2\b
\f3\b0 \}\
\f2\b <>
\f3\b0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1 \cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 <
\f3\b0 popThenRepushPositionsAtRegionBoundary
\f2\b >
\f3\b0 \
\f2\b
\f4\i\b0 To avoid a recursive function call, the stack links are reversed\
\f2\i0\b
\f4\i\b0 during the descent, reversing the entire stack, and then reversed\
\f2\i0\b
\f4\i\b0 again on the traversal which becomes the ascent.\
\f2\i0\b
\f4\i\b0 Descend the stack and generate pop positions in the old region.\
\f2\i0\b for
\f3\b0 (
\f7\i xs
\f3\i0 =
\f7\i ps
\f3\i0 =revPos(
\f7\i ps
\f3\i0 );
\f7\i xs
\f6\i0 \uc0\u8743
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 ;
\f7\i xs
\f3\i0 =
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 ) \{\
\f2\b
\f7\i\b0 pb
\f3\i0 = pushPos(
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 , 2,
\f7\i pb
\f3\i0 );\
\f2\b
\f3\b0 \}\
\f2\b
\f4\i\b0 Reascend the stack and generate push positions in the new region.\
\f3\i0 printPositionsToTheRegion;
\f2\b \
\f3\b0
\f7\i region
\f3\i0 =
\f7\i newregion
\f3\i0 ;\
\f2\b for
\f3\b0 (
\f7\i xs
\f3\i0 =
\f7\i ps
\f3\i0 =revPos(
\f7\i ps
\f3\i0 );
\f7\i xs
\f3\i0 ;
\f7\i xs
\f3\i0 =
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i link
\f3\i0 ) \{\
\f2\b
\f7\i\b0 pb
\f3\i0 = pushPos(
\f7\i xs
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 ,
\f7\i xs
\f3\i0 'ad
\f7\i ps
\f3\i0 ,
\f7\i pb
\f3\i0 );\
\f2\b
\f3\b0 \}\
\f2\b <>
\f3\b0 \
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li1080\fi-360\ql\qnatural\pardirnatural
\f0\b \cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\qr\pardirnatural
\fs26 \cf0 8.2 Regions\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\fs24 \cf0 \
priv structure
\f3\b0 *
\f2\b OutputFile is
\f3\b0 \{\
\f2\b Obj
\f3\b0
\f7\i path
\f3\i0 ;
\f4\i Output path or - for stdout.
\f3\i0 \
\f2\b int
\f3\b0
\f7\i m
\f3\i0 ;
\f4\i Length of region array.
\f3\i0 \
\f2\b Obj
\f3\b0 *
\f7\i region
\f3\i0 ;
\f4\i Text to region r of file f is appended f->region[r].
\f3\i0 \
\f2\b OutputFile
\f3\b0
\f7\i next
\f3\i0 ;
\f4\i This a MTF self orderring list.
\f3\i0 \
\f2\b
\f3\b0 \};\
\f2\b <
\f3\b0 outputFileVariables
\f2\b >\
\f4\i\b0 Establish a default fallback region which is stdout.
\f2\i0\b \
\f3\b0
\f2\b OutputFile
\f3\b0
\f7\i file
\f3\i0 = heap(
\f2\b struct
\f3\b0
\f2\b OutputFile
\f3\b0 ); *
\f7\i file
\f3\i0 = ((
\f2\b struct
\f3\b0
\f2\b OutputFile
\f3\b0 )\{\
incr(Tcl_NewStringObj("-", -1)), \
1, heap(
\f2\b Obj
\f3\b0 ), 0\
\});\
\f2\b Obj
\f3\b0
\f7\i region
\f3\i0 ,
\f7\i region0
\f3\i0 ,
\f7\i partial
\f3\i0 = 0;\
\f7\i region0
\f3\i0 =
\f7\i region
\f3\i0 =
\f7\i file
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 [0] = incr(Tcl_NewObj());\
\f2\b <>
\f3\b0 \
\f2\b <
\f3\b0 outputFileRegions
\f2\b >\
\f3\b0
\f2\b while
\f3\b0 (
\f7\i file
\f3\i0 ) \{\
\f2\b OutputFile
\f3\b0
\f7\i g
\f3\i0 =
\f7\i file
\f3\i0 ;
\f7\i file
\f3\i0 =
\f7\i file
\f6\i0 \uc0\u8594
\f7\i next
\f3\i0 ;\
\f2\b Tcl_Channel
\f3\b0
\f7\i chan
\f3\i0 ;\
\f2\b if
\f3\b0 (strcmp(Tcl_GetString(
\f7\i g
\f6\i0 \uc0\u8594
\f7\i path
\f3\i0 ), "-")==0) \{\
\f7\i chan
\f3\i0 =
\f7\i chstdout
\f3\i0 ;\
\}
\f2\b else
\f3\b0 \{\
\f2\b int
\f3\b0
\f7\i i
\f3\i0 ,
\f7\i n
\f3\i0 ;
\f2\b Obj
\f3\b0
\f7\i parts
\f3\i0 = Tcl_FSSplitPath(
\f7\i g
\f6\i0 \uc0\u8594
\f7\i path
\f3\i0 , &
\f7\i n
\f3\i0 );\
\f2\b for
\f3\b0 (
\f7\i i
\f3\i0 =1;
\f7\i i
\f3\i0 <
\f7\i n
\f3\i0 ;
\f7\i i
\f3\i0 ++) \{\
\f2\b Obj
\f3\b0
\f7\i directory
\f3\i0 = incr(Tcl_FSJoinPath(
\f7\i parts
\f3\i0 ,
\f7\i i
\f3\i0 ));\
Tcl_FSCreateDirectory(
\f7\i directory
\f3\i0 ); decr(
\f7\i directory
\f3\i0 );\
\}\
\f7\i chan
\f3\i0 = Tcl_FSOpenFileChannel(
\f7\i intr
\f3\i0 ,
\f7\i g
\f6\i0 \uc0\u8594
\f7\i path
\f3\i0 , "w", 0600);\
\}\
\f2\b if
\f3\b0 (
\f7\i chan
\f3\i0 ) \{\
\f2\b int
\f3\b0
\f7\i r
\f3\i0 ;
\f2\b for
\f3\b0 (
\f7\i r
\f3\i0 =0;
\f7\i r
\f3\i0 <
\f7\i g
\f6\i0 \uc0\u8594
\f7\i m
\f3\i0 ;
\f7\i r
\f3\i0 ++)
\f2\b if
\f3\b0 (
\f7\i g
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 [
\f7\i r
\f3\i0 ]) \{\
\f2\b chars
\f3\b0
\f7\i regiontext
\f3\i0 = Tcl_GetString(
\f7\i g
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 [
\f7\i r
\f3\i0 ]);\
\f2\b while
\f3\b0 (isspace(*
\f7\i regiontext
\f3\i0 )) ++
\f7\i regiontext
\f3\i0 ;\
\f2\b int
\f3\b0
\f7\i length
\f3\i0 = strlen(
\f7\i regiontext
\f3\i0 );\
\f2\b while
\f3\b0 (
\f7\i length
\f3\i0 >0
\f6 \uc0\u8743
\f3 isspace(
\f7\i regiontext
\f3\i0 [
\f7\i length
\f3\i0 -1])) --
\f7\i length
\f3\i0 ;\
\f2\b if
\f3\b0 (
\f7\i length
\f3\i0 ) cprintf(
\f7\i chan
\f3\i0 , "%.*s\\n",
\f7\i length
\f3\i0 ,
\f7\i regiontext
\f3\i0 );\
decr(
\f7\i g
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 [
\f7\i r
\f3\i0 ]);\
\}\
\f2\b if
\f3\b0 (
\f7\i chan
\f3\i0
\f6 \uc0\u8743
\f3
\f7\i chan
\f3\i0 'ad
\f7\i chstdout
\f3\i0 ) Tcl_Close(
\f7\i intr
\f3\i0 ,
\f7\i chan
\f3\i0 );\
\}
\f2\b else
\f3\b0 \{\
oprintf(
\f7\i region0
\f3\i0 , "#error open: %s: %s\\n", \
Tcl_GetStringResult(
\f7\i intr
\f3\i0 ), \
Tcl_GetString(
\f7\i g
\f6\i0 \uc0\u8594
\f7\i path
\f3\i0 ));\
\}\
dispose(
\f7\i g
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 ); decr(
\f7\i g
\f6\i0 \uc0\u8594
\f7\i path
\f3\i0 ); dispose(
\f7\i g
\f3\i0 );\
\}\
\f2\b <>
\f3\b0 \
\f2\b \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1\b0 \cf0 'c7
\f0\b region
\f1\b0
\f0\b [
\f4\i\b0 region
\f0\i0\b ]
\f4\i\b0 filename
\f1\i0 'c8 Where to write all text until the next region directive into the specified region of the specified file.
\f4\i region
\f1\i0 is a nonnegative integer value, 0 if omitted.
\f4\i filename
\f1\i0 is a relative (to the output directory of
\f0\b macro output
\f1\b0 ) or absolute file path, or it is a dash (-) which means stdout.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\b \cf0 <
\f3\b0 parseRegionDirectiveAndSendOutputToIt
\f2\b >
\f3\b0 \
\f2\b
\f4\i\b0 Parse the region number and output path. If there is no integer beginning\
\f2\i0\b
\f4\i\b0 the directive, strtol will return 0, the default region, without consuming\
\f2\i0\b
\f4\i\b0 any more input. Region numbers cannot be negative; they are silently\
\f2\i0\b
\f4\i\b0 mapped to region 0.\
\f3\i0
\f7\i embedded
\f3\i0 =\
\f7\i embedded
\f3\i0 /*'c7*/
\f6 \uc0\u8594
\f7\i post
\f3\i0 /*r*/
\f6 \uc0\u8594
\f7\i post
\f3\i0 /*e*/
\f6 \uc0\u8594
\f7\i post
\f3\i0 /*g*/\
\f6 \uc0\u8594
\f7\i post
\f3\i0 /*i*/
\f6 \uc0\u8594
\f7\i post
\f3\i0 /*o*/
\f6 \uc0\u8594
\f7\i post
\f3\i0 /*n*/
\f6 \uc0\u8594
\f7\i post
\f3\i0 /* */;\
\f2\b while
\f3\b0 (Tcl_UniCharIsSpace(
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ))
\f7\i embedded
\f3\i0 =
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b int
\f3\b0
\f7\i r
\f3\i0 = 0;\
\f2\b for
\f3\b0 (; Tcl_UniCharIsDigit(
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 );
\f7\i embedded
\f3\i0 =
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 )\
\f7\i r
\f3\i0 = 10*
\f7\i r
\f3\i0 + digittoint(
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 );\
\f2\b while
\f3\b0 (Tcl_UniCharIsSpace(
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ))
\f7\i embedded
\f3\i0 =
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b AttrString
\f3\b0
\f7\i x
\f3\i0 =
\f7\i output
\f3\i0 ;
\f2\b while
\f3\b0 (Tcl_UniCharIsSpace(
\f7\i x
\f6\i0 \uc0\u8594
\f7\i pre
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 ))
\f7\i x
\f3\i0 =
\f7\i x
\f6\i0 \uc0\u8594
\f7\i pre
\f3\i0 ;\
\f2\b Obj
\f3\b0
\f7\i path
\f3\i0 = substring(
\f7\i embedded
\f3\i0 ,
\f7\i x
\f3\i0 ,
\f2\b true
\f3\b0 );
\f2\b bool
\f3\b0
\f7\i relative
\f3\i0 = 'c2eqstring(
\f7\i embedded
\f3\i0 , '/', 0);\
\f2\b
\f4\i\b0 If the path is relative, prefix the output directory to it.\
\f2\i0\b if
\f3\b0 (
\f7\i relative
\f3\i0 ) \{\
\f2\b Obj
\f7\i\b0 abspath
\f3\i0 = oprintf(0, "%s/%s",Tcl_GetString(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i odir
\f3\i0 ), Tcl_GetString(
\f7\i path
\f3\i0 ));\
\f2\b
\f3\b0 decr(
\f7\i path
\f3\i0 );
\f7\i path
\f3\i0 =
\f7\i abspath
\f3\i0 ;\
\f2\b
\f3\b0 \}\
\f2\b
\f4\i\b0 Find or create the OutputFile block for this path. If the block already\
\f2\i0\b
\f4\i\b0 exists, move it to front. If not, create a new block.\
\f2\i0\b OutputFile
\f3\b0
\f7\i p
\f3\i0 ,
\f7\i c
\f3\i0 ;
\f2\b for
\f3\b0 (
\f7\i p
\f3\i0 =0,
\f7\i c
\f3\i0 =
\f7\i file
\f3\i0 ;
\f7\i c
\f3\i0 ;
\f7\i p
\f3\i0 =
\f7\i c
\f3\i0 ,
\f7\i c
\f3\i0 =
\f7\i c
\f6\i0 \uc0\u8594
\f7\i next
\f3\i0 ) \{\
\f2\b if
\f3\b0 (objeq(
\f7\i c
\f6\i0 \uc0\u8594
\f7\i path
\f3\i0 ,
\f7\i path
\f3\i0 )) \{\
\f2\b if
\f3\b0 (
\f7\i p
\f3\i0 ) \{
\f7\i p
\f6\i0 \uc0\u8594
\f7\i next
\f3\i0 =
\f7\i c
\f6\i0 \uc0\u8594
\f7\i next
\f3\i0 ;
\f7\i c
\f6\i0 \uc0\u8594
\f7\i next
\f3\i0 =
\f7\i file
\f3\i0 ;
\f7\i file
\f3\i0 =
\f7\i c
\f3\i0 ;\} decr(
\f7\i path
\f3\i0 );
\f2\b break
\f3\b0 ;\
\f2\b
\f3\b0 \}\
\f2\b
\f3\b0 \}\
\f2\b if
\f3\b0 ('c2
\f7\i c
\f3\i0 ) \{\
\f2\b
\f7\i\b0 c
\f3\i0 = heap(
\f2\b struct
\f3\b0
\f2\b OutputFile
\f3\b0 );\
\f2\b
\f3\b0 *
\f7\i c
\f3\i0 = ((
\f2\b struct
\f3\b0
\f2\b OutputFile
\f3\b0 )\{
\f7\i path
\f3\i0 , 0, 0,
\f7\i file
\f3\i0 \});
\f7\i file
\f3\i0 =
\f7\i c
\f3\i0 ;\
\f2\b
\f3\b0 \}\
\f2\b
\f4\i\b0 Make sure the region array is large enough for this region number.\
\f2\i0\b
\f4\i\b0 and this region is allocated and ready for appends.\
\f2\i0\b if
\f3\b0 (
\f7\i r
\f3\i0 'b3
\f7\i c
\f6\i0 \uc0\u8594
\f7\i m
\f3\i0 ) \{\
\f2\b
\f7\i\b0 c
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 = realloc(
\f7\i c
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 , (
\f7\i r
\f3\i0 +1)*
\f2\b sizeof
\f3\b0 (
\f2\b Obj
\f3\b0 ));\
\f2\b
\f3\b0 memset(
\f7\i c
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 +
\f7\i c
\f6\i0 \uc0\u8594
\f7\i m
\f3\i0 , 0, (
\f7\i r
\f3\i0 +1-
\f7\i c
\f6\i0 \uc0\u8594
\f7\i m
\f3\i0 )*
\f2\b sizeof
\f3\b0 (
\f2\b Obj
\f3\b0 ));\
\f2\b
\f7\i\b0 c
\f6\i0 \uc0\u8594
\f7\i m
\f3\i0 =
\f7\i r
\f3\i0 +1;\
\f2\b
\f3\b0 \}\
\f2\b if
\f3\b0 ('c2
\f7\i c
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 [
\f7\i r
\f3\i0 ])
\f7\i c
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 [
\f7\i r
\f3\i0 ] = incr(Tcl_NewObj());\
\f2\b Obj
\f7\i\b0 newregion
\f3\i0 =
\f7\i c
\f6\i0 \uc0\u8594
\f7\i region
\f3\i0 [
\f7\i r
\f3\i0 ];\
\f2\b
\f4\i\b0 Flush any partial output of the old region before switching regions.\
\f2\i0\b if
\f3\b0 (
\f7\i partial
\f3\i0 ) oprintf(
\f7\i region
\f3\i0 , "%P\\n",
\f7\i partial
\f3\i0 );
\f7\i partial
\f3\i0 = 0;\
\f2\b
\f3\b0 trace("Q#region %d %s",
\f7\i r
\f3\i0 , Tcl_GetString(
\f7\i c
\f6\i0 \uc0\u8594
\f7\i path
\f3\i0 ));\
\f2\b <>
\f3\b0 \
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\qr\pardirnatural
\f0\b\fs26 \cf0 8.3 Errors\
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\li4340\fi-3260\ql\qnatural\pardirnatural
\f1\b0\fs24 \cf0 \
'c7
\f0\b error
\f1\b0
\f4\i errormessage
\f1\i0 'c8 Macro detected error; either written with
\f0\b macro embedded error
\f1\b0 , or the result of a macro body returning an error. This becomes C pre-parser #error directive. Such errors are discoverred scanning the output: they are not written to stderr by
\f0\b renee
\f1\b0 .\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0
\f2\b <
\f3\b0 parseAndGenerateAnEmbeddedError
\f2\b >
\f3\b0 \
\f4\i The special case below ensures this is at the beginning of a line and\
line numbers are up to date.\
\f3\i0
\f4\i Generate an #error message directive.\
\f3\i0 oprintf(
\f7\i region
\f3\i0 , "#");
\f2\b Obj
\f3\b0
\f7\i e
\f3\i0 = 0;\
while (
\f7\i embedded
\f3\i0 =
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ,
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 !=ATEM) \{\
oprintf(
\f7\i region
\f3\i0 , "%U",
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 );\
\f7\i e
\f3\i0 = oprintf(
\f7\i e
\f3\i0 , "%U",
\f7\i embedded
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 );\
\}\
oprintf(
\f7\i region
\f3\i0 , "\\n");\
\f2\b
\f3\b0 trace("Q*#%s", Tcl_GetString(
\f7\i e
\f3\i0 )); decr(
\f7\i e
\f3\i0 );\
\f2\b <>
\f3\b0 \
\f2\b <
\f3\b0 newlineForEmbeddedError
\f2\b >
\f3\b0 \
\f2\b if
\f3\b0 (
\f7\i partial
\f6\i0 \uc0\u8743
\f3 eqstring(
\f7\i output
\f3\i0 , META, 'e', 'r', 'r', 'o', 'r', ' ', 0)) \{\
\f4\i This is a special because the error directive has to start on a new line.
\f3\i0 \
\f2\b
\f3\b0 oprintf(
\f7\i region
\f3\i0 , "%P\\n",
\f7\i partial
\f3\i0 );
\f7\i partial
\f3\i0 = 0;\
printPositionsToTheRegion;\
\}\
\f2\b <>
\f3\b0 \
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\qr\pardirnatural
\f0\b\fs26 \cf0 8.4 Write function\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\fs24 \cf0 \
priv func
\f3\b0
\f2\b void
\f3\b0 writeMacroExpansionsToFileRegions(
\f2\b Intr
\f3\b0
\f7\i intr
\f3\i0 ,
\f2\b MacroContext
\f3\b0
\f7\i cx
\f3\i0 )
\f2\b is
\f3\b0 \{\
\f4\i Make sure the output area has all macros expanded before\
scanning the output for directives and text to regions.
\f3\i0 \
\f2\b
\f3\b0 expandMacrosInAccumulatedEmissions(
\f7\i intr
\f3\i0 ,
\f7\i cx
\f3\i0 );\
\f2\b AttrString
\f7\i\b0 output
\f3\i0 = first(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 ),
\f7\i embedded
\f3\i0 = 0;\
\f2\b
\f3\b0 onOffFileNumberringVariable;\
\f2\b
\f3\b0 outputFileVariables;\
\f2\b
\f3\b0 positionStackVariable;\
\f2\b
\f3\b0 positionBufferVariable;\
\f2\b bool
\f3\b0
\f7\i backslash
\f3\i0 =
\f2\b false
\f3\b0 ;\
\f2\b while
\f3\b0 (
\f7\i output
\f3\i0 ) \{\
\f2\b Pos
\f3\b0
\f7\i pos
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i pos
\f3\i0 ;
\f2\b \
if
\f3\b0 (
\f7\i output
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 &styleInclude) \{\
\f2\b
\f3\b0 pushPosition;\
\}
\f2\b else
\f3\b0 \{\
updatePosition;\
\}\
\f2\b bool
\f3\b0
\f7\i exclude
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i style
\f3\i0 &styleExclude;\
newlineForEmbeddedError;\
\f2\b if
\f3\b0 (eqstring(
\f7\i output
\f3\i0 , META, 0)) \{\
\f7\i embedded
\f3\i0 =
\f7\i output
\f3\i0 ;\
\f7\i output
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;
\f7\i \
\f2\i0\b
\f3\b0 \}
\f2\b else if
\f3\b0 (eqstring(
\f7\i output
\f3\i0 , ATEM, 0)) \{\
\f2\b if
\f3\b0 (eqstring(
\f7\i embedded
\f3\i0 , META, 'e', 'r', 'r', 'o', 'r', ' ', 0)) \{\
\f2\b
\f3\b0 parseAndGenerateAnEmbeddedError;\
\f2\b
\f3\b0 \}
\f2\b else
\f3\b0
\f2\b if
\f3\b0 (eqstring(
\f7\i embedded
\f3\i0 , META, 'o', 'n', ATEM, 0)) \{\
\f2\b
\f3\b0 turnLineNumberGenerationOn;\
\f2\b
\f3\b0 \}
\f2\b else
\f3\b0
\f2\b if
\f3\b0 (eqstring(
\f7\i embedded
\f3\i0 , META, 'o', 'f', 'f', ATEM, 0)) \{\
\f2\b
\f3\b0 turnLineNumberGenerationOff;\
\f2\b
\f3\b0 \}
\f2\b else
\f3\b0
\f2\b if
\f3\b0 (eqstring(
\f7\i embedded
\f3\i0 , META, 'r', 'e', 'g', 'i', 'o', 'n', ' ', 0)) \{\
\f2\b
\f3\b0 parseRegionDirectiveAndSendOutputToIt;\
\f2\b if
\f3\b0 (
\f7\i showing
\f3\i0 >0
\f6 \uc0\u8743
\f3
\f7\i region
\f3\i0 'ad
\f7\i newregion
\f3\i0 ) \{\
\f2\b
\f3\b0 popThenRepushPositionsAtRegionBoundary;\
\f2\b
\f3\b0 \}
\f2\b else
\f3\b0 \
\f2\b
\f7\i\b0 region
\f3\i0 =
\f7\i newregion
\f3\i0 ;\
\f2\b
\f3\b0 \}
\f0\b else
\f3\b0 \
\f2\b
\f4\i\b0 This is an unrecognised directive, which is silently ignored.\
\f7 embedded
\f3\i0 = 0;\
\f7\i output
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;
\f7\i \
\f2\i0\b
\f3\b0 \}
\f2\b else if
\f3\b0 (
\f7\i embedded
\f3\i0 ) \{\
\f2\b
\f4\i\b0 Scanning an embedded directive.
\f3\i0 \
\f7\i output
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;
\f7\i \
\f2\i0\b
\f3\b0 \}
\f2\b else
\f3\b0
\f2\b if
\f3\b0 (eqstring(
\f7\i output
\f3\i0 , BREAK, 0)) \{\
\f4\i This character corresponds to the <-> break. It has done its job\
of interfering with macro name recognition: now elide it.
\f3\i0 \
\f2\b
\f7\i\b0 output
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b
\f3\b0 \}
\f2\b else
\f3\b0
\f2\b if
\f3\b0 (eqstring(
\f7\i output
\f3\i0 , '\\n', 0)) \{\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f4\i \cf0 If the last character was a backslash, the line is regarded as still\
partial. This handles things like preventing insertion of a line\
directive into a #define \\-continued on to a new lines.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\i0\b \cf0 if
\f3\b0 (
\f7\i backslash
\f3\i0 ) \{\
\f2\b
\f7\i\b0 partial
\f3\i0 = oprintf(
\f7\i partial
\f3\i0 , "\\n");\
\f2\b
\f3\b0 \}
\f2\b else if
\f3\b0 (
\f7\i partial
\f3\i0 ) \{\
\f2\b
\f3\b0 trace("Qline: '%s'", Tcl_GetString(
\f7\i partial
\f3\i0 ));\
\f2\b
\f3\b0 oprintf(
\f7\i region
\f3\i0 , "%P\\n",
\f7\i partial
\f3\i0 );\
\f7\i partial
\f3\i0 = 0;\
\f2\b
\f3\b0 \}
\f2\b else
\f3\b0 \{\
\f2\b
\f3\b0 trace("Qline: ''");\
oprintf(
\f7\i region
\f3\i0 , "\\n");\
\f7\i partial
\f3\i0 = 0;\
\}\
\f2\b
\f7\i\b0 backslash
\f3\i0 =
\f2\b false
\f3\b0 ;
\f2\b
\f7\i\b0 output
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;
\f7\i lp
\f3\i0 += xcLpIncr;\
\f2\b
\f3\b0 \}
\f2\b else
\f3\b0 \{\
\f4\i Write any bufferred line numbers before the beginning of the next line.\
\f3\i0
\f2\b if
\f3\b0 (
\f7\i partial
\f3\i0 ==0
\f6 \uc0\u8743
\f7\i showing
\f3\i0 >0) \{\
printPositionsToTheRegion;\
\}\
\f4\i This is some other text which will be appended to the current region.\
Backslash is used to detect \\+newline combinations.\
\f2\i0\b
\f7\i\b0 backslash
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 =='\\\';\
\f2\b
\f7\i\b0 partial
\f3\i0 = oprintf(
\f7\i partial
\f3\i0 , "%U",
\f7\i output
\f6\i0 \uc0\u8594
\f7\i uc
\f3\i0 );
\f7\i output
\f3\i0 =
\f7\i output
\f6\i0 \uc0\u8594
\f7\i post
\f3\i0 ;\
\f2\b
\f3\b0 \}\
\f2\b if
\f3\b0 (
\f7\i exclude
\f3\i0 ) \{\
\f2\b
\f3\b0 popPosition;\
\}\
\}\
\f2\b if
\f3\b0 (
\f7\i showing
\f3\i0 >0) \{\
printPositionsToTheRegion;\
\}\
freeattrstring(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 );\
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i outputfirst
\f3\i0 = 0;
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i output
\f3\i0 = 0;\
outputFileRegions;\
\f2\b
\f3\b0 \}\
\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f4\i \cf0 The following code is only used for tracing macro output, not for\
the write itself.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3\i0 \cf0 \
\f2\b func chars
\f3\b0 displayPosition(
\f2\b Pos
\f3\b0
\f7\i pos
\f3\i0 )
\f2\b is
\f3\b0 \{\
\f2\b static char
\f3\b0
\f7\i dis
\f3\i0 [100];\
\f2\b chars
\f3\b0
\f7\i fn
\f3\i0 = Tcl_GetString(
\f7\i included
\f3\i0 [
\f7\i pos
\f3\i0 %xcLpIncr]);\
\f2\b chars
\f3\b0
\f7\i lf
\f3\i0 = strrchr(
\f7\i fn
\f3\i0 , '/');
\f2\b if
\f3\b0 (
\f7\i lf
\f3\i0 )
\f7\i fn
\f3\i0 =
\f7\i lf
\f3\i0 +1;\
sprintf(
\f7\i dis
\f3\i0 , "%.80s:%d",
\f7\i fn
\f3\i0 ,
\f7\i pos
\f3\i0 /xcLpIncr);\
\f2\b return
\f3\b0
\f7\i dis
\f3\i0 ;\
\}\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f8\b\fs26 \cf0 \
EXAMPLES\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f9\b0\fs24 \cf0 The
\f8\b renee
\f9\b0 source file is distributed as the source code RTF file renee.rtf as well as the assembly files renee.h and renee.c.
\f8\b renee
\f9\b0 is compiled and loaded with the Tcl library. On MacOSX,\
./renee -o next renee.rtf\
cc -O -Inext -o next/renee -framework Tcl next/renee.c\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f8\b\fs26 \cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\cf0 DIAGNOSTICS\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f9\b0\fs24 \cf0 Exit status 0 if
\f8\b -p
\f9\b0 . Otherwise 0 if the Tcl script returned okay, or 1 if error.\
\f8\b -d
\f9\b0 output is written to stderr.\
Errors during macro recognition are embedded as
\f8\b #error
\f9\b0 directives in the output files.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f8\b\fs26 \cf0 \
FILES\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f9\b0\fs24 \cf0 Reads
\f10\i rtffile
\f9\i0 and/or stdin for RTF sources. Writes macro expansion to stdout or to other files as directed.\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f8\b\fs26 \cf0 \
SEE ALSO\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\fs24 \cf0 macro(n)
\f9\b0 .\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f8\b\fs26 \cf0 \
HISTORY\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li720\ql\qnatural\pardirnatural
\f9\b0\fs24 \cf0 Jan 2007. Initial version.\
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\ql\qnatural\pardirnatur
al
\f8\b\fs28 \cf0 [[]]\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f0 \cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\qr\pardirnatural
\cf0 9 macro Command\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f2\fs24 \cf0 \
\pard\tx4320\tx4680\tx5040\tx5400\tx5760
\tx6120\tx6480\tx6840\tx7200\tx7560\tx79
20\tx8280\tx8640\ql\qnatural\pardirnatur
al
\f8\fs28 \cf0 [[
\f9\b0\fs24 macro(n).rtf
\f8\b\fs28 ]]\
\
macro(n) Tcl Command\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\cf0 \
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\fs26 \cf0 NAME\
\pard\tx1080\tx1440\tx1800\tx2160\tx2520
\tx2880\tx3240\tx3600\tx3960\tx4320\tx46
80\tx5040\tx5400\tx5760\tx6120\tx6480\tx
6840\tx7200\tx7560\tx7920\tx8280\tx8640\
li1080\fi-360\ql\qnatural\pardirnatural
\f9\b0\fs24 \cf0 macro 'd1 Macro Processor\
\pard\tx360\tx720\tx1080\tx1440\tx1800\t
x2160\tx2520\tx2880\tx3240\tx3600\tx3960
\tx4320\tx4680\tx5040\tx5400\tx5760\tx61
20\tx6480\tx6840\tx7200\tx7560\tx7920\tx
8280\tx8640\ql\qnatural\pardirnatural
\f3 \cf0 \
\f2\b priv structure
\f3\b0 *
\f2\b MacroContext is
\f3\b0 \{\
\f2\b Intr
\f3\b0
\f7\i intr
\f3\i0 ;\
\f2\b Tcl_HashTable
\f3\b0 *
\f7\i macros
\f3\i0 ;\
outputBuffer;\
\f2\b Obj
\f3\b0
\f7\i subst
\f3\i0 ;\
\f2\b Obj
\f7\i\b0 odir
\f3\i0 ;\
\f2\b int
\f3\b0
\f7\i limit
\f3\i0 ;\
\f2\b bool
\f3\b0
\f7\i limitted
\f3\i0 ;\
\f2\b int
\f3\b0
\f7\i macrocount
\f3\i0 ;\
\f2\b
\f3\b0 \};\
\f2\b \
structure
\f3\b0 *
\f2\b MacroDefinition is
\f3\b0 \{\
\f2\b Obj
\f3\b0
\f7\i name
\f3\i0 ;\
\f2\b Obj
\f7\i\b0 body
\f3\i0 ;\
\f2\b Obj
\f7\i\b0 separators
\f3\i0 ;\
\f2\b
\f3\b0 \};\
\
\f2\b <
\f3\b0 createMacroCommand
\f2\b >
\f3\b0 \{\
\f2\b MacroContext
\f3\b0
\f7\i cx
\f3\i0 = heap(
\f2\b struct
\f3\b0
\f2\b MacroContext
\f3\b0 ); memset(
\f7\i cx
\f3\i0 , 0,
\f2\b sizeof
\f3\b0 *
\f7\i cx
\f3\i0 );\
\f2\b
\f7\i\b0 cx
\f6\i0 \uc0\u8594
\f7\i intr
\f3\i0 =
\f7\i intr
\f3\i0 ; Tcl_Preserve(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i intr
\f3\i0 );\
\f2\b
\f7\i\b0 cx
\f6\i0 \uc0\u8594
\f7\i macros
\f3\i0 = heap(
\f2\b Tcl_HashTable
\f3\b0 );\
Tcl_InitHashTable(
\f7\i cx
\f6\i0 \uc0\u8594
\f7\i macros
\f3\i0 , TCL_STRING_KEYS);\
\f2\b
\f7\i\b0 cx
\f6\i0 \uc0\u8594
\f7\i subst
\f3\i0 = incr(Tcl_NewObj());\
\f2\b
\f7\i\b0 cx
\f6\i0 \uc0\u8594
|