+ Fixes
[opsoft.git] / silentbob / sblib / the_fly.cxx
bloba4e0009a03b1941fe498b14d84b052ac580351e1
1 /*
2 * (c) Oleg Puchinin 2006,2007,2008
3 * graycardinalster@gmail.com
5 * Oleg, "THE FLY", and BUGS.
6 *
7 * "THE FLY" - "THE TT" analog for Perl code.
8 * 1 May 2006 - started.
9 * 26/06/06 - v1.0-rc1.
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <ctype.h>
17 #include <gclib/gclib.h>
18 #include <mod.h>
19 #include <head.h>
20 #include <dbg.h>
21 #include <the_tt.h>
22 #include "the_fly.hpp"
24 namespace THE_FLY {
26 char * t_map;
27 char * t_new;
28 char pch;
29 int i;
30 int ii;
31 int t_size;
32 int spaces;
33 int nlines;
34 int t_op_no;
35 pair_t * d_attachment = NULL;
37 #define T t_map[i]
39 inline void t_attach ()
41 t_op_no++;
42 d_attachment[t_op_no].pair_op = t_op_no;
43 d_attachment[t_op_no].pair_line = nlines;
44 d_attachment[t_op_no].offset = i;
47 inline void TN (char ch)
49 t_new[ii] = ch;
50 ++ii;
51 if ((i && t_map[i-1] != '\\') && (ch == '{' || ch == '}' || ch == ';'))
52 t_attach ();
55 inline char * fly_fw (char * word)
57 char * Ret;
58 char *S = word;
59 while (true) {
60 if (!if_abc (S) &&
61 !if_digit (S) &&
62 *S != '_' &&
63 *S != '*')
64 break;
65 ++S;
67 Ret = CNEW (char, S - word + 1);
68 memcpy (Ret, word, S - word);
69 Ret[S-word] = '\0';
70 return Ret;
73 void fly_skip ()
75 char * word = NULL;
76 char * S = NULL;
77 char * ptrn = NULL;
79 word = &t_map[i+2];
80 if (*word == '\'' || *word == '\"')
81 ++word;
83 word = fly_fw (word);
84 if (! word)
85 return;
87 ptrn = CNEW (char, strlen (word)+3);
88 sprintf (ptrn, "\n%s\n", word);
89 S = (char *) Dmemmem (&t_map[i+2], t_size-i-2, ptrn, strlen (ptrn));
90 assert (! S, "fly_skip fail !");
91 if (! S) {
92 i = t_size;
93 goto out;
96 nlines += Dsyms (&t_map[i+2], S, '\n');
97 nlines+=2;
98 i += S - &t_map[i] + strlen (ptrn) + 1;
100 out:
101 DROP (ptrn);
102 DROP (word);
105 void doc_skip ()
107 char *S;
108 char * ptrn = (char *) "\n=cut\n";
110 S = (char *) Dmemmem (&t_map[i], t_size-i, ptrn, 6);
111 if (! S) {
112 i = t_size;
113 return;
116 nlines += Dsyms (&t_map[i], S, '\n');
117 ++nlines;
118 i += S - &t_map[i] + 4;
121 void regexp_skip ()
123 char ss;
124 int count;
125 char * ptr;
126 int old;
128 count = 1;
129 old = i;
130 switch (T) {
131 case 't':
132 i+=2;
133 break;
134 case 's':
135 ++i;
136 count = 2;
137 break;
138 case 'm':
139 ++i;
140 break;
143 ss = T;
144 if (ss == '{')
145 ss = '}';
146 ++i;
147 ptr = &t_map[i];
148 while (true) {
149 for (; i < t_size; ++i) {
150 if (T == '\n')
151 break;
153 if (t_map[i] == ss && !(ww_nsyms_r (ptr, &t_map[i-1], '\\') % 2))
154 break;
157 if (T == '\n')
158 break;
160 assert (i >= t_size, "Sibadi 2006.2");
161 if (i >= t_size)
162 break;
164 if (--count == 0)
165 break;
166 ++i;
169 if (T == '\n') {
170 i = old;
171 TN(T);
175 bool regexp_test ()
177 char * ptr;
178 char ch = T;
179 char ss;
181 if (isalnum (pch) || pch == '_' || pch == ')')
182 return false;
184 if (! (ch == '/' || ch == 's' || ch == 'm' || !strncmp (&t_map[i], "tr", 2)))
185 return false;
187 ptr = &t_map[i];
188 ++ptr;
189 switch (ch) {
190 case 't':
191 ++ptr;
192 case 's':
193 case 'm':
194 ss = *ptr;
195 if (! (ss == '/' || ss == '?' || ss == '#'
196 || ss == '!' || ss == '&' || ss == '|' || ss == '{'))
197 return false;
198 break;
201 return true;
204 inline void tt_skip ()
206 while (T != '\n' && i < t_size)
207 ++i;
208 --i;
211 int fly_for_buffers (char * d_input, int size, char * d_output)
213 char ch;
214 char * S;
216 i = 0;
217 ii = 0;
218 t_size = size;
219 t_map = d_input;
220 t_new = d_output;
221 spaces = 0;
222 nlines = 0;
223 pch = 'a';
224 t_op_no = 0;
226 i = 0;
227 if (T == '#' || T == '=') {
228 tt_skip ();
229 ++i;
232 for (; i < size; i++) {
233 ch = T;
234 if (ch == '\n')
235 ++nlines;
237 if (regexp_test ()) {
238 regexp_skip ();
239 continue;
242 if (if_digit (&t_map[i]) || if_abc (&t_map[i])) {
243 spaces = 0;
244 goto abc;
247 if ((ch == '\'' || ch == '\"') && t_map[i-1] != '$' && t_map[i-1] != '\\') {
248 if (ch == '\'' && (isalnum (t_map[i-1]) || t_map[i-1] == '&'))
249 goto abc;
251 S = sstrend (&t_map[i]);
252 assert (S == NULL, "\n\nSibadi 2006\n\n");
253 nlines += Dsyms (&t_map[i], S, '\n');
254 i += S - &t_map[i];
255 pch = ch;
256 TN (ch);
257 TN (ch);
258 continue;
261 if (ch == '\n' || ch == ' ' || ch == '\t') {
262 if (spaces == 0) {
263 TN (' ');
264 spaces++;
265 continue;
266 } else
267 continue;
270 if (ch == '<' && t_map[i+1] == '<') {
271 fly_skip ();
272 if (i >= t_size) {
273 TN ('\0');
274 break;
276 TN (';');
277 TN (' ');
278 spaces = 0;
279 pch = ch;
280 continue;
283 if (ch == ';' || ch == '}' || ch == ')' ||
284 ch == '{' || ch == '(') {
285 if (! spaces)
286 TN (' ');
287 TN (ch);
288 TN (' ');
289 spaces = 1;
290 pch = ch;
291 continue;
294 if (ch == '=' && t_map[i-1] == '\n') {
295 doc_skip ();
296 pch = ch;
297 continue;
300 if (ch == '#' && t_map[i-1] != '$') {
301 tt_skip ();
302 pch = ch;
303 continue;
306 abc:
307 pch = ch;
308 TN(T);
311 TN('\0');
312 return ii;
315 char * fly_for_file (struct tt_state_t * tt)
317 int m_size;
319 if (! tt)
320 return NULL;
322 if (access (tt->fileName, R_OK) != F_OK) {
323 fprintf (stderr, "No such file %s\n", tt->fileName);
324 return NULL;
327 tt_map (tt);
329 m_size = fsize (tt->fileName);
330 tt->result = CNEW (char, m_size << 2);
331 tt->result[0] = 0;
332 d_attachment = (pair_t *) CNEW (char, m_size << 2);
333 tt->attachment = d_attachment;
334 tt->resultSize = fly_for_buffers (tt->fileData, tt->fileDataSize, tt->result);
336 return tt->result;
339 } // namespace THE_FLY