xref: /trunk/main/basic/source/comp/io.cxx (revision ffd38472365e95f6a578737bc9a5eb0fac624a86)
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 
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 
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 
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()
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 
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 
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 
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 
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 
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