Very old versions for history.
[opsoft_archive.git] / silentbob / silent_bob / the_tt.cpp
blob57606b3c9fb57eb14b5fedcfb06633327e213b60
1 /*
2 * (c) Oleg Puchinin 2006
3 * graycardinalster@gmail.com
4 *
5 */
7 /*
8 * "Oleg, THE_TT and BUGs"
9 *
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 **/
20 #include "functions.h"
21 #include <sys/mman.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/ioctl.h>
26 extern FILE * d_stream_dbg;
28 namespace THE_TT {
30 #define IF(arg) if (t_map[i] == arg)
31 #define IF2(arga, argb) if (t_map[i] == arga && t_map[i+1] == argb)
32 #define is_space(arg) (arg == ' ' || arg == '\t' || arg == '\n')
33 #define IF_breaker if (t_map[i]==';' || t_map[i] == '}' || t_map[i] == '{')
34 #define T t_map[i]
35 #define T2 t_map[i+1]
36 #define Toff(arg) t_map[i+arg]
37 #define ATTACH t_attach ();
39 //#define TN(arg) do { t_new[ii] = arg; ii++; } while (0)
41 int i;
42 int ii;
43 int t_size;
44 char * t_map;
45 char * t_new;
46 int t_input_line;
47 int t_op_no;
48 int brace_depth = 0; // for '()', not '{}' !
49 int block_depth = 0; // for '{}'
50 bool b_make_attachment;
51 bool t_in_macro;
52 pair_t * d_attachment = NULL;
54 // äÏÂÁ×ÉÔØ Ó×ÑÚËÕ ÎÏÍÅÒ ÏÐÅÒÁÔÏÒÁ + ÎÏÍÅÒ ÓÔÒÏËÉ.
55 inline void t_attach ()
57 t_op_no++;
58 d_attachment[t_op_no].pair_op = t_op_no;
59 d_attachment[t_op_no].pair_line = t_input_line;
60 d_attachment[t_op_no].offset = i;
61 brace_depth = 0; // Paranoid
64 // äÏÂÁ×ÉÔØ ÓÉÍ×ÏÌ "ÎÁ ×ÙÈÏÄ". åÓÌÉ ';','{','}' ÔÏ ÄÏÂÁ×ÉÔØ.
65 // ÎÏÍÅÒ ÓÔÒÏËÉ Ë ÓÐÉÓËÕ ÏÐÅÒÁÔÏÒÏ×.
66 inline void TN (char arg)
68 t_new[ii] = arg;
69 ++ii;
70 if (arg == '\n' ||
71 arg == '{' || arg == '}' ||
72 (arg == ';' && !brace_depth)) {
74 if (arg == '\n') {
75 --t_input_line;
76 ATTACH;
77 ++t_input_line;
78 } else
79 ATTACH;
83 #define TNs(arg) do { t_new[ii] = arg; ++ii; } while (0)
85 // ÐÒÏÐÕÓÔÉÔØ ËÏÍÍÅÎÔÁÒÉÊ "//"
86 inline void tt_skip ()
88 while (T != '\n' && i < t_size)
89 ++i;
90 --i;
93 /* ðÒÏÐÕÓÔÉÔØ ËÏÍÍÅÎÔÁÒÉÊ / * * / */
94 inline void tt_comment ()
96 while (i < t_size) {
97 IF2('*', '/')
98 break;
99 IF ('\n') {
100 t_input_line++;
102 i++;
104 i++;
107 // NOTE: you _must_ allocate d_input and d_output before call this.
108 // ÷ÚÑÔØ ÔÅËÓÔ D_INPUT, ÕÂÒÁÔØ ×ÓÅ ÌÉÛÎÉÅ ÐÒÏÂÅÌØÎÙÅ ÓÉÍ×ÏÌÙ,
109 // ÄÏÂÁ×ÉÔÔØ ÎÕÖÎÙÅ, ÕÂÉÔØ ËÏÍÍÅÎÔÁÒÉÉ etc É ×ÙÌÏÖÉÔØ × d_output.
110 int the_tt_for_buffers (char * d_input,
111 int t_new_size,
112 char * d_output)
114 unsigned int t_spaces = 1;
115 bool b_mustlined = false;
116 bool b_instring = false;
117 bool b_newline = true;
118 int d_slash_count = 0;
119 bool b_lined = true;
120 char ch_last = 0;
122 i = 0;
123 ii = 0;
124 b_lined = true;
125 b_mustlined = false;
126 b_newline = true;
127 t_size = t_new_size;
128 t_map = d_input;
129 t_new = d_output;
130 t_input_line = 0;
131 t_op_no = 0;
132 brace_depth = 0;
133 block_depth = 0;
135 if (t_map[0] == '\n') {
136 ++i; // "mmap BUG" fixed :))
137 ++t_input_line;
140 if (Toff (t_size-1) == '\n')
141 t_size--; // mmap'ed TT not work without this !
143 for (; i < t_size; ++i) {
144 /* I'm in string */
145 /* But count all lines anyway... */
146 IF ('\n')
147 ++t_input_line;
149 if (T == '\'' || T == '\"') {
150 if (b_instring && ch_last != T) {
151 TN(T);
152 continue;
155 if (b_instring) {
156 if (Toff(-1) != '\\') // Normal skip \" and... \\" :)
157 b_instring = false;
158 else {
159 d_slash_count = 1;
160 while (Toff (-(d_slash_count)) == '\\') // Yes, I'm don't like this.
161 d_slash_count++;
163 if (d_slash_count & 1)
164 b_instring = false;
166 } else {
167 ch_last = T;
168 b_instring = true;
172 if (b_instring) {
173 if (T != '\n')
174 TNs (T);
175 else {
176 if (Toff(-1) == '\\')
177 ii--;
179 continue;
182 if (if_abc (&t_map[i]) || if_digit (&t_map[i])) {
183 b_lined = false;
184 t_spaces = 0;
185 goto abc;
188 if (T == '\n') {
189 if (Toff(-1) == '\\') {
190 if (t_in_macro)
191 TN(T);
192 else
193 ii--;
195 continue;
196 } else
197 t_in_macro = false;
200 IF2('/','/') {
201 tt_skip ();
202 continue;
205 IF2('/', '*') {
206 tt_comment ();
207 continue;
210 // Next code for not-comment and not-string C code. May silent counting operators...
211 if (T == '(')
212 ++brace_depth;
214 if (T == ')')
215 --brace_depth;
217 if (brace_depth < 0)
218 brace_depth = 0;
220 if (is_space (T)) {
221 if (T == '\n') {
222 b_newline = true;
223 if (Toff(1) == '#' && !b_lined) {
224 TN ('\n');
225 t_spaces++;
226 b_lined = true;
227 b_mustlined = false;
228 continue;
231 if (b_mustlined) {
232 TN('\n');
233 t_spaces++;
234 if (!(Toff (-1) == '\\')) {
235 b_mustlined = false;
236 b_lined = true;
240 if (t_spaces == 0 && !b_lined) {
241 t_spaces++;
242 TN(' ');
244 continue;
245 } else {
246 t_spaces++;
247 if (t_spaces == 1)
248 TN(' ');
250 continue;
253 b_lined = false;
254 if (T == '(' && t_spaces == 0 && b_mustlined == 0) {
255 t_spaces++; // No space after '('.
256 TN(' ');
257 TN('(');
258 continue;
261 if (T == ')' && t_spaces == 0) {
262 t_spaces++;
263 TN(')');
264 TN(' ');
265 continue;
268 t_spaces = 0;
269 IF_breaker {
270 TN(T);
271 TN(' ');
272 t_spaces++;
273 continue;
276 IF('#' && b_newline) {
277 TN ('#');
278 t_in_macro = true;
279 b_mustlined = true;
280 continue;
283 IF (0x0D)
284 continue;
286 abc:
287 b_newline = false;
288 TN(T);
289 } // for
291 return ii;
294 char * do_tt_file (tt_state_t * d_tt_state)
296 char * t_output = NULL;
297 char * t_input = NULL;
298 bool b_mmap = false;
299 int t_size = 0;
300 char * f_name;
301 int t_fd = 0;
302 int t_Ret;
304 d_attachment = NULL;
306 if (! d_tt_state)
307 return 0;
309 f_name = d_tt_state->d_file_name;
311 if (EQ(f_name, "-")) {
312 t_input = Dread_to_eof (fileno (stdin), &t_size);
313 if (t_size <= 0) {
314 exit (1);
316 } else {
317 b_mmap = true;
318 t_input = DFMAP (f_name, &t_fd, &t_size);
319 if (t_input == NULL) {
320 t_size = fsize (f_name);
321 b_mmap = false;
322 t_input = CNEW (char, t_size);
323 Dfnread (f_name, t_input, t_size);
327 if (!(t_input > NULL)) {
328 fprintf (stderr, "can't open/mmap file %s\n", f_name);
329 perror ("open/mmap");
330 return NULL;
333 t_output = CNEW (char, t_size<<1); // Paranoid.
334 if (t_output == NULL) {
335 perror ("no such memory");
336 return NULL;
338 /**/
340 d_attachment = CNEW (pair_t, t_size>>1);
342 d_tt_state->d_attachment = d_attachment;
343 d_tt_state->d_fd = t_fd;
344 d_tt_state->d_file_in = t_input;
345 d_tt_state->d_filein_size = t_size;
346 d_tt_state->b_mmap = b_mmap;
348 t_Ret = the_tt_for_buffers (t_input, t_size, t_output);
349 t_output[t_Ret] = 0; // Required.
350 d_tt_state->d_output_size = t_Ret;
351 d_tt_state->d_output = t_output;
353 return t_output;
356 // $ silent_bob --the-tt
357 int the_tt_main (char * f_name)
359 char * t_output;
360 tt_state_t * d_tt_state;
362 d_tt_state = CNEW (tt_state_t, 1);
363 bzero (d_tt_state, sizeof (tt_state_t));
364 d_tt_state->d_file_name = f_name;
365 t_output = do_tt_file (d_tt_state);
367 if (! SB_FLGET (SB_FLSIMULATE))
368 write (fileno (stdout), t_output, d_tt_state->d_output_size);
370 free_tt_state (d_tt_state);
371 return EXIT_SUCCESS;
374 void free_tt_state (struct tt_state_t * S)
376 if (S->b_mmap)
377 munmap (S->d_file_in, S->d_filein_size);
378 else
379 DROP (S->d_file_in);
381 if (S->d_fd)
382 close (S->d_fd);
384 DROP (S->d_output);
385 DROP (S->d_attachment);
386 DROP (S);
389 } // namespace THE_TT