"Fossies" - the Fresh Open Source Software Archive 
Member "bbkeys-0.9.1/src/FileTokenizer.cpp" (6 Dec 2007, 5049 Bytes) of package /linux/privat/old/bbkeys-0.9.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "FileTokenizer.cpp" see the
Fossies "Dox" file reference documentation.
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // -- FileTokenizer.cpp --
3 // Copyright (c) 2001 - 2003 Jason 'vanRijn' Kasper <vR at movingparts dot net>
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 // DEALINGS IN THE SOFTWARE.
22
23 // E_O_H_VR
24
25 #include "FileTokenizer.h"
26
27 static unsigned int keywordLookup(const KeywordMap& keys, const string& tag) {
28 const KeywordMap::const_iterator it = keys.find(tag);
29 if (it != keys.end())
30 return it->second;
31 return 0;
32 }
33
34
35 static char tabToSpace(char c) {
36 if (c == '\t')
37 return ' ';
38 return c;
39 }
40
41
42 /* read a line into the string 'line', if it is continued then keep reading
43 * until we have the whole line
44 * returns the number of lines read and the line via the reference
45 */
46 static unsigned int getFullLine(ifstream& file, string& line) {
47 if (! file.good()) return 0;
48
49 getline(file, line);
50 unsigned int count = 1;
51 while (file.good() && line[line.length() - 1] == '\\') {
52 string tmp;
53 getline(file, tmp);
54 line.erase(line.length() - 1);
55 line += tmp;
56 ++count;
57 }
58 transform(line.begin(), line.end(), line.begin(), tabToSpace);
59 return count;
60 }
61
62
63
64 FileTokenizer::FileTokenizer(const KeywordMap& keys, const char* fname,
65 TokenError errhandler): filename(fname),
66 keywords(keys),
67 error(errhandler),
68 lineno(0l),
69 state(WANT_TAG) {
70 file.open(filename.c_str());
71
72 if (! file.good()) {
73 cerr << BBTOOL << ": " << "FileTokenizer::constructor: couldn't open file: [" << filename << "]" << endl;
74 }
75 }
76
77
78 FileTokenizer::~FileTokenizer(void) {
79 file.close();
80 }
81
82
83 TokenBlock* FileTokenizer::next(void) {
84 string line;
85
86 TOP:
87 unsigned int count;
88 if ((count = getFullLine(file, line)) == 0)
89 return (TokenBlock*) 0;
90 lineno += count;
91
92 TokenBlock* block = new TokenBlock;
93 block->lineno = lineno;
94
95 string::size_type pos = 0, len = line.length();
96 for (; state != WANT_NOTHING && pos < len; ++pos) {
97 if (isspace(line[pos])) continue;
98
99 if (state == WANT_TAG && line[pos] == '[') {
100 string::size_type start = ++pos;
101 while (pos < len && line[pos] != ']') ++pos; // no escapes allowed
102
103 string tag(line, start, pos - start);
104 transform(tag.begin(), tag.end(), tag.begin(), ::tolower);
105 unsigned int value = keywordLookup(keywords, tag);
106 if (value == 0) {
107 if (! error(filename, "unknown tag: " + tag, lineno))
108 goto ERR_EXIT;
109 goto TOP;
110 }
111 block->tag = value;
112 state = WANT_NAME;
113 } else if (state == WANT_NAME && line[pos] == '(') {
114 string::size_type start = ++pos;
115 while (pos < len && line[pos] != ')') {
116 if (line[pos++] == '\\') ++pos;
117 }
118
119 block->name.assign(line, start, pos - start);
120 state = WANT_DATA;
121 } else if (state == WANT_DATA && line[pos] == '{') {
122 string::size_type start = ++pos;
123 // now start to search for the closing curly bracket at the end
124 // as there might be a curly bracket in between starting and
125 // ending brackets
126 pos = len;
127 while (pos > start && line[pos] != '}') {
128 --pos;
129 }
130
131 block->data.assign(line, start, pos - start);
132 state = WANT_NOTHING;
133 } else {
134 if (line[pos] != '#') { // this isn't a comment, complain
135 const string e = "invalid input: " + string(line, pos, line.length());
136 if (! error(filename, e, lineno))
137 goto ERR_EXIT;
138 }
139 break;
140 }
141 }
142 if (state == WANT_TAG) {
143 // we never found what we wanted, so let's get a new line and try again
144 delete block;
145 goto TOP;
146 }
147
148 state = WANT_TAG; // reset state for next call
149
150 return block;
151
152 ERR_EXIT:
153 delete block;
154 return (TokenBlock*) 0;
155 }
156