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