2 * (c) Oleg Puchinin 2006,2007,2008
3 * graycardinalster@gmail.com
8 * "Oleg, THE_TT and BUGs"
10 * 01/01/06 00:00 - Started...
11 * January 2006 - string BUG fixed.
12 * "//" BUG fixed. It's work currently ?!
14 * January 2006, last day. added operator to line conversion.
15 * February 2006 - operator to line conversion work properly.
16 * February 2006 - "macro BUG" fixed.
17 * March 2006 - "Style BUG" fixed (?).
18 * January 2008 - C# patch.
22 #include <bob_flags.h>
26 extern FILE * d_stream_dbg
;
30 #define IF(arg) if (t_map[ipos] == arg)
31 #define IF2(arga, argb) if (t_map[ipos] == arga && t_map[ipos+1] == argb)
32 #define is_space(arg) (arg == ' ' || arg == '\t' || arg == '\n')
33 #define IF_breaker if (t_map[ipos]==';' || t_map[ipos] == '}' || t_map[ipos] == '{')
35 #define T2 t_map[ipos+1]
36 #define Toff(arg) t_map[ipos+arg]
37 #define ATTACH t_attach ();
46 int brace_depth
= 0; // for '()'
47 int block_depth
= 0; // for '{}'
48 bool b_make_attachment
;
50 pair_t
* d_attachment
= NULL
;
51 char * tt_out_buf
= NULL
;
52 int tt_outbuf_size
= 0;
53 unsigned int t_spaces
;
62 inline void t_attach ()
65 d_attachment
[t_op_no
].pair_op
= t_op_no
;
66 d_attachment
[t_op_no
].pair_line
= t_current_line
;
67 d_attachment
[t_op_no
].offset
= ipos
;
68 brace_depth
= 0; // Paranoid
71 inline void TN (char arg
)
76 arg
== '{' || arg
== '}' ||
77 (arg
== ';' && !brace_depth
)) {
88 #define TNs(arg) do { t_new[opos] = arg; ++opos; } while (0)
90 inline void tt_comment ()
92 while (ipos
< t_size
) {
103 inline void tt_skip ()
105 while (T
!= '\n' && ipos
< t_size
)
110 void tt_init (char * d_input
, int t_new_size
, char * d_output
)
135 bool tt_process_line ()
137 if (b_instring
&& ch_last
!= T
) {
143 if (b_sharp
|| (Toff(-1) != '\\')) { // \" and... \\" :)
148 while (Toff (-(d_slash_count
)) == '\\') // Yes, I'm don't like this.
151 if (d_slash_count
& 1) {
156 } else { // !b_instring
159 if (Toff (-1) == '@')
166 void tt_process_space ()
170 if (Toff(1) == '#' && !b_lined
) {
181 if (!(Toff (-1) == '\\')) {
187 if (t_spaces
== 0 && !b_lined
) {
201 // NOTE: you _must_ allocate d_input and d_output before call this.
202 int the_tt_for_buffers (char * d_input
,
206 tt_init (d_input
, t_new_size
, d_output
);
208 if (t_map
[0] == '\n') {
209 ++ipos
; // "mmap BUG" fixed :))
213 if (Toff (t_size
-1) == '\n')
214 t_size
--; // mmap'ed TT do not work without this !
216 for (; ipos
< t_size
; ++ipos
) {
217 if (if_abc (&t_map
[ipos
]) || if_digit (&t_map
[ipos
])) {
226 if (T
== '\'' || T
== '\"') {
227 if (tt_process_line ())
235 if (Toff(-1) == '\\')
242 if (Toff(-1) == '\\') {
280 if (T
== '(' && t_spaces
== 0 && b_mustlined
== 0) {
281 ++t_spaces
; // No space after '('.
287 if (T
== ')' && t_spaces
== 0) {
302 IF('#' && b_newline
) {
320 char * do_tt_file (tt_state_t
* d_tt_state
)
322 char * t_output
= NULL
;
331 f_name
= d_tt_state
->fileName
;
333 if (EQ(f_name
, "-")) {
334 d_tt_state
->fileData
= Dread_to_eof (fileno (stdin
), &d_tt_state
->fileDataSize
);
335 if (d_tt_state
->fileDataSize
<= 0)
338 if (tt_map (d_tt_state
) < 0)
342 t_size
= d_tt_state
->fileDataSize
;
343 t_output
= CNEW (char, t_size
<<1); // Paranoid.
346 d_attachment
= CNEW (pair_t
, 4096);
348 d_attachment
= CNEW (pair_t
, t_size
>>1);
349 d_tt_state
->attachment
= d_attachment
;
351 t_Ret
= the_tt_for_buffers (d_tt_state
->fileData
, t_size
, t_output
);
352 t_output
[t_Ret
] = 0; // Required.
353 d_tt_state
->resultSize
= t_Ret
;
354 d_tt_state
->result
= t_output
;
359 // $ silent_bob --the-tt
360 int the_tt_main (char * f_name
)
363 tt_state_t
* d_tt_state
;
365 d_tt_state
= CNEW (tt_state_t
, 1);
366 memset (d_tt_state
, 0, sizeof (tt_state_t
));
367 d_tt_state
->fileName
= f_name
;
368 t_output
= do_tt_file (d_tt_state
);
370 if (! SB_FLGET (SB_FLSIMULATE
))
371 write (fileno (stdout
), t_output
, d_tt_state
->resultSize
);
373 free_tt_state (d_tt_state
);
377 } // namespace THE_TT
379 void free_tt_state (struct tt_state_t
* S
)
382 munmap (S
->fileData
, S
->fileDataSize
);
390 DROP (S
->attachment
);
394 int tt_map (tt_state_t
*tt
)
397 tt
->fileData
= DFMAP (tt
->fileName
, &tt
->fd
, &tt
->fileDataSize
);
399 if (tt
->fileData
== NULL
) {
400 tt
->fileDataSize
= fsize (tt
->fileName
);
402 tt
->fileData
= CNEW (char, tt
->fileDataSize
);
403 if (Dfnread (tt
->fileName
, tt
->fileData
, tt
->fileDataSize
) < 0)
407 if (! tt
->fileData
) {
408 fprintf (stderr
, "can't open/mmap file %s\n", tt
->fileName
);
409 perror ("open/mmap");