1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_basic.hxx"
24
25 #include <tools/stream.hxx>
26 #include "sbcomp.hxx"
27 #include "iosys.hxx"
28
29 // Test, ob ein I/O-Channel angegeben wurde
30
Channel(sal_Bool bAlways)31 sal_Bool SbiParser::Channel( sal_Bool bAlways )
32 {
33 sal_Bool bRes = sal_False;
34 Peek();
35 if( IsHash() )
36 {
37 SbiExpression aExpr( this );
38 while( Peek() == COMMA || Peek() == SEMICOLON )
39 Next();
40 aExpr.Gen();
41 aGen.Gen( _CHANNEL );
42 bRes = sal_True;
43 }
44 else if( bAlways )
45 Error( SbERR_EXPECTED, "#" );
46 return bRes;
47 }
48
49 // Für PRINT und WRITE wird bei Objektvariablen versucht,
50 // die Default-Property anzusprechen.
51
52 // PRINT
53
Print()54 void SbiParser::Print()
55 {
56 sal_Bool bChan = Channel();
57 // Die Ausdrücke zum drucken:
58 while( !bAbort )
59 {
60 if( !IsEoln( Peek() ) )
61 {
62 SbiExpression* pExpr = new SbiExpression( this );
63 pExpr->Gen();
64 delete pExpr;
65 Peek();
66 aGen.Gen( eCurTok == COMMA ? _PRINTF : _BPRINT );
67 }
68 if( eCurTok == COMMA || eCurTok == SEMICOLON )
69 {
70 Next();
71 if( IsEoln( Peek() ) ) break;
72 }
73 else
74 {
75 aGen.Gen( _PRCHAR, '\n' );
76 break;
77 }
78 }
79 if( bChan )
80 aGen.Gen( _CHAN0 );
81 }
82
83 // WRITE #chan, expr, ...
84
Write()85 void SbiParser::Write()
86 {
87 sal_Bool bChan = Channel();
88 // Die Ausdrücke zum drucken:
89 while( !bAbort )
90 {
91 SbiExpression* pExpr = new SbiExpression( this );
92 pExpr->Gen();
93 delete pExpr;
94 aGen.Gen( _BWRITE );
95 if( Peek() == COMMA )
96 {
97 aGen.Gen( _PRCHAR, ',' );
98 Next();
99 if( IsEoln( Peek() ) ) break;
100 }
101 else
102 {
103 aGen.Gen( _PRCHAR, '\n' );
104 break;
105 }
106 }
107 if( bChan )
108 aGen.Gen( _CHAN0 );
109 }
110
111
112 // #i92642 Handle LINE keyword outside ::Next()
Line()113 void SbiParser::Line()
114 {
115 // #i92642: Special handling to allow name as symbol
116 if( Peek() == INPUT )
117 {
118 Next();
119 LineInput();
120 }
121 else
122 {
123 aGen.Statement();
124
125 KeywordSymbolInfo aInfo;
126 aInfo.m_aKeywordSymbol = String( RTL_CONSTASCII_USTRINGPARAM( "line" ) );
127 aInfo.m_eSbxDataType = GetType();
128 aInfo.m_eTok = SYMBOL;
129
130 Symbol( &aInfo );
131 }
132 }
133
134
135 // LINE INPUT [prompt], var$
136
LineInput()137 void SbiParser::LineInput()
138 {
139 Channel( sal_True );
140 // sal_Bool bChan = Channel( sal_True );
141 SbiExpression* pExpr = new SbiExpression( this, SbOPERAND );
142 /* AB 15.1.96: Keinen allgemeinen Ausdruck mehr zulassen
143 SbiExpression* pExpr = new SbiExpression( this );
144 if( !pExpr->IsVariable() )
145 {
146 SbiToken eTok = Peek();
147 if( eTok == COMMA || eTok == SEMICOLON ) Next();
148 else Error( SbERR_EXPECTED, COMMA );
149 // mit Prompt
150 if( !bChan )
151 {
152 pExpr->Gen();
153 aGen.Gen( _PROMPT );
154 }
155 else
156 Error( SbERR_VAR_EXPECTED );
157 delete pExpr;
158 pExpr = new SbiExpression( this, SbOPERAND );
159 }
160 */
161 if( !pExpr->IsVariable() )
162 Error( SbERR_VAR_EXPECTED );
163 if( pExpr->GetType() != SbxVARIANT && pExpr->GetType() != SbxSTRING )
164 Error( SbERR_CONVERSION );
165 pExpr->Gen();
166 aGen.Gen( _LINPUT );
167 delete pExpr;
168 aGen.Gen( _CHAN0 ); // ResetChannel() nicht mehr in StepLINPUT()
169 }
170
171 // INPUT
172
Input()173 void SbiParser::Input()
174 {
175 aGen.Gen( _RESTART );
176 Channel( sal_True );
177 // sal_Bool bChan = Channel( sal_True );
178 SbiExpression* pExpr = new SbiExpression( this, SbOPERAND );
179 /* ALT: Jetzt keinen allgemeinen Ausdruck mehr zulassen
180 SbiExpression* pExpr = new SbiExpression( this );
181 ...
182 siehe LineInput
183 */
184 while( !bAbort )
185 {
186 if( !pExpr->IsVariable() )
187 Error( SbERR_VAR_EXPECTED );
188 pExpr->Gen();
189 aGen.Gen( _INPUT );
190 if( Peek() == COMMA )
191 {
192 Next();
193 delete pExpr;
194 pExpr = new SbiExpression( this, SbOPERAND );
195 }
196 else break;
197 }
198 delete pExpr;
199 aGen.Gen( _CHAN0 ); // ResetChannel() nicht mehr in StepINPUT()
200 }
201
202 // OPEN stringexpr FOR mode ACCESS access mode AS Channel [Len=n]
203
Open()204 void SbiParser::Open()
205 {
206 SbiExpression aFileName( this );
207 SbiToken eTok;
208 TestToken( FOR );
209 short nMode = 0;
210 short nFlags = 0;
211 switch( Next() )
212 {
213 case INPUT:
214 nMode = STREAM_READ; nFlags |= SBSTRM_INPUT; break;
215 case OUTPUT:
216 nMode = STREAM_WRITE | STREAM_TRUNC; nFlags |= SBSTRM_OUTPUT; break;
217 case APPEND:
218 nMode = STREAM_WRITE; nFlags |= SBSTRM_APPEND; break;
219 case RANDOM:
220 nMode = STREAM_READ | STREAM_WRITE; nFlags |= SBSTRM_RANDOM; break;
221 case BINARY:
222 nMode = STREAM_READ | STREAM_WRITE; nFlags |= SBSTRM_BINARY; break;
223 default:
224 Error( SbERR_SYNTAX );
225 }
226 if( Peek() == ACCESS )
227 {
228 Next();
229 eTok = Next();
230 // #27964# Nur STREAM_READ,STREAM_WRITE-Flags in nMode beeinflussen
231 nMode &= ~(STREAM_READ | STREAM_WRITE); // löschen
232 if( eTok == READ )
233 {
234 if( Peek() == WRITE )
235 {
236 Next();
237 nMode |= (STREAM_READ | STREAM_WRITE);
238 }
239 else
240 nMode |= STREAM_READ;
241 }
242 else if( eTok == WRITE )
243 nMode |= STREAM_WRITE;
244 else
245 Error( SbERR_SYNTAX );
246 }
247 switch( Peek() )
248 {
249 #ifdef SHARED
250 #undef SHARED
251 #define tmpSHARED
252 #endif
253 case SHARED:
254 Next(); nMode |= STREAM_SHARE_DENYNONE; break;
255 #ifdef tmpSHARED
256 #define SHARED
257 #undef tmpSHARED
258 #endif
259 case LOCK:
260 Next();
261 eTok = Next();
262 if( eTok == READ )
263 {
264 if( Peek() == WRITE ) Next(), nMode |= STREAM_SHARE_DENYALL;
265 else nMode |= STREAM_SHARE_DENYREAD;
266 }
267 else if( eTok == WRITE )
268 nMode |= STREAM_SHARE_DENYWRITE;
269 else
270 Error( SbERR_SYNTAX );
271 break;
272 default: break;
273 }
274 TestToken( AS );
275 // Die Kanalnummer
276 SbiExpression* pChan = new SbiExpression( this );
277 if( !pChan )
278 Error( SbERR_SYNTAX );
279 SbiExpression* pLen = NULL;
280 if( Peek() == SYMBOL )
281 {
282 Next();
283 String aLen( aSym );
284 if( aLen.EqualsIgnoreCaseAscii( "LEN" ) )
285 {
286 TestToken( EQ );
287 pLen = new SbiExpression( this );
288 }
289 }
290 if( !pLen ) pLen = new SbiExpression( this, 128, SbxINTEGER );
291 // Der Stack für den OPEN-Befehl sieht wie folgt aus:
292 // Blocklänge
293 // Kanalnummer
294 // Dateiname
295 pLen->Gen();
296 if( pChan )
297 pChan->Gen();
298 aFileName.Gen();
299 aGen.Gen( _OPEN, nMode, nFlags );
300 delete pLen;
301 delete pChan;
302 }
303
304 // NAME file AS file
305
Name()306 void SbiParser::Name()
307 {
308 // #i92642: Special handling to allow name as symbol
309 if( Peek() == EQ )
310 {
311 aGen.Statement();
312
313 KeywordSymbolInfo aInfo;
314 aInfo.m_aKeywordSymbol = String( RTL_CONSTASCII_USTRINGPARAM( "name" ) );
315 aInfo.m_eSbxDataType = GetType();
316 aInfo.m_eTok = SYMBOL;
317
318 Symbol( &aInfo );
319 return;
320 }
321 SbiExpression aExpr1( this );
322 TestToken( AS );
323 SbiExpression aExpr2( this );
324 aExpr1.Gen();
325 aExpr2.Gen();
326 aGen.Gen( _RENAME );
327 }
328
329 // CLOSE [n,...]
330
Close()331 void SbiParser::Close()
332 {
333 Peek();
334 if( IsEoln( eCurTok ) )
335 aGen.Gen( _CLOSE, 0 );
336 else
337 for( ;; )
338 {
339 SbiExpression aExpr( this );
340 while( Peek() == COMMA || Peek() == SEMICOLON )
341 Next();
342 aExpr.Gen();
343 aGen.Gen( _CHANNEL );
344 aGen.Gen( _CLOSE, 1 );
345
346 if( IsEoln( Peek() ) )
347 break;
348 }
349 }
350
351 /* vim: set noet sw=4 ts=4: */
352