passenger 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

data/NEWS CHANGED
@@ -1,3 +1,23 @@
1
+ Release 3.0.2
2
+ -------------
3
+
4
+ * [Nginx] Fixed compilation problems
5
+ The Nginx compilation process was broken due to not correctly reverting
6
+ the working directory of the Nginx configure script. This has been fixed:
7
+ issue #595.
8
+ * [Nginx] Fixed crash if passenger_root refers to a nonexistant directory
9
+ Issue #599.
10
+ * Fixed compilation problems on NetBSD
11
+ There was a typo in a NetBSD-specific fcntl() call. It also turns out that
12
+ NetBSD doesn't support some ISO C99 math functions like llroundl(); this
13
+ has been worked around by using other functions. Issue #593.
14
+ * Fixed file descriptor closing issues on FreeBSD
15
+ Phusion Passenger child processes didn't correct close file descriptors
16
+ on FreeBSD because it queries /dev/fd to do that. On FreeBSD /dev/fd
17
+ only returns meaningful results if fdescfs is mounted, which it isn't
18
+ by default. Issue #597.
19
+
20
+
1
21
  Release 3.0.1
2
22
  -------------
3
23
 
@@ -71,6 +71,7 @@ def define_common_library_task(namespace, output_dir, extra_compiler_flags = nil
71
71
  AgentsStarter.cpp
72
72
  AgentsStarter.h
73
73
  AgentsStarter.hpp
74
+ IniFile.h
74
75
  ResourceLocator.h
75
76
  MessageClient.h
76
77
  MessageChannel.h
@@ -51,7 +51,7 @@
51
51
  <a name="l00026"></a>00026 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_CONSTANTS_H_</span>
52
52
  <a name="l00027"></a>00027 <span class="preprocessor"></span>
53
53
  <a name="l00028"></a>00028 <span class="comment">/* Don&#39;t forget to update lib/phusion_passenger.rb too. */</span>
54
- <a name="l00029"></a>00029 <span class="preprocessor">#define PASSENGER_VERSION &quot;3.0.1&quot;</span>
54
+ <a name="l00029"></a>00029 <span class="preprocessor">#define PASSENGER_VERSION &quot;3.0.2&quot;</span>
55
55
  <a name="l00030"></a>00030 <span class="preprocessor"></span>
56
56
  <a name="l00031"></a>00031 <span class="preprocessor">#define FEEDBACK_FD 3</span>
57
57
  <a name="l00032"></a>00032 <span class="preprocessor"></span>
@@ -0,0 +1,527 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
5
+ <title>Passenger: IniFile.h Source File</title>
6
+ <link href="tabs.css" rel="stylesheet" type="text/css"/>
7
+ <link href="doxygen.css" rel="stylesheet" type="text/css"/>
8
+ </head>
9
+ <body>
10
+ <!-- Generated by Doxygen 1.6.2 -->
11
+ <div class="navigation" id="top">
12
+ <div class="tabs">
13
+ <ul>
14
+ <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
15
+ <li><a href="modules.html"><span>Modules</span></a></li>
16
+ <li><a href="namespaces.html"><span>Namespaces</span></a></li>
17
+ <li><a href="annotated.html"><span>Classes</span></a></li>
18
+ <li class="current"><a href="files.html"><span>Files</span></a></li>
19
+ </ul>
20
+ </div>
21
+ <div class="tabs">
22
+ <ul>
23
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
24
+ </ul>
25
+ </div>
26
+ <h1>IniFile.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="preprocessor">#ifndef _PASSENGER_INI_FILE_H_</span>
27
+ <a name="l00002"></a>00002 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_INI_FILE_H_</span>
28
+ <a name="l00003"></a>00003 <span class="preprocessor"></span>
29
+ <a name="l00004"></a>00004 <span class="preprocessor">#include &lt;utility&gt;</span>
30
+ <a name="l00005"></a>00005 <span class="preprocessor">#include &lt;string&gt;</span>
31
+ <a name="l00006"></a>00006 <span class="preprocessor">#include &lt;map&gt;</span>
32
+ <a name="l00007"></a>00007 <span class="preprocessor">#include &lt;fstream&gt;</span>
33
+ <a name="l00008"></a>00008 <span class="preprocessor">#include &lt;iostream&gt;</span>
34
+ <a name="l00009"></a>00009 <span class="preprocessor">#include &lt;cstdio&gt;</span>
35
+ <a name="l00010"></a>00010 <span class="preprocessor">#include &lt;cstring&gt;</span>
36
+ <a name="l00011"></a>00011 <span class="preprocessor">#include &lt;cassert&gt;</span>
37
+ <a name="l00012"></a>00012 <span class="preprocessor">#include &lt;cctype&gt;</span>
38
+ <a name="l00013"></a>00013 <span class="preprocessor">#include &lt;boost/shared_ptr.hpp&gt;</span>
39
+ <a name="l00014"></a>00014 <span class="preprocessor">#include &lt;boost/make_shared.hpp&gt;</span>
40
+ <a name="l00015"></a>00015 <span class="preprocessor">#include &lt;Exceptions.h&gt;</span>
41
+ <a name="l00016"></a>00016
42
+ <a name="l00017"></a>00017 <span class="keyword">namespace </span>Passenger {
43
+ <a name="l00018"></a>00018
44
+ <a name="l00019"></a>00019 <span class="keyword">using namespace </span>std;
45
+ <a name="l00020"></a>00020 <span class="keyword">using namespace </span>boost;
46
+ <a name="l00021"></a>00021
47
+ <a name="l00022"></a>00022
48
+ <a name="l00023"></a>00023 <span class="keyword">class </span>IniFileSection {
49
+ <a name="l00024"></a>00024 <span class="keyword">protected</span>:
50
+ <a name="l00025"></a>00025 <span class="keyword">typedef</span> map&lt;string, string&gt; ValueMap;
51
+ <a name="l00026"></a>00026 <span class="keywordtype">string</span> sectionName;
52
+ <a name="l00027"></a>00027 ValueMap values;
53
+ <a name="l00028"></a>00028
54
+ <a name="l00029"></a>00029 <span class="keyword">public</span>:
55
+ <a name="l00030"></a>00030 IniFileSection(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;sectionName) {
56
+ <a name="l00031"></a>00031 this-&gt;sectionName = sectionName;
57
+ <a name="l00032"></a>00032 }
58
+ <a name="l00033"></a>00033
59
+ <a name="l00034"></a>00034 <span class="keywordtype">bool</span> hasKey(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;keyName)<span class="keyword"> const </span>{
60
+ <a name="l00035"></a>00035 <span class="keywordflow">return</span> values.find(keyName) != values.end();
61
+ <a name="l00036"></a>00036 }
62
+ <a name="l00037"></a>00037
63
+ <a name="l00038"></a>00038 <span class="keywordtype">string</span> <span class="keyword">get</span>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;keyName) <span class="keyword">const</span> {
64
+ <a name="l00039"></a>00039 ValueMap::const_iterator it = values.find(keyName);
65
+ <a name="l00040"></a>00040 <span class="keywordflow">if</span> (it != values.end()) {
66
+ <a name="l00041"></a>00041 <span class="keywordflow">return</span> it-&gt;second;
67
+ <a name="l00042"></a>00042 } <span class="keywordflow">else</span> {
68
+ <a name="l00043"></a>00043 <span class="keywordflow">return</span> string();
69
+ <a name="l00044"></a>00044 }
70
+ <a name="l00045"></a>00045 }
71
+ <a name="l00046"></a>00046
72
+ <a name="l00047"></a>00047 <span class="keywordtype">string</span> operator[](<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;keyName)<span class="keyword"> const </span>{
73
+ <a name="l00048"></a>00048 <span class="keywordflow">return</span> <span class="keyword">get</span>(keyName);
74
+ <a name="l00049"></a>00049 }
75
+ <a name="l00050"></a>00050
76
+ <a name="l00051"></a>00051 <span class="keywordtype">void</span> <span class="keyword">set</span>(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;keyName, <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;value) {
77
+ <a name="l00052"></a>00052 values[keyName] = value;
78
+ <a name="l00053"></a>00053 }
79
+ <a name="l00054"></a>00054
80
+ <a name="l00055"></a>00055 <span class="keywordtype">string</span> getSectionName()<span class="keyword"> const </span>{
81
+ <a name="l00056"></a>00056 <span class="keywordflow">return</span> sectionName;
82
+ <a name="l00057"></a>00057 }
83
+ <a name="l00058"></a>00058
84
+ <a name="l00059"></a>00059 <span class="keywordtype">void</span> inspect()<span class="keyword"> const </span>{
85
+ <a name="l00060"></a>00060 ValueMap::const_iterator it = values.begin();
86
+ <a name="l00061"></a>00061 <span class="keywordflow">while</span> (it != values.end()) {
87
+ <a name="l00062"></a>00062 cout &lt;&lt; it-&gt;first &lt;&lt; <span class="stringliteral">&quot; = &quot;</span> &lt;&lt; it-&gt;second &lt;&lt; endl;
88
+ <a name="l00063"></a>00063 it++;
89
+ <a name="l00064"></a>00064 }
90
+ <a name="l00065"></a>00065 }
91
+ <a name="l00066"></a>00066 };
92
+ <a name="l00067"></a>00067
93
+ <a name="l00068"></a>00068 <span class="keyword">class </span>IniFileLexer {
94
+ <a name="l00069"></a>00069 <span class="keyword">public</span>:
95
+ <a name="l00070"></a>00070 <span class="keyword">class </span>Token {
96
+ <a name="l00071"></a>00071 <span class="keyword">public</span>:
97
+ <a name="l00072"></a>00072 <span class="keyword">enum</span> Kind {
98
+ <a name="l00073"></a>00073 UNKNOWN = 0,
99
+ <a name="l00074"></a>00074 NEWLINE,
100
+ <a name="l00075"></a>00075 SECTION_NAME,
101
+ <a name="l00076"></a>00076 IDENTIFIER,
102
+ <a name="l00077"></a>00077 ASSIGNMENT,
103
+ <a name="l00078"></a>00078 TEXT,
104
+ <a name="l00079"></a>00079 END_OF_FILE
105
+ <a name="l00080"></a>00080 };
106
+ <a name="l00081"></a>00081
107
+ <a name="l00082"></a>00082 <span class="keyword">const</span> Kind kind;
108
+ <a name="l00083"></a>00083 <span class="keyword">const</span> <span class="keywordtype">string</span> value;
109
+ <a name="l00084"></a>00084 <span class="keyword">const</span> <span class="keywordtype">int</span> line;
110
+ <a name="l00085"></a>00085 <span class="keyword">const</span> <span class="keywordtype">int</span> column;
111
+ <a name="l00086"></a>00086
112
+ <a name="l00087"></a>00087 <span class="comment">// String representations of the Kind enum.</span>
113
+ <a name="l00088"></a>00088 <span class="keyword">const</span> <span class="keyword">static</span> <span class="keywordtype">char</span> *identityByKind(Kind kind) {
114
+ <a name="l00089"></a>00089 <span class="keyword">const</span> <span class="keyword">static</span> <span class="keywordtype">char</span>* KIND_IDENTITY_TABLE[] = {
115
+ <a name="l00090"></a>00090 <span class="stringliteral">&quot;&lt;T_UNKNOWN&gt;&quot;</span>,
116
+ <a name="l00091"></a>00091 <span class="stringliteral">&quot;&lt;T_NEWLINE&gt;&quot;</span>,
117
+ <a name="l00092"></a>00092 <span class="stringliteral">&quot;&lt;T_SECTION_NAME&gt;&quot;</span>,
118
+ <a name="l00093"></a>00093 <span class="stringliteral">&quot;&lt;T_IDENTIFIER&gt;&quot;</span>,
119
+ <a name="l00094"></a>00094 <span class="stringliteral">&quot;&lt;T_ASSIGNMENT&gt;&quot;</span>,
120
+ <a name="l00095"></a>00095 <span class="stringliteral">&quot;&lt;T_TEXT&gt;&quot;</span>,
121
+ <a name="l00096"></a>00096 <span class="stringliteral">&quot;&lt;T_EOF&gt;&quot;</span>
122
+ <a name="l00097"></a>00097 };
123
+ <a name="l00098"></a>00098
124
+ <a name="l00099"></a>00099 <span class="keywordflow">return</span> KIND_IDENTITY_TABLE[kind];
125
+ <a name="l00100"></a>00100 }
126
+ <a name="l00101"></a>00101
127
+ <a name="l00102"></a>00102 Token(<span class="keyword">const</span> Kind kind, <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;value, <span class="keyword">const</span> <span class="keywordtype">int</span> line, <span class="keyword">const</span> <span class="keywordtype">int</span> column)
128
+ <a name="l00103"></a>00103 : kind(kind), value(value), line(line), column(column) {
129
+ <a name="l00104"></a>00104
130
+ <a name="l00105"></a>00105 }
131
+ <a name="l00106"></a>00106
132
+ <a name="l00107"></a>00107 <span class="keyword">class </span>ExpectanceException : <span class="keyword">public</span> std::exception {
133
+ <a name="l00108"></a>00108 <span class="keyword">private</span>:
134
+ <a name="l00109"></a>00109 <span class="keywordtype">char</span> message[255];
135
+ <a name="l00110"></a>00110
136
+ <a name="l00111"></a>00111 <span class="keyword">public</span>:
137
+ <a name="l00112"></a>00112 ExpectanceException(<span class="keywordtype">char</span> expected, <span class="keywordtype">char</span> got, <span class="keywordtype">int</span> line, <span class="keywordtype">int</span> column) {
138
+ <a name="l00113"></a>00113 <span class="keywordtype">int</span> messageSize = <span class="keyword">sizeof</span>(message);
139
+ <a name="l00114"></a>00114 memset(message, 0, messageSize);
140
+ <a name="l00115"></a>00115 snprintf(message, messageSize,
141
+ <a name="l00116"></a>00116 <span class="stringliteral">&quot;On line %i, column %i: Expected &#39;%c&#39;, got &#39;%c&#39; instead.&quot;</span>,
142
+ <a name="l00117"></a>00117 line, column, expected, got);
143
+ <a name="l00118"></a>00118 }
144
+ <a name="l00119"></a>00119
145
+ <a name="l00120"></a>00120 ExpectanceException(Token::Kind expected, Token got) {
146
+ <a name="l00121"></a>00121 <span class="keyword">const</span> <span class="keywordtype">char</span> *expectedKindString = Token::identityByKind(expected);
147
+ <a name="l00122"></a>00122 <span class="keywordtype">int</span> messageSize = <span class="keyword">sizeof</span>(message);
148
+ <a name="l00123"></a>00123 memset(message, 0, messageSize);
149
+ <a name="l00124"></a>00124 snprintf(message, messageSize,
150
+ <a name="l00125"></a>00125 <span class="stringliteral">&quot;On line %i, column %i: Expected &#39;%s&#39;, got &#39;%s&#39; instead.&quot;</span>,
151
+ <a name="l00126"></a>00126 got.line, got.column, expectedKindString, got.value.c_str());
152
+ <a name="l00127"></a>00127 }
153
+ <a name="l00128"></a>00128
154
+ <a name="l00129"></a>00129 ExpectanceException(<span class="keywordtype">char</span> expected, Token::Kind got, <span class="keywordtype">int</span> line, <span class="keywordtype">int</span> column) {
155
+ <a name="l00130"></a>00130 <span class="keyword">const</span> <span class="keywordtype">char</span> *gotKindString = Token::identityByKind(got);
156
+ <a name="l00131"></a>00131 <span class="keywordtype">int</span> messageSize = <span class="keyword">sizeof</span>(message);
157
+ <a name="l00132"></a>00132 memset(message, 0, messageSize);
158
+ <a name="l00133"></a>00133 snprintf(message, messageSize,
159
+ <a name="l00134"></a>00134 <span class="stringliteral">&quot;On line %i, column %i: Expected &#39;%c&#39;, got &#39;%s&#39; instead.&quot;</span>,
160
+ <a name="l00135"></a>00135 line, column, expected, gotKindString);
161
+ <a name="l00136"></a>00136 }
162
+ <a name="l00137"></a>00137
163
+ <a name="l00138"></a>00138 <span class="keyword">virtual</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* what() <span class="keyword">const</span> throw() {
164
+ <a name="l00139"></a>00139 <span class="keywordflow">return</span> message;
165
+ <a name="l00140"></a>00140 }
166
+ <a name="l00141"></a>00141 };
167
+ <a name="l00142"></a>00142 };
168
+ <a name="l00143"></a>00143
169
+ <a name="l00144"></a>00144 <span class="keyword">typedef</span> shared_ptr&lt;IniFileLexer::Token&gt; TokenPtr;
170
+ <a name="l00145"></a>00145
171
+ <a name="l00146"></a>00146
172
+ <a name="l00147"></a>00147
173
+ <a name="l00148"></a>00148 <span class="keyword">protected</span>:
174
+ <a name="l00149"></a>00149 ifstream iniFileStream;
175
+ <a name="l00150"></a>00150
176
+ <a name="l00151"></a>00151 <span class="keywordtype">char</span> lastAcceptedChar;
177
+ <a name="l00152"></a>00152 <span class="keywordtype">char</span> upcomingChar;
178
+ <a name="l00153"></a>00153 <span class="keywordtype">bool</span> upcomingTokenPtrIsStale;
179
+ <a name="l00154"></a>00154
180
+ <a name="l00155"></a>00155 <span class="keywordtype">int</span> currentLine;
181
+ <a name="l00156"></a>00156 <span class="keywordtype">int</span> currentColumn;
182
+ <a name="l00157"></a>00157
183
+ <a name="l00158"></a>00158 TokenPtr upcomingTokenPtr;
184
+ <a name="l00159"></a>00159
185
+ <a name="l00160"></a>00160 <span class="keywordtype">void</span> expect(<span class="keywordtype">char</span> ch) {
186
+ <a name="l00161"></a>00161 <span class="keywordtype">char</span> upcomingChar = (char)iniFileStream.peek();
187
+ <a name="l00162"></a>00162
188
+ <a name="l00163"></a>00163 <span class="keywordflow">if</span> (ch != upcomingChar) {
189
+ <a name="l00164"></a>00164 <span class="keywordflow">switch</span>(upcomingChar) {
190
+ <a name="l00165"></a>00165 <span class="keywordflow">case</span> EOF:
191
+ <a name="l00166"></a>00166 <span class="keywordflow">throw</span> Token::ExpectanceException(ch, Token::END_OF_FILE,
192
+ <a name="l00167"></a>00167 currentLine, currentColumn + 1);
193
+ <a name="l00168"></a>00168 <span class="keywordflow">case</span> <span class="charliteral">&#39;\n&#39;</span>:
194
+ <a name="l00169"></a>00169 <span class="keywordflow">throw</span> Token::ExpectanceException(ch, upcomingChar,
195
+ <a name="l00170"></a>00170 currentLine + 1, 0);
196
+ <a name="l00171"></a>00171 <span class="keywordflow">default</span>:
197
+ <a name="l00172"></a>00172 <span class="keywordflow">throw</span> Token::ExpectanceException(ch, upcomingChar,
198
+ <a name="l00173"></a>00173 currentLine, currentColumn + 1);
199
+ <a name="l00174"></a>00174 }
200
+ <a name="l00175"></a>00175 }
201
+ <a name="l00176"></a>00176 }
202
+ <a name="l00177"></a>00177
203
+ <a name="l00178"></a>00178 <span class="keywordtype">void</span> accept() {
204
+ <a name="l00179"></a>00179 <span class="keywordflow">if</span> (upcomingChar == EOF) <span class="keywordflow">return</span>;
205
+ <a name="l00180"></a>00180
206
+ <a name="l00181"></a>00181 lastAcceptedChar = (char)iniFileStream.get();
207
+ <a name="l00182"></a>00182 upcomingChar = (char)iniFileStream.peek();
208
+ <a name="l00183"></a>00183 currentColumn++;
209
+ <a name="l00184"></a>00184
210
+ <a name="l00185"></a>00185 <span class="keywordflow">if</span> (lastAcceptedChar == <span class="charliteral">&#39;\n&#39;</span>) {
211
+ <a name="l00186"></a>00186 currentLine++;
212
+ <a name="l00187"></a>00187 currentColumn = 1;
213
+ <a name="l00188"></a>00188 }
214
+ <a name="l00189"></a>00189 }
215
+ <a name="l00190"></a>00190
216
+ <a name="l00191"></a>00191 <span class="keywordtype">void</span> ignore() {
217
+ <a name="l00192"></a>00192 <span class="keywordflow">if</span> (upcomingChar == EOF) <span class="keywordflow">return</span>;
218
+ <a name="l00193"></a>00193
219
+ <a name="l00194"></a>00194 upcomingChar = (char)iniFileStream.peek();
220
+ <a name="l00195"></a>00195 currentColumn++;
221
+ <a name="l00196"></a>00196
222
+ <a name="l00197"></a>00197 <span class="keywordflow">if</span> ((<span class="keywordtype">char</span>)iniFileStream.get() == <span class="charliteral">&#39;\n&#39;</span>) {
223
+ <a name="l00198"></a>00198 currentLine++;
224
+ <a name="l00199"></a>00199 currentColumn = 1;
225
+ <a name="l00200"></a>00200 }
226
+ <a name="l00201"></a>00201 }
227
+ <a name="l00202"></a>00202
228
+ <a name="l00203"></a>00203 <span class="keywordtype">void</span> expectAndAccept(<span class="keywordtype">char</span> ch) {
229
+ <a name="l00204"></a>00204 expect(ch);
230
+ <a name="l00205"></a>00205 accept();
231
+ <a name="l00206"></a>00206 }
232
+ <a name="l00207"></a>00207
233
+ <a name="l00208"></a>00208 <span class="keywordtype">void</span> acceptWhileNewLine() {
234
+ <a name="l00209"></a>00209 <span class="keywordflow">while</span> (iniFileStream.good() &amp;&amp; upcomingChar == <span class="charliteral">&#39;\n&#39;</span>) {
235
+ <a name="l00210"></a>00210 accept();
236
+ <a name="l00211"></a>00211 }
237
+ <a name="l00212"></a>00212 }
238
+ <a name="l00213"></a>00213
239
+ <a name="l00214"></a>00214 <span class="keywordtype">void</span> ignoreWhileNotNewLine() {
240
+ <a name="l00215"></a>00215 <span class="keywordflow">while</span> (iniFileStream.good() &amp;&amp; upcomingChar != <span class="charliteral">&#39;\n&#39;</span>) {
241
+ <a name="l00216"></a>00216 ignore();
242
+ <a name="l00217"></a>00217 }
243
+ <a name="l00218"></a>00218 }
244
+ <a name="l00219"></a>00219
245
+ <a name="l00220"></a>00220 Token tokenizeIdentifier() {
246
+ <a name="l00221"></a>00221 <span class="keywordtype">int</span> line = currentLine;
247
+ <a name="l00222"></a>00222 <span class="keywordtype">int</span> column = currentColumn;
248
+ <a name="l00223"></a>00223 <span class="keywordtype">string</span> result;
249
+ <a name="l00224"></a>00224
250
+ <a name="l00225"></a>00225 <span class="keywordflow">while</span> (isalnum(upcomingChar) || upcomingChar == <span class="charliteral">&#39;_&#39;</span> || upcomingChar == <span class="charliteral">&#39;-&#39;</span>) {
251
+ <a name="l00226"></a>00226 result.append(1, upcomingChar);
252
+ <a name="l00227"></a>00227 accept();
253
+ <a name="l00228"></a>00228 }
254
+ <a name="l00229"></a>00229
255
+ <a name="l00230"></a>00230 <span class="keywordflow">return</span> Token(Token::IDENTIFIER, result, line, column);
256
+ <a name="l00231"></a>00231 }
257
+ <a name="l00232"></a>00232
258
+ <a name="l00233"></a>00233 Token tokenizeSection() {
259
+ <a name="l00234"></a>00234 expectAndAccept(<span class="charliteral">&#39;[&#39;</span>);
260
+ <a name="l00235"></a>00235 Token sectionName = tokenizeSectionName();
261
+ <a name="l00236"></a>00236 expectAndAccept(<span class="charliteral">&#39;]&#39;</span>);
262
+ <a name="l00237"></a>00237 <span class="keywordflow">return</span> sectionName;
263
+ <a name="l00238"></a>00238 }
264
+ <a name="l00239"></a>00239
265
+ <a name="l00240"></a>00240 Token tokenizeSectionName() {
266
+ <a name="l00241"></a>00241 <span class="keywordtype">int</span> line = currentLine;
267
+ <a name="l00242"></a>00242 <span class="keywordtype">int</span> column = currentColumn;
268
+ <a name="l00243"></a>00243 <span class="keywordtype">string</span> result;
269
+ <a name="l00244"></a>00244
270
+ <a name="l00245"></a>00245 <span class="comment">//while (upcomingChar != &#39;]&#39; &amp;&amp; upcomingChar != &#39;[&#39; &amp;&amp; upcomingChar != &#39;\n&#39; &amp;&amp; upcomingChar != EOF) {</span>
271
+ <a name="l00246"></a>00246 <span class="keywordflow">while</span> (isalnum(upcomingChar) || upcomingChar == <span class="charliteral">&#39;_&#39;</span> || upcomingChar == <span class="charliteral">&#39;-&#39;</span>) {
272
+ <a name="l00247"></a>00247 result.append(1, upcomingChar);
273
+ <a name="l00248"></a>00248 accept();
274
+ <a name="l00249"></a>00249 }
275
+ <a name="l00250"></a>00250
276
+ <a name="l00251"></a>00251 <span class="keywordflow">return</span> Token(Token::SECTION_NAME, result, line, column);
277
+ <a name="l00252"></a>00252 }
278
+ <a name="l00253"></a>00253
279
+ <a name="l00254"></a>00254 Token tokenizeAssignment() {
280
+ <a name="l00255"></a>00255 expectAndAccept(<span class="charliteral">&#39;=&#39;</span>);
281
+ <a name="l00256"></a>00256 <span class="keywordflow">return</span> Token(Token::ASSIGNMENT, <span class="stringliteral">&quot;=&quot;</span>, currentLine, currentColumn);
282
+ <a name="l00257"></a>00257 }
283
+ <a name="l00258"></a>00258
284
+ <a name="l00259"></a>00259 Token tokenizeText() {
285
+ <a name="l00260"></a>00260 <span class="keywordtype">int</span> line = currentLine;
286
+ <a name="l00261"></a>00261 <span class="keywordtype">int</span> column = currentColumn;
287
+ <a name="l00262"></a>00262 <span class="keywordtype">string</span> result;
288
+ <a name="l00263"></a>00263
289
+ <a name="l00264"></a>00264 <span class="keywordflow">while</span> (upcomingChar != <span class="charliteral">&#39;\n&#39;</span> &amp;&amp; upcomingChar != EOF) {
290
+ <a name="l00265"></a>00265 result.append(1, upcomingChar);
291
+ <a name="l00266"></a>00266 accept();
292
+ <a name="l00267"></a>00267 }
293
+ <a name="l00268"></a>00268
294
+ <a name="l00269"></a>00269 <span class="keywordflow">return</span> Token(Token::TEXT, result, line, column);
295
+ <a name="l00270"></a>00270 }
296
+ <a name="l00271"></a>00271
297
+ <a name="l00272"></a>00272 Token tokenizeKey() {
298
+ <a name="l00273"></a>00273 <span class="keywordflow">return</span> tokenizeIdentifier();
299
+ <a name="l00274"></a>00274 }
300
+ <a name="l00275"></a>00275
301
+ <a name="l00276"></a>00276 Token tokenizeValue() {
302
+ <a name="l00277"></a>00277 <span class="keywordflow">return</span> tokenizeText();
303
+ <a name="l00278"></a>00278 }
304
+ <a name="l00279"></a>00279
305
+ <a name="l00280"></a>00280 Token tokenizeUnknown() {
306
+ <a name="l00281"></a>00281 <span class="keywordtype">int</span> line = currentLine;
307
+ <a name="l00282"></a>00282 <span class="keywordtype">int</span> column = currentColumn;
308
+ <a name="l00283"></a>00283 <span class="keywordtype">string</span> result;
309
+ <a name="l00284"></a>00284
310
+ <a name="l00285"></a>00285 <span class="keywordflow">while</span> (upcomingChar != EOF) {
311
+ <a name="l00286"></a>00286 result.append(1, upcomingChar);
312
+ <a name="l00287"></a>00287 accept();
313
+ <a name="l00288"></a>00288 }
314
+ <a name="l00289"></a>00289
315
+ <a name="l00290"></a>00290 <span class="keywordflow">return</span> Token(Token::UNKNOWN, result, line, column);
316
+ <a name="l00291"></a>00291 }
317
+ <a name="l00292"></a>00292
318
+ <a name="l00293"></a>00293 <span class="keyword">public</span>:
319
+ <a name="l00294"></a>00294 IniFileLexer(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;fileName) {
320
+ <a name="l00295"></a>00295 currentLine = 1;
321
+ <a name="l00296"></a>00296 currentColumn = 1;
322
+ <a name="l00297"></a>00297 upcomingTokenPtrIsStale = <span class="keyword">true</span>;
323
+ <a name="l00298"></a>00298 iniFileStream.open(fileName.c_str());
324
+ <a name="l00299"></a>00299 <span class="keywordflow">if</span> (iniFileStream.fail()) {
325
+ <a name="l00300"></a>00300 <span class="keywordtype">int</span> e = errno;
326
+ <a name="l00301"></a>00301 <span class="keywordflow">throw</span> FileSystemException(<span class="stringliteral">&quot;Cannot open file &#39;&quot;</span> + fileName + <span class="stringliteral">&quot;&#39; for reading&quot;</span>,
327
+ <a name="l00302"></a>00302 e, fileName);
328
+ <a name="l00303"></a>00303 }
329
+ <a name="l00304"></a>00304 }
330
+ <a name="l00305"></a>00305
331
+ <a name="l00306"></a>00306 ~IniFileLexer() {
332
+ <a name="l00307"></a>00307 iniFileStream.close();
333
+ <a name="l00308"></a>00308 }
334
+ <a name="l00309"></a>00309
335
+ <a name="l00310"></a>00310 <span class="keywordtype">int</span> getCurrentLine() {
336
+ <a name="l00311"></a>00311 <span class="keywordflow">return</span> currentLine;
337
+ <a name="l00312"></a>00312 }
338
+ <a name="l00313"></a>00313
339
+ <a name="l00314"></a>00314 <span class="keywordtype">int</span> getCurrentColumn() {
340
+ <a name="l00315"></a>00315 <span class="keywordflow">return</span> currentColumn;
341
+ <a name="l00316"></a>00316 }
342
+ <a name="l00317"></a>00317
343
+ <a name="l00318"></a>00318 TokenPtr peekToken() {
344
+ <a name="l00319"></a>00319 <span class="keywordflow">if</span> (upcomingTokenPtrIsStale) {
345
+ <a name="l00320"></a>00320 Token upcomingToken = getToken();
346
+ <a name="l00321"></a>00321 upcomingTokenPtr = make_shared&lt;Token&gt;(upcomingToken);
347
+ <a name="l00322"></a>00322 upcomingTokenPtrIsStale = <span class="keyword">false</span>;
348
+ <a name="l00323"></a>00323 }
349
+ <a name="l00324"></a>00324
350
+ <a name="l00325"></a>00325 <span class="keywordflow">return</span> upcomingTokenPtr;
351
+ <a name="l00326"></a>00326 }
352
+ <a name="l00327"></a>00327
353
+ <a name="l00328"></a>00328 Token getToken() {
354
+ <a name="l00329"></a>00329 <span class="keywordflow">if</span> (!upcomingTokenPtrIsStale) {
355
+ <a name="l00330"></a>00330 upcomingTokenPtrIsStale = <span class="keyword">true</span>;
356
+ <a name="l00331"></a>00331 <span class="keywordflow">return</span> *upcomingTokenPtr;
357
+ <a name="l00332"></a>00332 }
358
+ <a name="l00333"></a>00333
359
+ <a name="l00334"></a>00334 <span class="keywordflow">while</span> (iniFileStream.good()) {
360
+ <a name="l00335"></a>00335 upcomingChar = (char)iniFileStream.peek();
361
+ <a name="l00336"></a>00336 <span class="keywordflow">switch</span>(upcomingChar) {
362
+ <a name="l00337"></a>00337 <span class="keywordflow">case</span> <span class="charliteral">&#39;[&#39;</span>:
363
+ <a name="l00338"></a>00338 <span class="keywordflow">return</span> tokenizeSection();
364
+ <a name="l00339"></a>00339 <span class="keywordflow">case</span> <span class="charliteral">&#39;\n&#39;</span>:
365
+ <a name="l00340"></a>00340 <span class="keywordflow">if</span> (lastAcceptedChar != <span class="charliteral">&#39;\n&#39;</span>) {
366
+ <a name="l00341"></a>00341 accept();
367
+ <a name="l00342"></a>00342 <span class="keywordflow">return</span> Token(Token::NEWLINE, <span class="stringliteral">&quot;\n&quot;</span>, currentLine, currentColumn);
368
+ <a name="l00343"></a>00343 } <span class="keywordflow">else</span> {
369
+ <a name="l00344"></a>00344 ignore();
370
+ <a name="l00345"></a>00345 <span class="keywordflow">break</span>;
371
+ <a name="l00346"></a>00346 }
372
+ <a name="l00347"></a>00347 <span class="keywordflow">case</span> <span class="charliteral">&#39;;&#39;</span>:
373
+ <a name="l00348"></a>00348 <span class="comment">// Comment encountered: accept all characters until newline (exclusive).</span>
374
+ <a name="l00349"></a>00349 ignoreWhileNotNewLine();
375
+ <a name="l00350"></a>00350 <span class="keywordflow">break</span>;
376
+ <a name="l00351"></a>00351 <span class="keywordflow">case</span> <span class="charliteral">&#39;=&#39;</span>:
377
+ <a name="l00352"></a>00352 <span class="keywordflow">return</span> tokenizeAssignment();
378
+ <a name="l00353"></a>00353 <span class="keywordflow">case</span> EOF:
379
+ <a name="l00354"></a>00354 <span class="keywordflow">return</span> Token(Token::END_OF_FILE, <span class="stringliteral">&quot;&lt;END_OF_FILE&gt;&quot;</span>, currentLine, currentColumn);
380
+ <a name="l00355"></a>00355 <span class="keywordflow">default</span>:
381
+ <a name="l00356"></a>00356 <span class="keywordflow">if</span> (isblank(upcomingChar)) {
382
+ <a name="l00357"></a>00357 ignore();
383
+ <a name="l00358"></a>00358 } <span class="keywordflow">else</span> {
384
+ <a name="l00359"></a>00359 <span class="keywordflow">switch</span>(lastAcceptedChar) {
385
+ <a name="l00360"></a>00360 <span class="keywordflow">case</span> <span class="charliteral">&#39;\n&#39;</span>:
386
+ <a name="l00361"></a>00361 <span class="keywordflow">return</span> tokenizeKey();
387
+ <a name="l00362"></a>00362 <span class="keywordflow">case</span> <span class="charliteral">&#39;=&#39;</span>:
388
+ <a name="l00363"></a>00363 <span class="keywordflow">return</span> tokenizeValue();
389
+ <a name="l00364"></a>00364 <span class="keywordflow">default</span>:
390
+ <a name="l00365"></a>00365 <span class="keywordflow">return</span> tokenizeUnknown();
391
+ <a name="l00366"></a>00366 }
392
+ <a name="l00367"></a>00367 }
393
+ <a name="l00368"></a>00368 }
394
+ <a name="l00369"></a>00369 }
395
+ <a name="l00370"></a>00370
396
+ <a name="l00371"></a>00371 <span class="keywordflow">return</span> Token(Token::END_OF_FILE, <span class="stringliteral">&quot;&lt;END_OF_FILE&gt;&quot;</span>, currentLine, currentColumn);
397
+ <a name="l00372"></a>00372 }
398
+ <a name="l00373"></a>00373 };
399
+ <a name="l00374"></a>00374
400
+ <a name="l00375"></a>00375 <span class="keyword">typedef</span> shared_ptr&lt;IniFileSection&gt; IniFileSectionPtr;
401
+ <a name="l00376"></a>00376
402
+ <a name="l00377"></a>00377
403
+ <a name="l00378"></a>00378 <span class="keyword">class </span>IniFile {
404
+ <a name="l00379"></a>00379 <span class="keyword">protected</span>:
405
+ <a name="l00380"></a>00380 <span class="keyword">typedef</span> map&lt;string, IniFileSectionPtr&gt; SectionMap;
406
+ <a name="l00381"></a>00381 <span class="keywordtype">string</span> name;
407
+ <a name="l00382"></a>00382 SectionMap sections;
408
+ <a name="l00383"></a>00383
409
+ <a name="l00384"></a>00384 <span class="keyword">class </span>IniFileParser {
410
+ <a name="l00385"></a>00385 <span class="keyword">typedef</span> IniFileLexer::Token Token;
411
+ <a name="l00386"></a>00386
412
+ <a name="l00387"></a>00387 <span class="keyword">protected</span>:
413
+ <a name="l00388"></a>00388 IniFileLexer lexer;
414
+ <a name="l00389"></a>00389 IniFile *iniFile;
415
+ <a name="l00390"></a>00390
416
+ <a name="l00391"></a>00391 <span class="comment">// The Start Symbol.</span>
417
+ <a name="l00392"></a>00392 <span class="keywordtype">void</span> parseSections() {
418
+ <a name="l00393"></a>00393 <span class="keywordflow">while</span> ((lexer.peekToken())-&gt;kind == Token::SECTION_NAME) {
419
+ <a name="l00394"></a>00394 parseSection();
420
+ <a name="l00395"></a>00395 }
421
+ <a name="l00396"></a>00396 }
422
+ <a name="l00397"></a>00397
423
+ <a name="l00398"></a>00398 <span class="keywordtype">void</span> parseSection() {
424
+ <a name="l00399"></a>00399 Token token = acceptAndReturnif(Token::SECTION_NAME);
425
+ <a name="l00400"></a>00400 acceptIfEOL();
426
+ <a name="l00401"></a>00401
427
+ <a name="l00402"></a>00402 <span class="keywordtype">string</span> sectionName = token.value;
428
+ <a name="l00403"></a>00403 IniFileSection *section = <span class="keyword">new</span> IniFileSection(sectionName);
429
+ <a name="l00404"></a>00404 iniFile-&gt;addSection(section);
430
+ <a name="l00405"></a>00405
431
+ <a name="l00406"></a>00406 parseSectionBody(section);
432
+ <a name="l00407"></a>00407 }
433
+ <a name="l00408"></a>00408
434
+ <a name="l00409"></a>00409 <span class="keywordtype">void</span> parseSectionBody(IniFileSection *currentSection) {
435
+ <a name="l00410"></a>00410 <span class="keywordflow">while</span> ((lexer.peekToken())-&gt;kind == Token::IDENTIFIER) {
436
+ <a name="l00411"></a>00411 parseKeyValue(currentSection);
437
+ <a name="l00412"></a>00412 }
438
+ <a name="l00413"></a>00413 }
439
+ <a name="l00414"></a>00414
440
+ <a name="l00415"></a>00415 <span class="keywordtype">void</span> parseKeyValue(IniFileSection *currentSection) {
441
+ <a name="l00416"></a>00416 Token identifierToken = acceptAndReturnif (Token::IDENTIFIER);
442
+ <a name="l00417"></a>00417 acceptif (Token::ASSIGNMENT);
443
+ <a name="l00418"></a>00418 Token valueToken = acceptAndReturnif (Token::TEXT);
444
+ <a name="l00419"></a>00419 acceptIfEOL();
445
+ <a name="l00420"></a>00420 currentSection-&gt;set(identifierToken.value, valueToken.value);
446
+ <a name="l00421"></a>00421 }
447
+ <a name="l00422"></a>00422
448
+ <a name="l00423"></a>00423 <span class="keywordtype">void</span> acceptif (Token::Kind expectedKind) {
449
+ <a name="l00424"></a>00424 Token token = lexer.getToken();
450
+ <a name="l00425"></a>00425
451
+ <a name="l00426"></a>00426 <span class="keywordflow">if</span> (token.kind != expectedKind) {
452
+ <a name="l00427"></a>00427 <span class="keywordflow">throw</span> Token::ExpectanceException(expectedKind, token);
453
+ <a name="l00428"></a>00428 }
454
+ <a name="l00429"></a>00429 }
455
+ <a name="l00430"></a>00430
456
+ <a name="l00431"></a>00431 <span class="keywordtype">void</span> acceptIfEOL() {
457
+ <a name="l00432"></a>00432 Token token = lexer.getToken();
458
+ <a name="l00433"></a>00433
459
+ <a name="l00434"></a>00434 <span class="keywordflow">if</span> (token.kind != Token::NEWLINE &amp;&amp; token.kind != Token::END_OF_FILE) {
460
+ <a name="l00435"></a>00435 <span class="keywordflow">throw</span> Token::ExpectanceException(Token::NEWLINE, token);
461
+ <a name="l00436"></a>00436 }
462
+ <a name="l00437"></a>00437 }
463
+ <a name="l00438"></a>00438
464
+ <a name="l00439"></a>00439 Token acceptAndReturnif (Token::Kind expectedKind) {
465
+ <a name="l00440"></a>00440 Token token = lexer.getToken();
466
+ <a name="l00441"></a>00441
467
+ <a name="l00442"></a>00442 <span class="keywordflow">if</span> (token.kind != expectedKind) {
468
+ <a name="l00443"></a>00443 <span class="keywordflow">throw</span> Token::ExpectanceException(expectedKind, token);
469
+ <a name="l00444"></a>00444 }
470
+ <a name="l00445"></a>00445
471
+ <a name="l00446"></a>00446 <span class="keywordflow">return</span> token;
472
+ <a name="l00447"></a>00447 }
473
+ <a name="l00448"></a>00448
474
+ <a name="l00449"></a>00449 <span class="keyword">public</span>:
475
+ <a name="l00450"></a>00450 IniFileParser(IniFile *iniFile) : lexer(iniFile-&gt;getName()), iniFile(iniFile) {
476
+ <a name="l00451"></a>00451 parseSections();
477
+ <a name="l00452"></a>00452 }
478
+ <a name="l00453"></a>00453 };
479
+ <a name="l00454"></a>00454
480
+ <a name="l00455"></a>00455 <span class="keyword">public</span>:
481
+ <a name="l00456"></a>00456 IniFile(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;iniFileName)
482
+ <a name="l00457"></a>00457 : name(iniFileName)
483
+ <a name="l00458"></a>00458 {
484
+ <a name="l00459"></a>00459 IniFileParser parser(<span class="keyword">this</span>);
485
+ <a name="l00460"></a>00460 }
486
+ <a name="l00461"></a>00461
487
+ <a name="l00462"></a>00462 <span class="keywordtype">void</span> addSection(IniFileSection *section) {
488
+ <a name="l00463"></a>00463 sections.insert(make_pair(section-&gt;getSectionName(), IniFileSectionPtr(section)));
489
+ <a name="l00464"></a>00464 }
490
+ <a name="l00465"></a>00465
491
+ <a name="l00466"></a>00466 IniFileSectionPtr section(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;sectionName) {
492
+ <a name="l00467"></a>00467 SectionMap::iterator it = sections.find(sectionName);
493
+ <a name="l00468"></a>00468 <span class="keywordflow">if</span> (it != sections.end()) {
494
+ <a name="l00469"></a>00469 <span class="keywordflow">return</span> it-&gt;second;
495
+ <a name="l00470"></a>00470 } <span class="keywordflow">else</span> {
496
+ <a name="l00471"></a>00471 <span class="keywordflow">return</span> IniFileSectionPtr();
497
+ <a name="l00472"></a>00472 }
498
+ <a name="l00473"></a>00473 }
499
+ <a name="l00474"></a>00474
500
+ <a name="l00475"></a>00475 <span class="keywordtype">bool</span> hasSection(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;sectionName)<span class="keyword"> const </span>{
501
+ <a name="l00476"></a>00476 <span class="keywordflow">return</span> sections.find(sectionName) != sections.end();
502
+ <a name="l00477"></a>00477 }
503
+ <a name="l00478"></a>00478
504
+ <a name="l00479"></a>00479 <span class="keywordtype">string</span> getName()<span class="keyword"> const </span>{
505
+ <a name="l00480"></a>00480 <span class="keywordflow">return</span> name;
506
+ <a name="l00481"></a>00481 }
507
+ <a name="l00482"></a>00482
508
+ <a name="l00483"></a>00483 <span class="keywordtype">void</span> inspect()<span class="keyword"> const </span>{
509
+ <a name="l00484"></a>00484 SectionMap::const_iterator it = sections.begin();
510
+ <a name="l00485"></a>00485 <span class="keywordflow">while</span> (it != sections.end()) {
511
+ <a name="l00486"></a>00486 cout &lt;&lt; <span class="stringliteral">&quot;[&quot;</span> &lt;&lt; (it-&gt;first) &lt;&lt; <span class="stringliteral">&quot;]&quot;</span> &lt;&lt; endl;
512
+ <a name="l00487"></a>00487 it-&gt;second-&gt;inspect();
513
+ <a name="l00488"></a>00488
514
+ <a name="l00489"></a>00489 it++;
515
+ <a name="l00490"></a>00490 }
516
+ <a name="l00491"></a>00491 }
517
+ <a name="l00492"></a>00492 };
518
+ <a name="l00493"></a>00493
519
+ <a name="l00494"></a>00494 } <span class="comment">// namespace Passenger</span>
520
+ <a name="l00495"></a>00495
521
+ <a name="l00496"></a>00496 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_INI_FILE_H_ */</span>
522
+ </pre></div></div>
523
+ <hr size="1"/><address style="text-align: right;"><small>Generated by&nbsp;
524
+ <a href="http://www.doxygen.org/index.html">
525
+ <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.6.2 </small></address>
526
+ </body>
527
+ </html>