1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 %option yylineno
21 
22 %{
23 /*
24  * scanner.ll - Lexical scanner for IDLC 1.0
25  */
26 
27 #include <sal/config.h>
28 
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <rtl/character.hxx>
33 
34 #if defined _MSC_VER
35 #pragma warning ( push )
36 // Silence warnings about redefinition of INT8_MIN etc in stdint.h
37 // The flex-generated workdir/LexTarget/idlc/source/scanner.cxx defines them prior to these includes
38 #pragma warning ( disable : 4005 )
39 #endif
40 #include <idlc.hxx>
41 #if defined _MSC_VER
42 #pragma warning ( pop )
43 #endif
44 #include <errorhandler.hxx>
45 #include <fehelper.hxx>
46 
47 #include "attributeexceptions.hxx"
48 
49 
50 class AstExpression;
51 class AstMember;
52 
53 #include <parser.hxx>
54 
55 /* handle locations */
56 static int yycolumn = 1;
57 
58 #define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \
59     yycolumn += yyleng;
60 
61 static sal_Int32       beginLine = 0;
62 static OString docu;
63 
asciiToInteger(char const * s,sal_Int64 * sval,sal_uInt64 * uval)64 static int asciiToInteger(char const * s, sal_Int64  * sval, sal_uInt64 * uval) {
65     bool neg = false;
66     if (*s == '-') {
67         neg = true;
68         ++s;
69     }
70     unsigned int base = 10;
71     if (*s == '0') {
72         base = 8;
73         ++s;
74         if (*s == 'X' || *s == 'x') {
75             base = 16;
76             ++s;
77         }
78     }
79     sal_uInt64 val = 0;
80     for (; *s != 0; ++s) {
81         unsigned int n;
82         if (*s >= '0' && *s <= '9') {
83             n = *s - '0';
84         } else {
85             switch (*s) {
86             case 'A':
87             case 'a':
88                 n = 10;
89                 break;
90             case 'B':
91             case 'b':
92                 n = 11;
93                 break;
94             case 'C':
95             case 'c':
96                 n = 12;
97                 break;
98             case 'D':
99             case 'd':
100                 n = 13;
101                 break;
102             case 'E':
103             case 'e':
104                 n = 14;
105                 break;
106             case 'F':
107             case 'f':
108                 n = 15;
109                 break;
110             default:
111                 goto done;
112             }
113         }
114         // The following guarantees the invariant val <= SAL_MAX_UINT64 (because
115         // base and n are sufficiently small), *if*
116         // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64:
117         sal_uInt64 nval = val * base + n;
118         if (nval < val) {
119             ErrorHandler::syntaxError(
120                 PS_NoState, idlc()->getLineNumber(),
121                 "integral constant too large");
122             val = 0;
123             break;
124         }
125         val = nval;
126     }
127  done:
128     if (neg) {
129         if (val < SAL_CONST_UINT64(0x8000000000000000)) {
130             *sval = -static_cast< sal_Int64 >(val);
131         } else if (val == SAL_CONST_UINT64(0x8000000000000000)) {
132             *sval = SAL_MIN_INT64;
133         } else {
134             ErrorHandler::syntaxError(
135                 PS_NoState, idlc()->getLineNumber(),
136                 "negative integral constant too large");
137             *sval = 0;
138         }
139         return IDL_INTEGER_LITERAL;
140     } else if (val <= static_cast< sal_uInt64 >(SAL_MAX_INT64)) {
141         *sval = static_cast< sal_Int64 >(val);
142         return IDL_INTEGER_LITERAL;
143     } else {
144         *uval = val;
145         return IDL_INTEGER_ULITERAL;
146     }
147 }
148 
asciiToFloat(const sal_Char * s)149 static double asciiToFloat(const sal_Char *s)
150 {
151     double      d = 0.0;
152     double      e, k;
153     sal_Int32   neg = 0;
154 
155     if (*s == '-')
156     {
157         neg = 1;
158         s++;
159     }
160     while (*s >= '0' && *s <= '9')
161     {
162         d = (d * 10) + *s - '0';
163         s++;
164     }
165     if (*s == '.')
166     {
167         s++;
168         e = 10;
169         while (*s >= '0' && *s <= '9')
170         {
171             d += (*s - '0') / (e * 1.0);
172             e *= 10;
173             s++;
174         }
175     }
176     if (*s == 'e' || *s == 'E')
177     {
178         s++;
179         if (*s == '-')
180         {
181             s++;
182         } else
183         {
184             if (*s == '+')
185                 s++;
186             e = 0;
187             while (*s >= '0' && *s <= '9')
188             {
189                 e = (e * 10) + *s - '0';
190                 s++;
191             }
192             if (e > 0)
193             {
194                 for (k = 1; e > 0; k *= 10, e--)
195                     ;
196                 d /= k;
197             }
198         }
199     }
200     if (neg) d *= -1.0;
201     return d;
202 }
203 
idlParsePragma(sal_Char * pPragma)204 static void idlParsePragma(sal_Char* pPragma)
205 {
206     OString pragma(pPragma);
207     sal_Int32 index = pragma.indexOf("include");
208     sal_Char* begin = pPragma + index + 8;
209     sal_Char* offset = begin;
210     while (*offset != ',') offset++;
211     //OString include = pragma.copy(index + 8, offset - begin);
212     //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
213 }
214 
parseLineAndFile(sal_Char * pBuf)215 static void parseLineAndFile(sal_Char* pBuf)
216 {
217     sal_Char    *r = pBuf;
218     sal_Char    *h;
219     bool    bIsInMain = false;
220 
221     /* Skip initial '#' */
222     if (*r != '#')
223         return;
224 
225     /* Find line number */
226     for (r++; *r == ' ' || *r == '\t' || rtl::isAsciiAlpha(static_cast<unsigned char>(*r)); r++) ;
227     h = r;
228     for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
229     *r++ = 0;
230     idlc()->setLineNumber(sal_uInt32(atol(h)));
231     yylineno = atol(h);
232 
233     /* Find file name, if present */
234     for (; *r != '"'; r++)
235     {
236         if (*r == '\n' || *r == '\0')
237             return;
238     }
239     h = ++r;
240     for (; *r != '"'; r++) ;
241     *r = 0;
242     if (*h == '\0')
243         idlc()->setFileName("standard input");
244     else
245         idlc()->setFileName(OString(h));
246 
247     bIsInMain = idlc()->getFileName() == idlc()->getRealFileName();
248     idlc()->setInMainfile(bIsInMain);
249 }
250 
251 // Suppress any warnings from generated code:
252 #ifdef __GNUC__
253 #pragma GCC diagnostic ignored "-Wunused-function"
254 #pragma GCC diagnostic ignored "-Wunused-label"
255 #elif defined _MSC_VER
256 /**/
257 #ifdef yywrap
258 #undef  yywrap
259 #define yywrap() 1
260 #endif
261 /**/
262 #endif
263 #define YY_NO_UNISTD_H
264 %}
265 
266 %option noyywrap
267 %option never-interactive
268 
269 %x DOCU
270 %x COMMENT
271 
272 DIGIT           [0-9]
273 OCT_DIGIT       [0-7]
274 HEX_DIGIT       [a-fA-F0-9]
275 CAPITAL         [A-Z]
276 ALPHA           [a-zA-Z]
277 INT_LITERAL     [1-9][0-9]*
278 OCT_LITERAL     0{OCT_DIGIT}*
279 HEX_LITERAL     (0x|0X){HEX_DIGIT}*
280 
281 IDENTIFIER_NEW  ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
282 IDENTIFIER      ("_"?({ALPHA}|{DIGIT})+)*
283 
284 %%
285 
286 [ \t\r]+    ; /* eat up whitespace */
287 [\n]           {
288        idlc()->incLineNumber();
289        yycolumn = 1;
290        yylineno++;
291 }
292 
293 attribute       return IDL_ATTRIBUTE;
294 bound           return IDL_BOUND;
295 const           return IDL_CONST;
296 constants       return IDL_CONSTANTS;
297 constrained     return IDL_CONSTRAINED;
298 enum            return IDL_ENUM;
299 exception       return IDL_EXCEPTION;
300 interface       return IDL_INTERFACE;
301 maybeambiguous  return IDL_MAYBEAMBIGUOUS;
302 maybedefault    return IDL_MAYBEDEFAULT;
303 maybevoid       return IDL_MAYBEVOID;
304 module          return IDL_MODULE;
305 needs           return IDL_NEEDS;
306 observes        return IDL_OBSERVES;
307 optional        return IDL_OPTIONAL;
308 property        return IDL_PROPERTY;
309 raises          return IDL_RAISES;
310 readonly        return IDL_READONLY;
311 removable       return IDL_REMOVABLE;
312 service         return IDL_SERVICE;
313 sequence        return IDL_SEQUENCE;
314 singleton       return IDL_SINGLETON;
315 struct          return IDL_STRUCT;
316 transient       return IDL_TRANSIENT;
317 typedef         return IDL_TYPEDEF;
318 
319 any             return IDL_ANY;
320 boolean         return IDL_BOOLEAN;
321 byte            return IDL_BYTE;
322 char            return IDL_CHAR;
323 double          return IDL_DOUBLE;
324 float           return IDL_FLOAT;
325 hyper           return IDL_HYPER;
326 long            return IDL_LONG;
327 short           return IDL_SHORT;
328 string          return IDL_STRING;
329 type            return IDL_TYPE;
330 unsigned        return IDL_UNSIGNED;
331 void            return IDL_VOID;
332 
333 TRUE            return IDL_TRUE;
334 True            return IDL_TRUE;
335 FALSE           return IDL_FALSE;
336 False           return IDL_FALSE;
337 
338 in              return IDL_IN;
339 out             return IDL_OUT;
340 inout           return IDL_INOUT;
341 
342 get             return IDL_GET;
343 set             return IDL_SET;
344 
345 published       return IDL_PUBLISHED;
346 
347 "..."           return IDL_ELLIPSIS;
348 
349 ("-")?{INT_LITERAL}+(l|L|u|U)?    {
350                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
351             }
352 
353 ("-")?{OCT_LITERAL}+(l|L|u|U)?    {
354                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
355             }
356 
357 ("-")?{HEX_LITERAL}+(l|L|u|U)?    {
358                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
359             }
360 
361 ("-")?{DIGIT}+(e|E)(("+"|"-")?{DIGIT}+)?(f|F)?  |
362 ("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?        {
363                 yylval.dval = asciiToFloat( yytext );
364                 return IDL_FLOATING_PT_LITERAL;
365             }
366 
367 {IDENTIFIER}    {
368                 yylval.sval = new OString(yytext);
369                 return IDL_IDENTIFIER;
370             }
371 
372 \<\<    {
373         yylval.strval = yytext;
374         return IDL_LEFTSHIFT;
375     }
376 \>\>    {
377         yylval.strval = yytext;
378         return IDL_RIGHTSHIFT;
379     }
380 \:\:    {
381         yylval.strval = yytext;
382         return IDL_SCOPESEPARATOR;
383     }
384 
385 "/*"    {
386             BEGIN( COMMENT );
387             docu = OString();
388             beginLine = idlc()->getLineNumber();
389         }
390 
391 "/***"  {
392             BEGIN( COMMENT );
393             docu = OString();
394             beginLine = idlc()->getLineNumber();
395         }
396 
397 <COMMENT>[^*]+  {
398                 docu += OString(yytext);
399             }
400 
401 <COMMENT>"*"[^*/]+  {
402                 docu += OString(yytext);
403             }
404 
405 <COMMENT>"**"   {
406                 docu += OString(yytext);
407             }
408 
409 <COMMENT>[*]+"/"  {
410                 docu = docu.trim();
411                 sal_Int32 nIndex = 0;
412                 int count = 0;
413                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
414                 idlc()->setLineNumber( beginLine + count - 1);
415                 BEGIN( INITIAL );
416             }
417 
418 "/**"   {
419             BEGIN( DOCU );
420             docu = OString();
421             beginLine = idlc()->getLineNumber();
422         }
423 
424 <DOCU>[^*\n]+   {
425                 docu += OString(yytext);
426             }
427 
428 <DOCU>"\n"[ \t]*"*"{1}  {
429                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
430                 docu += OString("\n");
431             }
432 
433 <DOCU>"\n"  {
434                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
435                 docu += OString(yytext);
436             }
437 
438 <DOCU>"*"[^*^/\n]*  {
439                 docu += OString(yytext);
440             }
441 
442 <DOCU>"\n"[ \t]*"*/"    {
443                 docu = docu.trim();
444                 sal_Int32 nIndex = 0;
445                 int count = 0;
446                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
447                 idlc()->setLineNumber( beginLine + count - 1);
448                 if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 )
449                 {
450                     if ( 0 != nIndex &&
451                          (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
452                         ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
453                                                      "nested documentation strings are not allowed!");
454                 }
455                 idlc()->setDocumentation(docu);
456                 BEGIN( INITIAL );
457             }
458 
459 <DOCU>"*/"  {
460                 docu = docu.trim();
461                 sal_Int32 nIndex = 0;
462                 int count = 0;
463                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
464                 idlc()->setLineNumber( beginLine + count - 1);
465                 if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 )
466                 {
467                     if ( 0 != nIndex &&
468                          (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
469                         ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
470                                                      "nested documentation strings are not allowed!");
471                 }
472                 idlc()->setDocumentation(docu);
473                 BEGIN( INITIAL );
474             }
475 
476 "//"[^/]{1}.*"\n" {
477                 /* only a comment */
478                 OString docStr(yytext);
479                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
480                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
481                 docStr = docStr.trim();
482                 idlc()->incLineNumber();
483             }
484 
485 "///".*"\n"  {
486                 OString docStr(yytext);
487                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
488                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
489                 docStr = docStr.trim();
490                 idlc()->incLineNumber();
491                 idlc()->setDocumentation(docStr);
492             }
493 
494 .   return yytext[0];
495 
496 ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n    {
497     parseLineAndFile(yytext);
498 }
499 
500 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
501     parseLineAndFile(yytext);
502 }
503 
504 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
505     parseLineAndFile(yytext);
506 }
507 
508 ^#[ \t]*[0-9]*\n {
509     parseLineAndFile(yytext);
510 }
511 
512 ^#[ \t]*ident.*\n {
513     /* ignore cpp ident */
514     idlc()->incLineNumber();
515 }
516 
517 ^#[ \t]*pragma[ \t].*\n        {       /* remember pragma */
518     idlParsePragma(yytext);
519     idlc()->incLineNumber();
520 }
521 
522 %%
523 
524 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
525