core/vul/vul_awk.cxx
Go to the documentation of this file.
00001 // This is core/vul/vul_awk.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Andrew W. Fitzgibbon, Oxford RRG
00008 // \date   17 May 1997
00009 // \verbatim
00010 //  Modifications
00011 //   AWF (Oxford)     17 May 1997: Initial version.
00012 //   Eric Moyer       15 Jul 2009: Added strip comment functionality
00013 // \endverbatim
00014 //
00015 //-----------------------------------------------------------------------------
00016 
00017 #include "vul_awk.h"
00018 
00019 #include <vcl_cctype.h>
00020 #include <vcl_cstring.h>
00021 #include <vcl_iostream.h>
00022 #include <vcl_cstdio.h> // for EOF
00023 
00024 //: Construct from input stream
00025 vul_awk::vul_awk(vcl_istream& s, ModeFlags mode):
00026   fd_(s),
00027   mode_(mode)
00028 {
00029   done_ = false;
00030   line_number_ = 0;
00031   split_line_ = 0;
00032 
00033   next();
00034 }
00035 
00036 vul_awk::~vul_awk()
00037 {
00038   delete [] split_line_;
00039 }
00040 
00041 void vul_awk::next()
00042 {
00043   bool do_strip_comments = ( ((int)mode_) & ((int)strip_comments) ) != 0;
00044 #if 0
00045   bool do_backslash_continuations = (int(mode_) & int(backslash_continuations)) != 0;
00046 #endif
00047   bool discard_current_line = true;
00048   while (discard_current_line)
00049   {
00050     bool extract_fields = true;
00051     discard_current_line = false;
00052 
00053     // Read line -- should be quite fast after the first one.
00054     line_.erase();
00055 
00056     while (true) {
00057       int c = fd_.get();
00058       if (c == EOF  ||  fd_.eof()) {
00059         done_ = true;
00060         break;
00061       }
00062       if (c == '\n')
00063         break;
00064       line_ += char(c);
00065     }
00066 
00067     char const* linep = line_.c_str();
00068 
00069     // copy string
00070     delete [] split_line_;
00071     split_line_ = new char[line_.size() + 1];
00072     vcl_strcpy(split_line_, linep);
00073 
00074     //strip comments
00075     if (do_strip_comments) {
00076       //find the first # character
00077       char* comment_char = split_line_;
00078       while (*comment_char != '#' && *comment_char != '\0') ++comment_char;
00079       //replace the # with a single space and terminate the string.  I
00080       //use a single space since that will help the backslash
00081       //continuation if it is ever implemented
00082       if (*comment_char == '#') {
00083         //Replace with a space
00084         *comment_char = ' '; ++comment_char;
00085         //Terminate the string
00086         if (*comment_char != '\0') { *comment_char = '\0'; }
00087         if (comment_char - split_line_ == 1) {
00088           //The line was only a comment -- don't try to extract
00089           //records, just discard the current line and go to the next
00090           extract_fields = false;
00091           discard_current_line = true;
00092         }
00093       }
00094     }
00095 
00096     if (extract_fields) {
00097       // Chop line up into fields
00098       fields_.clear();
00099       char* cp = split_line_;
00100 
00101       while (true) {
00102         // Eat white
00103         while (*cp && vcl_isspace(*cp))
00104           ++cp;
00105         if (!*cp) break;
00106 
00107         // Push
00108         fields_.push_back(cp);
00109 
00110         // Find nonwhite
00111         while (*cp && !vcl_isspace(*cp))
00112           ++cp;
00113         if (!*cp) break;
00114 
00115         // Zap space
00116         *cp++ = '\0';
00117       }
00118     }
00119     // Increment line number
00120     ++line_number_;
00121   }
00122 }
00123 
00124 char const* vul_awk::line_from(int field_number) const
00125 {
00126   char const *p = line_.c_str();
00127   if (field_number >= NF())
00128     field_number = NF() - 1;
00129   if (field_number < 0) {
00130     vcl_cerr << "vul_awk::line_from("<< field_number <<") -- ZOIKS\n";
00131     return line();
00132   }
00133 
00134   return p + (fields_[field_number] - split_line_);
00135 }
00136 
00137 void testvul_awk()
00138 {
00139   vcl_cout << "Start\n";
00140   for (vul_awk awk(vcl_cin); awk; ++awk) {
00141     vcl_cout << awk.NF() << ':' << awk[2] << vcl_endl;
00142   }
00143 }