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