1 // This is core/vul/vul_awk.cxx 2 //: 3 // \file 4 // \author Andrew W. Fitzgibbon, Oxford RRG 5 // \date 17 May 1997 6 // \verbatim 7 // Modifications 8 // AWF (Oxford) 17 May 1997: Initial version. 9 // Eric Moyer 15 Jul 2009: Added strip comment functionality 10 // \endverbatim 11 // 12 //----------------------------------------------------------------------------- 13 14 #include <cctype> 15 #include <cstring> 16 #include <iostream> 17 #include <cstdio> 18 #include "vul_awk.h" 19 20 #ifdef _MSC_VER 21 # include "vcl_msvc_warnings.h" 22 #endif 23 24 //: Construct from input stream vul_awk(std::istream & s,ModeFlags mode)25vul_awk::vul_awk(std::istream & s, ModeFlags mode) 26 : fd_(s) 27 , mode_(mode) 28 { 29 done_ = false; 30 line_number_ = 0; 31 split_line_ = nullptr; 32 33 next(); 34 } 35 ~vul_awk()36vul_awk::~vul_awk() 37 { 38 delete[] split_line_; 39 } 40 41 void next()42vul_awk::next() 43 { 44 bool do_strip_comments = (((int)mode_) & ((int)strip_comments)) != 0; 45 #if 0 46 bool do_backslash_continuations = (int(mode_) & int(backslash_continuations)) != 0; 47 #endif 48 bool discard_current_line = true; 49 while (discard_current_line) 50 { 51 bool extract_fields = true; 52 discard_current_line = false; 53 54 // Read line -- should be quite fast after the first one. 55 line_.erase(); 56 57 while (true) 58 { 59 int c = fd_.get(); 60 if (c == EOF || fd_.eof()) 61 { 62 done_ = true; 63 break; 64 } 65 if (c == '\n') 66 break; 67 line_ += char(c); 68 } 69 70 char const * linep = line_.c_str(); 71 72 // copy string 73 delete[] split_line_; 74 split_line_ = new char[line_.size() + 1]; 75 std::strcpy(split_line_, linep); 76 77 // strip comments 78 if (do_strip_comments) 79 { 80 // find the first # character 81 char * comment_char = split_line_; 82 while (*comment_char != '#' && *comment_char != '\0') 83 ++comment_char; 84 // replace the # with a single space and terminate the string. I 85 // use a single space since that will help the backslash 86 // continuation if it is ever implemented 87 if (*comment_char == '#') 88 { 89 // Replace with a space 90 *comment_char = ' '; 91 ++comment_char; 92 // Terminate the string 93 if (*comment_char != '\0') 94 { 95 *comment_char = '\0'; 96 } 97 if (comment_char - split_line_ == 1) 98 { 99 // The line was only a comment -- don't try to extract 100 // records, just discard the current line and go to the next 101 extract_fields = false; 102 discard_current_line = true; 103 } 104 } 105 } 106 107 if (extract_fields) 108 { 109 // Chop line up into fields 110 fields_.clear(); 111 char * cp = split_line_; 112 113 while (true) 114 { 115 // Eat white 116 while (*cp && std::isspace(*cp)) 117 ++cp; 118 if (!*cp) 119 break; 120 121 // Push 122 fields_.push_back(cp); 123 124 // Find nonwhite 125 while (*cp && !std::isspace(*cp)) 126 ++cp; 127 if (!*cp) 128 break; 129 130 // Zap space 131 *cp++ = '\0'; 132 } 133 } 134 // Increment line number 135 ++line_number_; 136 } 137 } 138 139 char const * line_from(int field_number) const140vul_awk::line_from(int field_number) const 141 { 142 char const * p = line_.c_str(); 143 if (field_number >= NF()) 144 field_number = NF() - 1; 145 if (field_number < 0) 146 { 147 std::cerr << "vul_awk::line_from(" << field_number << ") -- ZOIKS\n"; 148 return line(); 149 } 150 151 return p + (fields_[field_number] - split_line_); 152 } 153 154 void testvul_awk()155testvul_awk() 156 { 157 std::cout << "Start\n"; 158 for (vul_awk awk(std::cin); awk; ++awk) 159 { 160 std::cout << awk.NF() << ':' << awk[2] << std::endl; 161 } 162 } 163