source: CMT/v1r12p20020606/src/cmt_awk.cxx @ 1

Last change on this file since 1 was 1, checked in by arnault, 19 years ago

Import all tags

File size: 13.8 KB
Line 
1
2#ifdef WIN32
3#include <direct.h>
4#define popen _popen
5#define pclose _pclose
6#endif
7
8#include "cmt_awk.h"
9#include "cmt_system.h"
10
11class Parser
12{
13public:
14  Parser (Awk* awk, const cmt_string pattern, const cmt_regexp* expression) :
15          m_pattern (pattern), m_expression (expression), m_awk(awk)
16      {
17      }
18
19    /**
20     *  this first level parsing function extracts individual lines
21     *  from the text, taking care of both Unix and Windows EOL styles.
22     *
23     *   Then the second level parsing function parse_line is called.
24     */
25  Awk::condition parse (const cmt_string& text)
26      {
27        Awk::condition result = Awk::ok;
28
29        cmt_string line;
30        int pos;
31        int max_pos;
32
33        pos = 0;
34        max_pos = text.size ();
35
36        m_accumulator.erase (0);
37
38        for (pos = 0; pos < max_pos;)
39          {
40            int eol = text.find (pos, '\n');
41           
42            if (eol == cmt_string::npos)
43              {
44                  // Last line, since there is no eol at all
45                text.substr (pos, line);
46                pos = max_pos;
47              }
48            else
49              {
50                int length = 1;
51
52                int cr = text.find (pos, "\r\n");
53
54                if (cr == (eol-1))
55                  {
56                    eol = cr;
57                    length = 2;
58                  }
59
60                if (eol == pos)
61                  {
62                      // this is an empty line
63                    line = "";
64                    pos += length;
65                  }
66                else
67                  {
68                      // The eol was found beyond the current position
69                      // (ie. this is a non empty line)
70                    text.substr (pos, eol - pos, line);
71                    pos = eol + length;
72                  }
73              }
74
75            if (m_awk != 0) m_awk->inc_line_number ();
76
77              //cout << "parse> line=[" << line << "]" << endl;
78
79            result = parse_line (line);
80            if (result != Awk::ok) break;
81          }
82
83        return (result);
84      }
85
86    /**
87     *   This second level parsing function accumulates individual lines
88     *   with real trailing back slashes.
89     *    Eventually the possible text pattern or regular expression is
90     *   checked and the Awk::filter function is called in case of
91     *   succesful match onto the accumulated line.
92     */
93  Awk::condition parse_line (const cmt_string& line)
94      {
95        Awk::condition result = Awk::ok;
96        int length;
97        cmt_string temp_line = line;
98
99          //
100          // We scan the line for handling backslashes.
101          //
102          // Really terminating backslashes (ie those only followed by spaces/tabs
103          // mean continued line
104          //
105          //
106
107        bool finished = true;
108
109        length = temp_line.size ();
110
111        if (length == 0)
112          {
113              // An empty line following a backslash terminates the continuation.
114            finished = true;
115          }
116        else
117          {
118            int back_slash = temp_line.find_last_of ('\\');
119       
120        if (back_slash != cmt_string::npos)
121          {
122              //
123              // This is the last backslash
124              // check if there are only space chars after it
125              //
126           
127            bool at_end = true;
128           
129                for (int i = (back_slash + 1); i < length; i++)
130                  {
131                    char c = temp_line[i];
132                    if ((c != ' ') && (c != '\t'))
133                      {
134                        at_end = false;
135                        break;
136                      }
137                  }
138               
139                if (at_end)
140                  {
141                    temp_line.erase (back_slash);
142                    finished = false;
143                  }
144                else
145                  {
146                      // This was not a trailing backslash.
147                    finished = true;
148                  }
149              }
150       
151            m_accumulator += temp_line;
152          }
153
154          //cout << "parse_line1> accumulator=[" << m_accumulator << "]" << endl;
155          //cout << "parse_line1> finished=[" << finished << "]" << endl;
156
157        if (!finished)
158          {
159              // We still need to accumulate forthcoming lines
160              // before parsing the resulting text.
161            return (Awk::ok);
162          }
163
164          // now filter the complete accumulated line (if non empty)
165
166        if (m_accumulator != "")
167          {
168            bool ok = false;
169           
170            if (m_expression != 0)
171              {
172                if (m_expression->match (m_accumulator))
173                  {
174                    ok = true;
175                  }
176              }
177            else
178              {
179                if ((m_pattern == "") ||
180                    (m_accumulator.find (m_pattern) != cmt_string::npos))
181                  {
182                    ok = true;
183                  }
184              }
185           
186            if (ok && (m_awk != 0))
187              {
188                  //cout << "parse_line> accumulator=[" << m_accumulator << "]" << endl;
189
190                m_awk->filter (m_accumulator);
191                result = m_awk->get_last_condition ();
192              }
193
194            m_accumulator.erase (0);
195          }
196       
197        return (result);
198      }
199
200private:
201
202  cmt_string m_accumulator;
203  cmt_string m_pattern;
204  const cmt_regexp* m_expression;
205  Awk* m_awk;
206};
207
208//------------------------------------------------
209Awk::Awk ()
210{
211  m_condition = ok;
212}
213
214//------------------------------------------------
215Awk::~Awk ()
216{
217}
218
219//------------------------------------------------
220Awk::condition Awk::run (const cmt_string& text,
221                         const cmt_string& pattern)
222{
223  m_line_number = 0;
224  m_condition = ok;
225
226  begin ();
227  if (m_condition != ok) return (m_condition);
228
229  if (CmtSystem::testenv ("CMTTESTAWK"))
230    {
231      Parser p (this, pattern, 0);
232
233      m_condition = p.parse (text);
234      if (m_condition != ok) return (m_condition);
235    }
236  else
237    {
238      cmt_string line;
239      int pos = 0;
240      int max_pos;
241
242      max_pos = text.size ();
243
244      for (pos = 0; pos < max_pos;)
245        {
246          int cr = text.find (pos, "\r\n");
247          int nl = text.find (pos, '\n');
248         
249            // Get the first end-of-line (either lf or cr-lf)
250
251            //--------------------
252            //
253            //     cr    1    0
254            //   nl
255            //
256            //    1      a    b
257            //
258            //    0      c    d
259            //
260            //--------------------
261         
262          int first = nl;
263         
264          if (cr != cmt_string::npos)
265            {
266                // cases a or c
267
268              if (nl == cmt_string::npos)
269                {
270                    // case a
271                  first = cr;
272                }
273              else
274                {
275                    // case c
276                  first = (nl < cr) ? nl : cr;
277                }
278            }
279         
280          if (first == cmt_string::npos)
281            {
282                // This is likely the last line since there is no end-of-line
283              text.substr (pos, line);
284              pos = max_pos;
285            }
286          else if (first > pos)
287            {
288                // The eol was found beyond the current position
289                // (ie. this is a non empty line)
290              text.substr (pos, first - pos, line);
291              pos = first + 1;
292            }
293          else
294            {
295                // an empty line
296              line = "";
297              pos++;
298            }
299         
300          m_line_number++;
301         
302          if (line != "")
303            {
304              if ((pattern == "") ||
305                  (line.find (pattern) != cmt_string::npos))
306                {
307                  filter (line);
308                  if (m_condition != ok) return (m_condition);
309                }
310            }
311        }
312    }
313
314  end ();
315
316  return (m_condition);
317}
318
319//------------------------------------------------
320Awk::condition Awk::run (const cmt_string& text,
321                         const cmt_regexp& expression)
322{
323  m_line_number = 0;
324  m_condition = ok;
325
326  begin ();
327  if (m_condition != ok) return (m_condition);
328
329  Parser p (this, "", &expression);
330
331  m_condition = p.parse (text);
332  if (m_condition != ok) return (m_condition);
333
334    /*
335  if (CmtSystem::testenv ("CMTTESTAWK"))
336    {
337    }
338  else
339    {
340      cmt_string line;
341      int pos = 0;
342      int max_pos;
343
344      max_pos = text.size ();
345
346      for (pos = 0; pos < max_pos;)
347        {
348          int cr = text.find (pos, "\r\n");
349          int nl = text.find (pos, '\n');
350         
351            // Get the first end-of-line (either lf or cr-lf)
352         
353          int first = nl;
354         
355          if (cr != cmt_string::npos)
356            {
357              if (nl == cmt_string::npos)
358                {
359                  first = cr;
360                }
361              else
362                {
363                  first = (nl < cr) ? nl : cr;
364                }
365            }
366         
367          if (first == cmt_string::npos)
368            {
369                // This is likely the last line since there is no end-of-line
370              text.substr (pos, line);
371              pos = max_pos;
372            }
373          else if (first > pos)
374            {
375                // The eol was found beyond the current position
376                // (ie. this is a non empty line)
377              text.substr (pos, first - pos, line);
378              pos = first + 1;
379            }
380          else
381            {
382                // an empty line
383              line = "";
384              pos++;
385            }
386         
387          m_line_number++;
388         
389          if (line != "")
390            {
391              if (expression.match (line))
392                {
393                  filter (line);
394                  if (m_condition != ok) return (m_condition);
395                }
396            }
397        }
398    }
399    */
400
401  end ();
402
403  return (m_condition);
404}
405
406//------------------------------------------------
407void Awk::stop ()
408{
409  m_condition = stopped;
410}
411
412//------------------------------------------------
413void Awk::abort ()
414{
415  m_condition = failed;
416}
417
418//------------------------------------------------
419void Awk::allow_continuation ()
420{
421  m_continuation_allowed = true;
422}
423
424//------------------------------------------------
425Awk::condition Awk::get_last_condition () const
426{
427  return (m_condition);
428}
429
430//------------------------------------------------
431void Awk::begin ()
432{
433}
434
435//------------------------------------------------
436void Awk::filter (const cmt_string& /*line*/)
437{
438    //cout << "awk> " << line << endl;
439}
440
441//------------------------------------------------
442void Awk::end ()
443{
444}
445
446//------------------------------------------------
447void Awk::inc_line_number ()
448{
449  m_line_number++;
450}
451
452//------------------------------------------------
453Awk::condition FAwk::run (const cmt_string& file_name,
454                          const cmt_string& pattern)
455{
456  if (!CmtSystem::test_file (file_name)) return (failed);
457
458  CmtSystem::basename (file_name, m_file_name);
459  CmtSystem::dirname (file_name, m_dir_name);
460
461  cmt_string text;
462
463  text.read (file_name);
464
465  return (Awk::run (text, pattern));
466}
467
468//------------------------------------------------
469Awk::condition FAwk::run (const cmt_string& file_name,
470                          const cmt_regexp& expression)
471{
472  if (!CmtSystem::test_file (file_name)) return (failed);
473
474  CmtSystem::basename (file_name, m_file_name);
475  CmtSystem::dirname (file_name, m_dir_name);
476
477  cmt_string text;
478
479  text.read (file_name);
480
481  return (Awk::run (text, expression));
482}
483
484//------------------------------------------------
485Awk::condition PAwk::run (const cmt_string& command, 
486                          const cmt_string& pattern)
487{
488  cmt_string line;
489
490  m_line_number = 0;
491  m_condition = ok;
492
493  begin ();
494  if (m_condition != ok) return (m_condition);
495
496  FILE* f = popen (command.c_str (), "r"); 
497 
498  if (f == 0) return (failed);
499
500  char buffer[8192]; 
501  char* ptr;
502
503  while ((ptr = fgets (buffer, sizeof (buffer), f)) != NULL) 
504    {
505      line = ptr;
506
507      if (line.find ("\n") == cmt_string::npos)
508        {
509          cerr << "#CMT> Warning : Line too long and truncated in PAwk::run for command " << command << endl;
510        }
511
512      line.replace ("\n", "");
513
514      m_line_number++;
515
516      if (line != "")
517        {
518          if ((pattern == "") ||
519              (line.find (pattern) != cmt_string::npos))
520            {
521              filter (line);
522              if (m_condition != ok) return (m_condition);
523            }
524        }
525    }
526
527  pclose (f);
528
529  end ();
530
531  return (m_condition);
532}
533
534//------------------------------------------------
535Awk::condition PAwk::run (const cmt_string& command, 
536                          const cmt_regexp& expression)
537{
538  cmt_string line;
539
540  m_line_number = 0;
541  m_condition = ok;
542
543  begin ();
544  if (m_condition != ok) return (m_condition);
545
546  FILE* f = popen (command.c_str (), "r"); 
547 
548  if (f == 0) return (failed);
549
550  char buffer[256]; 
551  char* ptr;
552
553  while ((ptr = fgets (buffer, sizeof (buffer), f)) != NULL) 
554    {
555      line = ptr;
556
557      line.replace ("\n", "");
558
559      m_line_number++;
560
561      if (line != "")
562        {
563          if (expression.match (line))
564            {
565              filter (line);
566              if (m_condition != ok) return (m_condition);
567            }
568        }
569    }
570
571  pclose (f);
572
573  end ();
574
575  return (m_condition);
576}
577
Note: See TracBrowser for help on using the repository browser.