xref: /AOO41X/main/basic/source/comp/scanner.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_basic.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "sbcomp.hxx"
32*cdf0e10cSrcweir #include <stdio.h>
33*cdf0e10cSrcweir #include <string.h>
34*cdf0e10cSrcweir #include <ctype.h>
35*cdf0e10cSrcweir #if defined UNX
36*cdf0e10cSrcweir #include <stdlib.h>
37*cdf0e10cSrcweir #else
38*cdf0e10cSrcweir #include <math.h>   // atof()
39*cdf0e10cSrcweir #endif
40*cdf0e10cSrcweir #include <rtl/math.hxx>
41*cdf0e10cSrcweir #include <vcl/svapp.hxx>
42*cdf0e10cSrcweir #include <unotools/charclass.hxx>
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir #include <runtime.hxx>
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir SbiScanner::SbiScanner( const ::rtl::OUString& rBuf, StarBASIC* p ) : aBuf( rBuf )
47*cdf0e10cSrcweir {
48*cdf0e10cSrcweir 	pBasic   = p;
49*cdf0e10cSrcweir 	pLine    = NULL;
50*cdf0e10cSrcweir 	nVal	 = 0;
51*cdf0e10cSrcweir 	eScanType = SbxVARIANT;
52*cdf0e10cSrcweir 	nErrors  = 0;
53*cdf0e10cSrcweir 	nBufPos  = 0;
54*cdf0e10cSrcweir 	nCurCol1 = 0;
55*cdf0e10cSrcweir 	nSavedCol1 = 0;
56*cdf0e10cSrcweir 	nColLock = 0;
57*cdf0e10cSrcweir 	nLine	 = 0;
58*cdf0e10cSrcweir 	nCol1	 = 0;
59*cdf0e10cSrcweir 	nCol2	 = 0;
60*cdf0e10cSrcweir 	nCol     = 0;
61*cdf0e10cSrcweir 	bError	 =
62*cdf0e10cSrcweir 	bAbort   =
63*cdf0e10cSrcweir 	bSpaces  =
64*cdf0e10cSrcweir 	bNumber  =
65*cdf0e10cSrcweir 	bSymbol  =
66*cdf0e10cSrcweir 	bUsedForHilite =
67*cdf0e10cSrcweir 	bCompatible =
68*cdf0e10cSrcweir 	bVBASupportOn =
69*cdf0e10cSrcweir 	bPrevLineExtentsComment = sal_False;
70*cdf0e10cSrcweir 	bHash    =
71*cdf0e10cSrcweir 	bErrors  = sal_True;
72*cdf0e10cSrcweir }
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir SbiScanner::~SbiScanner()
75*cdf0e10cSrcweir {}
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir void SbiScanner::LockColumn()
78*cdf0e10cSrcweir {
79*cdf0e10cSrcweir 	if( !nColLock++ )
80*cdf0e10cSrcweir 		nSavedCol1 = nCol1;
81*cdf0e10cSrcweir }
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir void SbiScanner::UnlockColumn()
84*cdf0e10cSrcweir {
85*cdf0e10cSrcweir 	if( nColLock )
86*cdf0e10cSrcweir 		nColLock--;
87*cdf0e10cSrcweir }
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir void SbiScanner::GenError( SbError code )
90*cdf0e10cSrcweir {
91*cdf0e10cSrcweir     if( GetSbData()->bBlockCompilerError )
92*cdf0e10cSrcweir     {
93*cdf0e10cSrcweir         bAbort = sal_True;
94*cdf0e10cSrcweir         return;
95*cdf0e10cSrcweir     }
96*cdf0e10cSrcweir 	if( !bError && bErrors )
97*cdf0e10cSrcweir 	{
98*cdf0e10cSrcweir 		sal_Bool bRes = sal_True;
99*cdf0e10cSrcweir 		// Nur einen Fehler pro Statement reporten
100*cdf0e10cSrcweir 		bError = sal_True;
101*cdf0e10cSrcweir 		if( pBasic )
102*cdf0e10cSrcweir 		{
103*cdf0e10cSrcweir 			// Falls EXPECTED oder UNEXPECTED kommen sollte, bezieht es sich
104*cdf0e10cSrcweir 			// immer auf das letzte Token, also die Col1 uebernehmen
105*cdf0e10cSrcweir 			sal_uInt16 nc = nColLock ? nSavedCol1 : nCol1;
106*cdf0e10cSrcweir 			switch( code )
107*cdf0e10cSrcweir 			{
108*cdf0e10cSrcweir 				case SbERR_EXPECTED:
109*cdf0e10cSrcweir 				case SbERR_UNEXPECTED:
110*cdf0e10cSrcweir 				case SbERR_SYMBOL_EXPECTED:
111*cdf0e10cSrcweir 				case SbERR_LABEL_EXPECTED:
112*cdf0e10cSrcweir 					nc = nCol1;
113*cdf0e10cSrcweir 					if( nc > nCol2 ) nCol2 = nc;
114*cdf0e10cSrcweir 					break;
115*cdf0e10cSrcweir 			}
116*cdf0e10cSrcweir 			bRes = pBasic->CError( code, aError, nLine, nc, nCol2 );
117*cdf0e10cSrcweir 		}
118*cdf0e10cSrcweir 		bAbort |= !bRes |
119*cdf0e10cSrcweir 			 ( code == SbERR_NO_MEMORY || code == SbERR_PROG_TOO_LARGE );
120*cdf0e10cSrcweir 	}
121*cdf0e10cSrcweir 	if( bErrors )
122*cdf0e10cSrcweir 		nErrors++;
123*cdf0e10cSrcweir }
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir // Falls sofort ein Doppelpunkt folgt, wird sal_True zurueckgeliefert.
126*cdf0e10cSrcweir // Wird von SbiTokenizer::MayBeLabel() verwendet, um einen Label zu erkennen
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir sal_Bool SbiScanner::DoesColonFollow()
129*cdf0e10cSrcweir {
130*cdf0e10cSrcweir 	if( pLine && *pLine == ':' )
131*cdf0e10cSrcweir 	{
132*cdf0e10cSrcweir 		pLine++; nCol++; return sal_True;
133*cdf0e10cSrcweir 	}
134*cdf0e10cSrcweir 	else return sal_False;
135*cdf0e10cSrcweir }
136*cdf0e10cSrcweir 
137*cdf0e10cSrcweir // Testen auf ein legales Suffix
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir static SbxDataType GetSuffixType( sal_Unicode c )
140*cdf0e10cSrcweir {
141*cdf0e10cSrcweir 	static String aSuffixesStr = String::CreateFromAscii( "%&!#@ $" );
142*cdf0e10cSrcweir 	if( c )
143*cdf0e10cSrcweir 	{
144*cdf0e10cSrcweir 		sal_uInt32 n = aSuffixesStr.Search( c );
145*cdf0e10cSrcweir 		if( STRING_NOTFOUND != n && c != ' ' )
146*cdf0e10cSrcweir 			return SbxDataType( (sal_uInt16) n + SbxINTEGER );
147*cdf0e10cSrcweir 	}
148*cdf0e10cSrcweir 	return SbxVARIANT;
149*cdf0e10cSrcweir }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir // Einlesen des naechsten Symbols in die Variablen aSym, nVal und eType
152*cdf0e10cSrcweir // Returnwert ist sal_False bei EOF oder Fehlern
153*cdf0e10cSrcweir #define BUF_SIZE 80
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir namespace {
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir /** Returns true, if the passed character is a white space character. */
158*cdf0e10cSrcweir inline bool lclIsWhitespace( sal_Unicode cChar )
159*cdf0e10cSrcweir {
160*cdf0e10cSrcweir     return (cChar == ' ') || (cChar == '\t') || (cChar == '\f');
161*cdf0e10cSrcweir }
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir } // namespace
164*cdf0e10cSrcweir 
165*cdf0e10cSrcweir sal_Bool SbiScanner::NextSym()
166*cdf0e10cSrcweir {
167*cdf0e10cSrcweir 	// Fuer den EOLN-Fall merken
168*cdf0e10cSrcweir 	sal_uInt16 nOldLine = nLine;
169*cdf0e10cSrcweir 	sal_uInt16 nOldCol1 = nCol1;
170*cdf0e10cSrcweir 	sal_uInt16 nOldCol2 = nCol2;
171*cdf0e10cSrcweir 	sal_Unicode buf[ BUF_SIZE ], *p = buf;
172*cdf0e10cSrcweir 	bHash = sal_False;
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir 	eScanType = SbxVARIANT;
175*cdf0e10cSrcweir 	aSym.Erase();
176*cdf0e10cSrcweir 	bSymbol =
177*cdf0e10cSrcweir 	bNumber = bSpaces = sal_False;
178*cdf0e10cSrcweir 
179*cdf0e10cSrcweir 	// Zeile einlesen?
180*cdf0e10cSrcweir 	if( !pLine )
181*cdf0e10cSrcweir 	{
182*cdf0e10cSrcweir 		sal_Int32 n = nBufPos;
183*cdf0e10cSrcweir 		sal_Int32 nLen = aBuf.getLength();
184*cdf0e10cSrcweir 		if( nBufPos >= nLen )
185*cdf0e10cSrcweir 			return sal_False;
186*cdf0e10cSrcweir 		const sal_Unicode* p2 = aBuf.getStr();
187*cdf0e10cSrcweir 		p2 += n;
188*cdf0e10cSrcweir 		while( ( n < nLen ) && ( *p2 != '\n' ) && ( *p2 != '\r' ) )
189*cdf0e10cSrcweir 			p2++, n++;
190*cdf0e10cSrcweir         // #163944# ignore trailing whitespace
191*cdf0e10cSrcweir         sal_Int32 nCopyEndPos = n;
192*cdf0e10cSrcweir         while( (nBufPos < nCopyEndPos) && lclIsWhitespace( aBuf[ nCopyEndPos - 1 ] ) )
193*cdf0e10cSrcweir             --nCopyEndPos;
194*cdf0e10cSrcweir 		aLine = aBuf.copy( nBufPos, nCopyEndPos - nBufPos );
195*cdf0e10cSrcweir 		if( n < nLen )
196*cdf0e10cSrcweir         {
197*cdf0e10cSrcweir 		    if( *p2 == '\r' && *( p2+1 ) == '\n' )
198*cdf0e10cSrcweir 			    n += 2;
199*cdf0e10cSrcweir 		    else
200*cdf0e10cSrcweir 			    n++;
201*cdf0e10cSrcweir         }
202*cdf0e10cSrcweir 		nBufPos = n;
203*cdf0e10cSrcweir         pLine = aLine.getStr();
204*cdf0e10cSrcweir 		nOldLine = ++nLine;
205*cdf0e10cSrcweir 		nCol = nCol1 = nCol2 = nOldCol1 = nOldCol2 = 0;
206*cdf0e10cSrcweir 		nColLock = 0;
207*cdf0e10cSrcweir 	}
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir 	// Leerstellen weg:
210*cdf0e10cSrcweir 	while( lclIsWhitespace( *pLine ) )
211*cdf0e10cSrcweir 		pLine++, nCol++, bSpaces = sal_True;
212*cdf0e10cSrcweir 
213*cdf0e10cSrcweir 	nCol1 = nCol;
214*cdf0e10cSrcweir 
215*cdf0e10cSrcweir 	// nur Leerzeile?
216*cdf0e10cSrcweir 	if( !*pLine )
217*cdf0e10cSrcweir 		goto eoln;
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir 	if( bPrevLineExtentsComment )
220*cdf0e10cSrcweir 		goto PrevLineCommentLbl;
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir 	if( *pLine == '#' )
223*cdf0e10cSrcweir 	{
224*cdf0e10cSrcweir 		pLine++;
225*cdf0e10cSrcweir 		nCol++;
226*cdf0e10cSrcweir 		bHash = sal_True;
227*cdf0e10cSrcweir 	}
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir 	// Symbol? Dann Zeichen kopieren.
230*cdf0e10cSrcweir     if( BasicSimpleCharClass::isAlpha( *pLine, bCompatible ) || *pLine == '_' )
231*cdf0e10cSrcweir 	{
232*cdf0e10cSrcweir 		// Wenn nach '_' nichts kommt, ist es ein Zeilenabschluss!
233*cdf0e10cSrcweir 		if(	*pLine == '_' && !*(pLine+1) )
234*cdf0e10cSrcweir 		{	pLine++;
235*cdf0e10cSrcweir 			goto eoln;	}
236*cdf0e10cSrcweir 		bSymbol = sal_True;
237*cdf0e10cSrcweir 		short n = nCol;
238*cdf0e10cSrcweir 		for ( ; (BasicSimpleCharClass::isAlphaNumeric( *pLine, bCompatible ) || ( *pLine == '_' ) ); pLine++ )
239*cdf0e10cSrcweir 			nCol++;
240*cdf0e10cSrcweir 		aSym = aLine.copy( n, nCol - n );
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir 		// Special handling for "go to"
243*cdf0e10cSrcweir 		if( bCompatible && *pLine && aSym.EqualsIgnoreCaseAscii( "go" ) )
244*cdf0e10cSrcweir 		{
245*cdf0e10cSrcweir 			const sal_Unicode* pTestLine = pLine;
246*cdf0e10cSrcweir 			short nTestCol = nCol;
247*cdf0e10cSrcweir 			while( lclIsWhitespace( *pTestLine ) )
248*cdf0e10cSrcweir 			{
249*cdf0e10cSrcweir 				pTestLine++;
250*cdf0e10cSrcweir 				nTestCol++;
251*cdf0e10cSrcweir 			}
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 			if( *pTestLine && *(pTestLine + 1) )
254*cdf0e10cSrcweir 			{
255*cdf0e10cSrcweir 				String aTestSym = aLine.copy( nTestCol, 2 );
256*cdf0e10cSrcweir 				if( aTestSym.EqualsIgnoreCaseAscii( "to" ) )
257*cdf0e10cSrcweir 				{
258*cdf0e10cSrcweir 					aSym = String::CreateFromAscii( "goto" );
259*cdf0e10cSrcweir 					pLine = pTestLine + 2;
260*cdf0e10cSrcweir 					nCol = nTestCol + 2;
261*cdf0e10cSrcweir 				}
262*cdf0e10cSrcweir 			}
263*cdf0e10cSrcweir 		}
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir 		// Abschliessendes '_' durch Space ersetzen, wenn Zeilenende folgt
266*cdf0e10cSrcweir 		// (sonst falsche Zeilenfortsetzung)
267*cdf0e10cSrcweir 		if(	!bUsedForHilite && !*pLine && *(pLine-1) == '_' )
268*cdf0e10cSrcweir 		{
269*cdf0e10cSrcweir 			aSym.GetBufferAccess();		// #109693 force copy if necessary
270*cdf0e10cSrcweir 			*((sal_Unicode*)(pLine-1)) = ' ';		// cast wegen const
271*cdf0e10cSrcweir 		}
272*cdf0e10cSrcweir 		// Typkennung?
273*cdf0e10cSrcweir 		// Das Ausrufezeichen bitte nicht testen, wenn
274*cdf0e10cSrcweir 		// danach noch ein Symbol anschliesst
275*cdf0e10cSrcweir 		else if( *pLine != '!' || !BasicSimpleCharClass::isAlpha( pLine[ 1 ], bCompatible ) )
276*cdf0e10cSrcweir 		{
277*cdf0e10cSrcweir 			SbxDataType t = GetSuffixType( *pLine );
278*cdf0e10cSrcweir 			if( t != SbxVARIANT )
279*cdf0e10cSrcweir 			{
280*cdf0e10cSrcweir 				eScanType = t;
281*cdf0e10cSrcweir 				pLine++;
282*cdf0e10cSrcweir 				nCol++;
283*cdf0e10cSrcweir 			}
284*cdf0e10cSrcweir 		}
285*cdf0e10cSrcweir 	}
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir 	// Zahl? Dann einlesen und konvertieren.
288*cdf0e10cSrcweir 	else if( BasicSimpleCharClass::isDigit( *pLine & 0xFF )
289*cdf0e10cSrcweir 		|| ( *pLine == '.' && BasicSimpleCharClass::isDigit( *(pLine+1) & 0xFF ) ) )
290*cdf0e10cSrcweir 	{
291*cdf0e10cSrcweir 		short exp = 0;
292*cdf0e10cSrcweir 		short comma = 0;
293*cdf0e10cSrcweir 		short ndig = 0;
294*cdf0e10cSrcweir 		short ncdig = 0;
295*cdf0e10cSrcweir 		eScanType = SbxDOUBLE;
296*cdf0e10cSrcweir 		sal_Bool bBufOverflow = sal_False;
297*cdf0e10cSrcweir 		while( strchr( "0123456789.DEde", *pLine ) && *pLine )
298*cdf0e10cSrcweir 		{
299*cdf0e10cSrcweir 			// AB 4.1.1996: Buffer voll? -> leer weiter scannen
300*cdf0e10cSrcweir 			if( (p-buf) == (BUF_SIZE-1) )
301*cdf0e10cSrcweir 			{
302*cdf0e10cSrcweir 				bBufOverflow = sal_True;
303*cdf0e10cSrcweir 				pLine++, nCol++;
304*cdf0e10cSrcweir 				continue;
305*cdf0e10cSrcweir 			}
306*cdf0e10cSrcweir 			// Komma oder Exponent?
307*cdf0e10cSrcweir 			if( *pLine == '.' )
308*cdf0e10cSrcweir 			{
309*cdf0e10cSrcweir 				if( ++comma > 1 )
310*cdf0e10cSrcweir 				{
311*cdf0e10cSrcweir 					pLine++; nCol++; continue;
312*cdf0e10cSrcweir 				}
313*cdf0e10cSrcweir 				else *p++ = *pLine++, nCol++;
314*cdf0e10cSrcweir 			}
315*cdf0e10cSrcweir 			else if( strchr( "DdEe", *pLine ) )
316*cdf0e10cSrcweir 			{
317*cdf0e10cSrcweir 				if (++exp > 1)
318*cdf0e10cSrcweir 				{
319*cdf0e10cSrcweir 					pLine++; nCol++; continue;
320*cdf0e10cSrcweir 				}
321*cdf0e10cSrcweir //              if( toupper( *pLine ) == 'D' )
322*cdf0e10cSrcweir //                  eScanType = SbxDOUBLE;
323*cdf0e10cSrcweir 				*p++ = 'E'; pLine++; nCol++;
324*cdf0e10cSrcweir 				// Vorzeichen hinter Exponent?
325*cdf0e10cSrcweir 				if( *pLine == '+' )
326*cdf0e10cSrcweir 					pLine++, nCol++;
327*cdf0e10cSrcweir 				else
328*cdf0e10cSrcweir 				if( *pLine == '-' )
329*cdf0e10cSrcweir 					*p++ = *pLine++, nCol++;
330*cdf0e10cSrcweir 			}
331*cdf0e10cSrcweir 			else
332*cdf0e10cSrcweir 			{
333*cdf0e10cSrcweir 				*p++ = *pLine++, nCol++;
334*cdf0e10cSrcweir 				if( comma && !exp ) ncdig++;
335*cdf0e10cSrcweir 			}
336*cdf0e10cSrcweir 			if (!exp) ndig++;
337*cdf0e10cSrcweir 		}
338*cdf0e10cSrcweir 		*p = 0;
339*cdf0e10cSrcweir 		aSym = p; bNumber = sal_True;
340*cdf0e10cSrcweir 		// Komma, Exponent mehrfach vorhanden?
341*cdf0e10cSrcweir 		if( comma > 1 || exp > 1 )
342*cdf0e10cSrcweir 		{	aError = '.';
343*cdf0e10cSrcweir 			GenError( SbERR_BAD_CHAR_IN_NUMBER );	}
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir 		// #57844 Lokalisierte Funktion benutzen
346*cdf0e10cSrcweir 	    nVal = rtl_math_uStringToDouble( buf, buf+(p-buf), '.', ',', NULL, NULL );
347*cdf0e10cSrcweir 		// ALT: nVal = atof( buf );
348*cdf0e10cSrcweir 
349*cdf0e10cSrcweir 		ndig = ndig - comma;
350*cdf0e10cSrcweir 		if( !comma && !exp )
351*cdf0e10cSrcweir 		{
352*cdf0e10cSrcweir 			if( nVal >= SbxMININT && nVal <= SbxMAXINT )
353*cdf0e10cSrcweir 				eScanType = SbxINTEGER;
354*cdf0e10cSrcweir 			else
355*cdf0e10cSrcweir 			if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
356*cdf0e10cSrcweir 				eScanType = SbxLONG;
357*cdf0e10cSrcweir 		}
358*cdf0e10cSrcweir 		if( bBufOverflow )
359*cdf0e10cSrcweir 			GenError( SbERR_MATH_OVERFLOW );
360*cdf0e10cSrcweir 		// zu viele Zahlen fuer SINGLE?
361*cdf0e10cSrcweir //      if (ndig > 15 || ncdig > 6)
362*cdf0e10cSrcweir //          eScanType = SbxDOUBLE;
363*cdf0e10cSrcweir //      else
364*cdf0e10cSrcweir //      if( nVal > SbxMAXSNG || nVal < SbxMINSNG )
365*cdf0e10cSrcweir //          eScanType = SbxDOUBLE;
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir 		// Typkennung?
368*cdf0e10cSrcweir 		SbxDataType t = GetSuffixType( *pLine );
369*cdf0e10cSrcweir 		if( t != SbxVARIANT )
370*cdf0e10cSrcweir 		{
371*cdf0e10cSrcweir 			eScanType = t;
372*cdf0e10cSrcweir 			pLine++;
373*cdf0e10cSrcweir 			nCol++;
374*cdf0e10cSrcweir 		}
375*cdf0e10cSrcweir 	}
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir 	// Hex/Oktalzahl? Einlesen und konvertieren:
378*cdf0e10cSrcweir 	else if( *pLine == '&' )
379*cdf0e10cSrcweir 	{
380*cdf0e10cSrcweir 		pLine++; nCol++;
381*cdf0e10cSrcweir 		sal_Unicode cmp1[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', 0 };
382*cdf0e10cSrcweir 		sal_Unicode cmp2[] = { '0', '1', '2', '3', '4', '5', '6', '7', 0 };
383*cdf0e10cSrcweir 		sal_Unicode *cmp = cmp1;
384*cdf0e10cSrcweir 		//char *cmp = "0123456789ABCDEF";
385*cdf0e10cSrcweir 		sal_Unicode base = 16;
386*cdf0e10cSrcweir 		sal_Unicode ndig = 8;
387*cdf0e10cSrcweir 		sal_Unicode xch  = *pLine++ & 0xFF; nCol++;
388*cdf0e10cSrcweir 		switch( toupper( xch ) )
389*cdf0e10cSrcweir 		{
390*cdf0e10cSrcweir 			case 'O':
391*cdf0e10cSrcweir 				cmp = cmp2; base = 8; ndig = 11; break;
392*cdf0e10cSrcweir 				//cmp = "01234567"; base = 8; ndig = 11; break;
393*cdf0e10cSrcweir 			case 'H':
394*cdf0e10cSrcweir 				break;
395*cdf0e10cSrcweir 			default :
396*cdf0e10cSrcweir 				// Wird als Operator angesehen
397*cdf0e10cSrcweir 				pLine--; nCol--; nCol1 = nCol-1; aSym = '&'; return SYMBOL;
398*cdf0e10cSrcweir 		}
399*cdf0e10cSrcweir 		bNumber = sal_True;
400*cdf0e10cSrcweir 		long l = 0;
401*cdf0e10cSrcweir 		int i;
402*cdf0e10cSrcweir 		sal_Bool bBufOverflow = sal_False;
403*cdf0e10cSrcweir 		while( BasicSimpleCharClass::isAlphaNumeric( *pLine & 0xFF, bCompatible ) )
404*cdf0e10cSrcweir 		{
405*cdf0e10cSrcweir 			sal_Unicode ch = sal::static_int_cast< sal_Unicode >(
406*cdf0e10cSrcweir                 toupper( *pLine & 0xFF ) );
407*cdf0e10cSrcweir 			pLine++; nCol++;
408*cdf0e10cSrcweir 			// AB 4.1.1996: Buffer voll, leer weiter scannen
409*cdf0e10cSrcweir 			if( (p-buf) == (BUF_SIZE-1) )
410*cdf0e10cSrcweir 				bBufOverflow = sal_True;
411*cdf0e10cSrcweir 			else if( String( cmp ).Search( ch ) != STRING_NOTFOUND )
412*cdf0e10cSrcweir 			//else if( strchr( cmp, ch ) )
413*cdf0e10cSrcweir 				*p++ = ch;
414*cdf0e10cSrcweir 			else
415*cdf0e10cSrcweir 			{
416*cdf0e10cSrcweir 				aError = ch;
417*cdf0e10cSrcweir 				GenError( SbERR_BAD_CHAR_IN_NUMBER );
418*cdf0e10cSrcweir 			}
419*cdf0e10cSrcweir 		}
420*cdf0e10cSrcweir 		*p = 0;
421*cdf0e10cSrcweir 		for( p = buf; *p; p++ )
422*cdf0e10cSrcweir 		{
423*cdf0e10cSrcweir 			i = (*p & 0xFF) - '0';
424*cdf0e10cSrcweir 			if( i > 9 ) i -= 7;
425*cdf0e10cSrcweir 			l = ( l * base ) + i;
426*cdf0e10cSrcweir 			if( !ndig-- )
427*cdf0e10cSrcweir 			{
428*cdf0e10cSrcweir 				GenError( SbERR_MATH_OVERFLOW ); break;
429*cdf0e10cSrcweir 			}
430*cdf0e10cSrcweir 		}
431*cdf0e10cSrcweir 		if( *pLine == '&' ) pLine++, nCol++;
432*cdf0e10cSrcweir 		nVal = (double) l;
433*cdf0e10cSrcweir 		eScanType = ( l >= SbxMININT && l <= SbxMAXINT ) ? SbxINTEGER : SbxLONG;
434*cdf0e10cSrcweir 		if( bBufOverflow )
435*cdf0e10cSrcweir 			GenError( SbERR_MATH_OVERFLOW );
436*cdf0e10cSrcweir 	}
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir 	// Strings:
439*cdf0e10cSrcweir 	else if( *pLine == '"' || *pLine == '[' )
440*cdf0e10cSrcweir 	{
441*cdf0e10cSrcweir 		sal_Unicode cSep = *pLine;
442*cdf0e10cSrcweir 		if( cSep == '[' )
443*cdf0e10cSrcweir 			bSymbol = sal_True, cSep = ']';
444*cdf0e10cSrcweir 		short n = nCol+1;
445*cdf0e10cSrcweir 		while( *pLine )
446*cdf0e10cSrcweir 		{
447*cdf0e10cSrcweir 			do pLine++, nCol++;
448*cdf0e10cSrcweir 			while( *pLine && ( *pLine != cSep ) );
449*cdf0e10cSrcweir 			if( *pLine == cSep )
450*cdf0e10cSrcweir 			{
451*cdf0e10cSrcweir 				pLine++; nCol++;
452*cdf0e10cSrcweir 				if( *pLine != cSep || cSep == ']' ) break;
453*cdf0e10cSrcweir 			} else aError = cSep, GenError( SbERR_EXPECTED );
454*cdf0e10cSrcweir 		}
455*cdf0e10cSrcweir 		// If VBA Interop then doen't eat the [] chars
456*cdf0e10cSrcweir 		if ( cSep == ']' && bVBASupportOn )
457*cdf0e10cSrcweir 			aSym = aLine.copy( n - 1, nCol - n  + 1);
458*cdf0e10cSrcweir 		else
459*cdf0e10cSrcweir 			aSym = aLine.copy( n, nCol - n - 1 );
460*cdf0e10cSrcweir 		// Doppelte Stringbegrenzer raus
461*cdf0e10cSrcweir 		String s( cSep );
462*cdf0e10cSrcweir 		s += cSep;
463*cdf0e10cSrcweir 		sal_uInt16 nIdx = 0;
464*cdf0e10cSrcweir 		do
465*cdf0e10cSrcweir 		{
466*cdf0e10cSrcweir 			nIdx = aSym.Search( s, nIdx );
467*cdf0e10cSrcweir 			if( nIdx == STRING_NOTFOUND )
468*cdf0e10cSrcweir 				break;
469*cdf0e10cSrcweir 			aSym.Erase( nIdx, 1 );
470*cdf0e10cSrcweir 			nIdx++;
471*cdf0e10cSrcweir 		}
472*cdf0e10cSrcweir 		while( true );
473*cdf0e10cSrcweir 		if( cSep != ']' )
474*cdf0e10cSrcweir 			eScanType = ( cSep == '#' ) ? SbxDATE : SbxSTRING;
475*cdf0e10cSrcweir 	}
476*cdf0e10cSrcweir 	// ungueltige Zeichen:
477*cdf0e10cSrcweir 	else if( ( *pLine & 0xFF ) >= 0x7F )
478*cdf0e10cSrcweir 	{
479*cdf0e10cSrcweir 		GenError( SbERR_SYNTAX ); pLine++; nCol++;
480*cdf0e10cSrcweir 	}
481*cdf0e10cSrcweir 	// andere Gruppen:
482*cdf0e10cSrcweir 	else
483*cdf0e10cSrcweir 	{
484*cdf0e10cSrcweir 		short n = 1;
485*cdf0e10cSrcweir 		switch( *pLine++ )
486*cdf0e10cSrcweir 		{
487*cdf0e10cSrcweir 			case '<': if( *pLine == '>' || *pLine == '=' ) n = 2; break;
488*cdf0e10cSrcweir 			case '>': if( *pLine == '=' ) n = 2; break;
489*cdf0e10cSrcweir 			case ':': if( *pLine == '=' ) n = 2; break;
490*cdf0e10cSrcweir 		}
491*cdf0e10cSrcweir 		aSym = aLine.copy( nCol, n );
492*cdf0e10cSrcweir 		pLine += n-1; nCol = nCol + n;
493*cdf0e10cSrcweir 	}
494*cdf0e10cSrcweir 
495*cdf0e10cSrcweir 	nCol2 = nCol-1;
496*cdf0e10cSrcweir 
497*cdf0e10cSrcweir PrevLineCommentLbl:
498*cdf0e10cSrcweir 	// Kommentar?
499*cdf0e10cSrcweir 	if( bPrevLineExtentsComment || (eScanType != SbxSTRING &&
500*cdf0e10cSrcweir 		( aSym.GetBuffer()[0] == '\'' || aSym.EqualsIgnoreCaseAscii( "REM" ) ) ) )
501*cdf0e10cSrcweir 	{
502*cdf0e10cSrcweir 		bPrevLineExtentsComment = sal_False;
503*cdf0e10cSrcweir 		aSym = String::CreateFromAscii( "REM" );
504*cdf0e10cSrcweir 		sal_uInt16 nLen = String( pLine ).Len();
505*cdf0e10cSrcweir 		if( bCompatible && pLine[ nLen - 1 ] == '_' && pLine[ nLen - 2 ] == ' ' )
506*cdf0e10cSrcweir 			bPrevLineExtentsComment = sal_True;
507*cdf0e10cSrcweir 		nCol2 = nCol2 + nLen;
508*cdf0e10cSrcweir 		pLine = NULL;
509*cdf0e10cSrcweir 	}
510*cdf0e10cSrcweir 	return sal_True;
511*cdf0e10cSrcweir 
512*cdf0e10cSrcweir 	// Sonst Zeilen-Ende: aber bitte auf '_' testen, ob die
513*cdf0e10cSrcweir 	// Zeile nicht weitergeht!
514*cdf0e10cSrcweir eoln:
515*cdf0e10cSrcweir 	if( nCol && *--pLine == '_' )
516*cdf0e10cSrcweir 	{
517*cdf0e10cSrcweir 		pLine = NULL;
518*cdf0e10cSrcweir 		bool bRes = NextSym();
519*cdf0e10cSrcweir 		if( bVBASupportOn && aSym.GetBuffer()[0] == '.' )
520*cdf0e10cSrcweir 		{
521*cdf0e10cSrcweir 			// object _
522*cdf0e10cSrcweir 			//    .Method
523*cdf0e10cSrcweir 			// ^^^  <- spaces is legal in MSO VBA
524*cdf0e10cSrcweir 			OSL_TRACE("*** resetting bSpaces***");
525*cdf0e10cSrcweir 			bSpaces = sal_False;
526*cdf0e10cSrcweir 		}
527*cdf0e10cSrcweir 		return bRes;
528*cdf0e10cSrcweir 	}
529*cdf0e10cSrcweir 	else
530*cdf0e10cSrcweir 	{
531*cdf0e10cSrcweir 		pLine = NULL;
532*cdf0e10cSrcweir 		nLine = nOldLine;
533*cdf0e10cSrcweir 		nCol1 = nOldCol1;
534*cdf0e10cSrcweir 		nCol2 = nOldCol2;
535*cdf0e10cSrcweir 		aSym = '\n';
536*cdf0e10cSrcweir 		nColLock = 0;
537*cdf0e10cSrcweir 		return sal_True;
538*cdf0e10cSrcweir 	}
539*cdf0e10cSrcweir }
540*cdf0e10cSrcweir 
541*cdf0e10cSrcweir LetterTable BasicSimpleCharClass::aLetterTable;
542*cdf0e10cSrcweir 
543*cdf0e10cSrcweir LetterTable::LetterTable( void )
544*cdf0e10cSrcweir {
545*cdf0e10cSrcweir 	for( int i = 0 ; i < 256 ; ++i )
546*cdf0e10cSrcweir 		IsLetterTab[i] = false;
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir 	IsLetterTab[0xC0] = true;	// � , CAPITAL LETTER A WITH GRAVE ACCENT
549*cdf0e10cSrcweir 	IsLetterTab[0xC1] = true;	// � , CAPITAL LETTER A WITH ACUTE ACCENT
550*cdf0e10cSrcweir 	IsLetterTab[0xC2] = true;	// � , CAPITAL LETTER A WITH CIRCUMFLEX ACCENT
551*cdf0e10cSrcweir 	IsLetterTab[0xC3] = true;	// � , CAPITAL LETTER A WITH TILDE
552*cdf0e10cSrcweir 	IsLetterTab[0xC4] = true;	// � , CAPITAL LETTER A WITH DIAERESIS
553*cdf0e10cSrcweir 	IsLetterTab[0xC5] = true;	// � , CAPITAL LETTER A WITH RING ABOVE
554*cdf0e10cSrcweir 	IsLetterTab[0xC6] = true;	// � , CAPITAL LIGATURE AE
555*cdf0e10cSrcweir 	IsLetterTab[0xC7] = true;	// � , CAPITAL LETTER C WITH CEDILLA
556*cdf0e10cSrcweir 	IsLetterTab[0xC8] = true;	// � , CAPITAL LETTER E WITH GRAVE ACCENT
557*cdf0e10cSrcweir 	IsLetterTab[0xC9] = true;	// � , CAPITAL LETTER E WITH ACUTE ACCENT
558*cdf0e10cSrcweir 	IsLetterTab[0xCA] = true;	// � , CAPITAL LETTER E WITH CIRCUMFLEX ACCENT
559*cdf0e10cSrcweir 	IsLetterTab[0xCB] = true;	// � , CAPITAL LETTER E WITH DIAERESIS
560*cdf0e10cSrcweir 	IsLetterTab[0xCC] = true;	// � , CAPITAL LETTER I WITH GRAVE ACCENT
561*cdf0e10cSrcweir 	IsLetterTab[0xCD] = true;	// � , CAPITAL LETTER I WITH ACUTE ACCENT
562*cdf0e10cSrcweir 	IsLetterTab[0xCE] = true;	// � , CAPITAL LETTER I WITH CIRCUMFLEX ACCENT
563*cdf0e10cSrcweir 	IsLetterTab[0xCF] = true;	// � , CAPITAL LETTER I WITH DIAERESIS
564*cdf0e10cSrcweir 	IsLetterTab[0xD0] = true;	// � , CAPITAL LETTER ETH
565*cdf0e10cSrcweir 	IsLetterTab[0xD1] = true;	// � , CAPITAL LETTER N WITH TILDE
566*cdf0e10cSrcweir 	IsLetterTab[0xD2] = true;	// � , CAPITAL LETTER O WITH GRAVE ACCENT
567*cdf0e10cSrcweir 	IsLetterTab[0xD3] = true;	// � , CAPITAL LETTER O WITH ACUTE ACCENT
568*cdf0e10cSrcweir 	IsLetterTab[0xD4] = true;	// � , CAPITAL LETTER O WITH CIRCUMFLEX ACCENT
569*cdf0e10cSrcweir 	IsLetterTab[0xD5] = true;	// � , CAPITAL LETTER O WITH TILDE
570*cdf0e10cSrcweir 	IsLetterTab[0xD6] = true;	// � , CAPITAL LETTER O WITH DIAERESIS
571*cdf0e10cSrcweir 	IsLetterTab[0xD8] = true;	// � , CAPITAL LETTER O WITH STROKE
572*cdf0e10cSrcweir 	IsLetterTab[0xD9] = true;	// � , CAPITAL LETTER U WITH GRAVE ACCENT
573*cdf0e10cSrcweir 	IsLetterTab[0xDA] = true;	// � , CAPITAL LETTER U WITH ACUTE ACCENT
574*cdf0e10cSrcweir 	IsLetterTab[0xDB] = true;	// � , CAPITAL LETTER U WITH CIRCUMFLEX ACCENT
575*cdf0e10cSrcweir 	IsLetterTab[0xDC] = true;	// � , CAPITAL LETTER U WITH DIAERESIS
576*cdf0e10cSrcweir 	IsLetterTab[0xDD] = true;	// � , CAPITAL LETTER Y WITH ACUTE ACCENT
577*cdf0e10cSrcweir 	IsLetterTab[0xDE] = true;	// � , CAPITAL LETTER THORN
578*cdf0e10cSrcweir 	IsLetterTab[0xDF] = true;	// � , SMALL LETTER SHARP S
579*cdf0e10cSrcweir 	IsLetterTab[0xE0] = true;	// � , SMALL LETTER A WITH GRAVE ACCENT
580*cdf0e10cSrcweir 	IsLetterTab[0xE1] = true;	// � , SMALL LETTER A WITH ACUTE ACCENT
581*cdf0e10cSrcweir 	IsLetterTab[0xE2] = true;	// � , SMALL LETTER A WITH CIRCUMFLEX ACCENT
582*cdf0e10cSrcweir 	IsLetterTab[0xE3] = true;	// � , SMALL LETTER A WITH TILDE
583*cdf0e10cSrcweir 	IsLetterTab[0xE4] = true;	// � , SMALL LETTER A WITH DIAERESIS
584*cdf0e10cSrcweir 	IsLetterTab[0xE5] = true;	// � , SMALL LETTER A WITH RING ABOVE
585*cdf0e10cSrcweir 	IsLetterTab[0xE6] = true;	// � , SMALL LIGATURE AE
586*cdf0e10cSrcweir 	IsLetterTab[0xE7] = true;	// � , SMALL LETTER C WITH CEDILLA
587*cdf0e10cSrcweir 	IsLetterTab[0xE8] = true;	// � , SMALL LETTER E WITH GRAVE ACCENT
588*cdf0e10cSrcweir 	IsLetterTab[0xE9] = true;	// � , SMALL LETTER E WITH ACUTE ACCENT
589*cdf0e10cSrcweir 	IsLetterTab[0xEA] = true;	// � , SMALL LETTER E WITH CIRCUMFLEX ACCENT
590*cdf0e10cSrcweir 	IsLetterTab[0xEB] = true;	// � , SMALL LETTER E WITH DIAERESIS
591*cdf0e10cSrcweir 	IsLetterTab[0xEC] = true;	// � , SMALL LETTER I WITH GRAVE ACCENT
592*cdf0e10cSrcweir 	IsLetterTab[0xED] = true;	// � , SMALL LETTER I WITH ACUTE ACCENT
593*cdf0e10cSrcweir 	IsLetterTab[0xEE] = true;	// � , SMALL LETTER I WITH CIRCUMFLEX ACCENT
594*cdf0e10cSrcweir 	IsLetterTab[0xEF] = true;	// � , SMALL LETTER I WITH DIAERESIS
595*cdf0e10cSrcweir 	IsLetterTab[0xF0] = true;	// � , SMALL LETTER ETH
596*cdf0e10cSrcweir 	IsLetterTab[0xF1] = true;	// � , SMALL LETTER N WITH TILDE
597*cdf0e10cSrcweir 	IsLetterTab[0xF2] = true;	// � , SMALL LETTER O WITH GRAVE ACCENT
598*cdf0e10cSrcweir 	IsLetterTab[0xF3] = true;	// � , SMALL LETTER O WITH ACUTE ACCENT
599*cdf0e10cSrcweir 	IsLetterTab[0xF4] = true;	// � , SMALL LETTER O WITH CIRCUMFLEX ACCENT
600*cdf0e10cSrcweir 	IsLetterTab[0xF5] = true;	// � , SMALL LETTER O WITH TILDE
601*cdf0e10cSrcweir 	IsLetterTab[0xF6] = true;	// � , SMALL LETTER O WITH DIAERESIS
602*cdf0e10cSrcweir 	IsLetterTab[0xF8] = true;	// � , SMALL LETTER O WITH OBLIQUE BAR
603*cdf0e10cSrcweir 	IsLetterTab[0xF9] = true;	// � , SMALL LETTER U WITH GRAVE ACCENT
604*cdf0e10cSrcweir 	IsLetterTab[0xFA] = true;	// � , SMALL LETTER U WITH ACUTE ACCENT
605*cdf0e10cSrcweir 	IsLetterTab[0xFB] = true;	// � , SMALL LETTER U WITH CIRCUMFLEX ACCENT
606*cdf0e10cSrcweir 	IsLetterTab[0xFC] = true;	// � , SMALL LETTER U WITH DIAERESIS
607*cdf0e10cSrcweir 	IsLetterTab[0xFD] = true;	// � , SMALL LETTER Y WITH ACUTE ACCENT
608*cdf0e10cSrcweir 	IsLetterTab[0xFE] = true;	// � , SMALL LETTER THORN
609*cdf0e10cSrcweir 	IsLetterTab[0xFF] = true;	// � , SMALL LETTER Y WITH DIAERESIS
610*cdf0e10cSrcweir }
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir bool LetterTable::isLetterUnicode( sal_Unicode c )
613*cdf0e10cSrcweir {
614*cdf0e10cSrcweir 	static CharClass* pCharClass = NULL;
615*cdf0e10cSrcweir 	if( pCharClass == NULL )
616*cdf0e10cSrcweir 		pCharClass = new CharClass( Application::GetSettings().GetLocale() );
617*cdf0e10cSrcweir 	String aStr( c );
618*cdf0e10cSrcweir 	bool bRet = pCharClass->isLetter( aStr, 0 );
619*cdf0e10cSrcweir 	return bRet;
620*cdf0e10cSrcweir }
621