Synopsis - Cross-Reference

File: /Synopsis/Parsers/IDL/idl.ll
  1%{ // -*- c++ -*-
  2//                          Package   : omniidl
  3// idl.ll                   Created on: 1999/10/05
  4//			    Author    : Duncan Grisby (dpg1)
  5//
  6//    Copyright (C) 1999 AT&T Laboratories Cambridge
  7//
  8//  This file is part of omniidl.
  9//
 10//  omniidl is free software; you can redistribute it and/or modify it
 11//  under the terms of the GNU General Public License as published by
 12//  the Free Software Foundation; either version 2 of the License, or
 13//  (at your option) any later version.
 14//
 15//  This program is distributed in the hope that it will be useful,
 16//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 17//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18//  General Public License for more details.
 19//
 20//  You should have received a copy of the GNU General Public License
 21//  along with this program; if not, write to the Free Software
 22//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 23//  02111-1307, USA.
 24//
 25// Description:
 26//   
 27//   Flex lexical analyser
 28
 29// $Id: idl.ll,v 1.13.2.2 2005/01/06 23:11:14 dgrisby Exp $
 30// $Log: idl.ll,v $
 31// Revision 1.13.2.2  2005/01/06 23:11:14  dgrisby
 32// Big merge from omni4_0_develop.
 33//
 34// Revision 1.13.2.1  2003/03/23 21:01:48  dgrisby
 35// Start of omniORB 4.1.x development branch.
 36//
 37// Revision 1.9.2.8  2001/10/22 10:48:22  dpg1
 38// Cope with DOS line endings in all IDL situations.
 39//
 40// Revision 1.9.2.7  2001/10/17 16:48:32  dpg1
 41// Minor error message tweaks
 42//
 43// Revision 1.9.2.6  2001/06/13 11:28:20  dpg1
 44// Proper omniidl support for wchar/wstring constants.
 45//
 46// Revision 1.9.2.5  2001/03/13 10:32:10  dpg1
 47// Fixed point support.
 48//
 49// Revision 1.9.2.4  2000/11/01 12:45:55  dpg1
 50// Update to CORBA 2.4 specification.
 51//
 52// Revision 1.9.2.3  2000/10/27 16:31:07  dpg1
 53// Clean up of omniidl dependencies and types, from omni3_develop.
 54//
 55// Revision 1.9.2.2  2000/10/10 10:18:50  dpg1
 56// Update omniidl front-end from omni3_develop.
 57//
 58// Revision 1.7.2.8  2000/08/07 15:34:35  dpg1
 59// Partial back-port of long long from omni3_1_develop.
 60//
 61// Revision 1.7.2.7  2000/06/09 11:20:47  dpg1
 62// Last fix put __omni_pragma line numbers off by one...
 63//
 64// Revision 1.7.2.6  2000/06/08 14:58:19  dpg1
 65// Line numbers for #pragmas and // comments were off by one
 66//
 67// Revision 1.7.2.5  2000/06/08 14:36:19  dpg1
 68// Comments and pragmas are now objects rather than plain strings, so
 69// they can have file,line associated with them.
 70//
 71// Revision 1.7.2.4  2000/06/05 18:12:25  dpg1
 72// Support for __omni_pragma
 73//
 74// Revision 1.7.2.3  2000/04/26 09:55:48  dpg1
 75// cccp escapes characters like \ in line directives, so
 76// parseLineDirective() needs to use escapedStringToString().
 77//
 78// Revision 1.7.2.2  2000/03/06 15:03:49  dpg1
 79// Minor bug fixes to omniidl. New -nf and -k flags.
 80//
 81// Revision 1.7.2.1  2000/02/16 16:30:54  dpg1
 82// #pragma ID was misspelled #pragma id. Oops.
 83//
 84// Revision 1.7  2000/02/04 12:17:10  dpg1
 85// Support for VMS.
 86//
 87// Revision 1.6  1999/12/28 17:44:01  dpg1
 88// Stupid string allocation bug.
 89//
 90// Revision 1.5  1999/11/19 16:03:40  dpg1
 91// Flex scanner now accepts \r as whitespace.
 92//
 93// Revision 1.4  1999/11/05 10:36:42  dpg1
 94// Sorted out isatty() problems.
 95//
 96// Revision 1.3  1999/11/02 17:07:28  dpg1
 97// Changes to compile on Solaris.
 98//
 99// Revision 1.2  1999/11/01 10:05:00  dpg1
100// New file attribute to AST.
101//
102// Revision 1.1  1999/10/27 14:06:00  dpg1
103// *** empty log message ***
104//
105
106#define YY_NEVER_INTERACTIVE 1
107
108#include <stdlib.h>
109#include <string.h>
110#include <ctype.h>
111#include <errno.h>
112
113#include <idlerr.h>
114#include <idlutil.h>
115#include <idlrepoId.h>
116#include <idlscope.h>
117#include <idlexpr.h>
118#include <idlast.h>
119
120#include <y.tab.h>
121
122char*       currentFile;
123IDL_Boolean mainFile  = 1; // Are we processing the main file
124int         nestDepth = 0; // #include nesting depth
125
126char octalToChar(char* s);
127char hexToChar(char* s);
128char escapeToChar(char* s);
129IDL_UShort octalToWChar(char* s);
130IDL_UShort hexToWChar(char* s);
131IDL_UShort escapeToWChar(char* s);
132char* escapedStringToString(char* s);
133IDL_UShort* escapedStringToWString(char* s);
134void parseLineDirective(char* s);
135
136%}
137
138%option noyywrap
139%option yylineno
140
141%x comment
142%s known_pragma
143%x unknown_pragma
144%x omni_pragma
145
146WS          [ \t\v\n\f\r]
147SPACE       [ \t]
148
149ASCIILETTER [a-zA-Z]
150IDCHAR      [a-zA-Z0-9_]
151IDENT       ({ASCIILETTER}{IDCHAR}*)
152
153DECDIGIT    [0-9]
154DECSTART    [1-9]
155OCTSTART    0
156OCTDIGIT    [0-7]
157HEXSTART    (0[xX])
158HEXDIGIT    [0-9a-fA-F]
159
160EXPONENT    ([Ee][+-]?{DECDIGIT}+)
161
162STR         (\"([^\"]|\\\")*\")
163
164%%
165
166abstract        return ABSTRACT;
167any             return ANY;
168attribute       return ATTRIBUTE;
169boolean         return BOOLEAN;
170case            return CASE;
171char            return CHAR;
172const           return CONST;
173context         return CONTEXT;
174custom          return CUSTOM;
175default         return DEFAULT;
176double          return DOUBLE;
177enum            return ENUM;
178exception       return EXCEPTION;
179factory         return FACTORY;
180FALSE           return FALSE_;
181fixed           return FIXED;
182float           return FLOAT;
183in              return IN;
184inout           return INOUT;
185interface       return INTERFACE;
186local           return LOCAL;
187long            return LONG;
188module          return MODULE;
189native          return NATIVE;
190Object          return OBJECT;
191octet           return OCTET;
192oneway          return ONEWAY;
193out             return OUT;
194private         return PRIVATE;
195public          return PUBLIC;
196raises          return RAISES;
197readonly        return READONLY;
198sequence        return SEQUENCE;
199short           return SHORT;
200string          return STRING;
201struct          return STRUCT;
202supports        return SUPPORTS;
203switch          return SWITCH;
204TRUE            return TRUE_;
205truncatable     return TRUNCATABLE;
206typedef         return TYPEDEF;
207union           return UNION;
208unsigned        return UNSIGNED;
209ValueBase       return VALUEBASE;
210valuetype       return VALUETYPE;
211void            return VOID;
212wchar           return WCHAR;
213wstring         return WSTRING;
214
215"<<"            return LEFT_SHIFT;
216">>"            return RIGHT_SHIFT;
217"::"            return SCOPE_DELIM;
218
219{IDENT} {
220  yylval.id_val = idl_strdup(yytext);
221  return IDENTIFIER;
222}
223
224_{IDENT} {
225  yylval.id_val = idl_strdup(yytext);
226  return IDENTIFIER;
227}
228
229{DECSTART}{DECDIGIT}* {
230  errno = 0;
231  yylval.int_literal_val = idl_strtoul(yytext, 10);
232  if (errno == ERANGE) {
233    IdlError(currentFile, yylineno,
234	     "Integer literal '%s' is too big", yytext);
235  }
236  return INTEGER_LITERAL;
237}
238
239{OCTSTART}{OCTDIGIT}+ {
240  errno = 0;
241  yylval.int_literal_val = idl_strtoul(yytext, 8);
242  if (errno == ERANGE) {
243    IdlError(currentFile, yylineno,
244	     "Integer literal '%s' is too big", yytext);
245  }
246  return INTEGER_LITERAL;
247}
248
249{HEXSTART}{HEXDIGIT}+ {
250  errno = 0;
251  yylval.int_literal_val = idl_strtoul(yytext, 16);
252  if (errno == ERANGE) {
253    IdlError(currentFile, yylineno,
254	     "Integer literal '%s' is too big", yytext);
255  }
256  return INTEGER_LITERAL;
257}
258
259"0" {
260  yylval.int_literal_val = 0;
261  return INTEGER_LITERAL;
262}
263
264"'"."'" {
265  yylval.char_val = yytext[1];
266  return CHARACTER_LITERAL;
267}
268
269"'"\\([0-7]{1,3})"'" {
270  yytext[yyleng-1] = '\0';
271  yylval.char_val = octalToChar(yytext + 1);
272  return CHARACTER_LITERAL;
273}
274
275"'"\\x({HEXDIGIT}{1,2})"'" {
276  yytext[yyleng-1] = '\0';
277  yylval.char_val = hexToChar(yytext + 1);
278  return CHARACTER_LITERAL;
279}
280
281"'"\\u({HEXDIGIT}{1,4})"'" {
282  IdlError(currentFile, yylineno,
283	   "\\u may only be used in wide characters and strings");
284  yylval.char_val = 0;
285  return CHARACTER_LITERAL;
286}
287
288"'"\\."'" {
289  yytext[yyleng-1] = '\0';
290  yylval.char_val = escapeToChar(yytext + 1);
291  return CHARACTER_LITERAL;
292}
293
294L"'"."'" {
295  yylval.wchar_val = yytext[2];
296  return WIDE_CHARACTER_LITERAL;
297}
298
299L"'"\\([0-7]{1,3})"'" {
300  yytext[yyleng-1] = '\0';
301  yylval.wchar_val = octalToWChar(yytext + 2);
302  return WIDE_CHARACTER_LITERAL;
303}
304
305L"'"\\x({HEXDIGIT}{1,2})"'" {
306  yytext[yyleng-1] = '\0';
307  yylval.wchar_val = hexToWChar(yytext + 2);
308  return WIDE_CHARACTER_LITERAL;
309}
310
311L"'"\\u({HEXDIGIT}{1,4})"'" {
312  yytext[yyleng-1] = '\0';
313  yylval.wchar_val = hexToWChar(yytext + 2);
314  return WIDE_CHARACTER_LITERAL;
315}
316
317L"'"\\."'" {
318  yytext[yyleng-1] = '\0';
319  yylval.wchar_val = escapeToWChar(yytext + 2);
320  return WIDE_CHARACTER_LITERAL;
321}
322
323<INITIAL>{DECDIGIT}+{EXPONENT} {
324  // Only deal with floats in INITIAL state, so version pragmas don't
325  // get interpreted as floats.
326  yylval.float_literal_val = idl_strtod(yytext);
327  return FLOATING_PT_LITERAL;
328}
329
330<INITIAL>{DECDIGIT}*"."{DECDIGIT}+{EXPONENT}? {
331  yylval.float_literal_val = idl_strtod(yytext);
332  return FLOATING_PT_LITERAL;
333}
334
335<INITIAL>{DECDIGIT}+"."{DECDIGIT}*{EXPONENT}? {
336  yylval.float_literal_val = idl_strtod(yytext);
337  return FLOATING_PT_LITERAL;
338}
339
340{STR} {
341  yytext[yyleng-1] = '\0';
342  yylval.string_val = escapedStringToString(yytext + 1);
343  return STRING_LITERAL;
344}
345
346L{STR} {
347  yytext[yyleng-1] = '\0';
348  yylval.wstring_val = escapedStringToWString(yytext + 2);
349  return WIDE_STRING_LITERAL;
350}
351
352{DECDIGIT}+"."{DECDIGIT}*[dD] {
353  yylval.fixed_val = new IDL_Fixed(yytext, currentFile, yylineno);
354  return FIXED_PT_LITERAL;
355}
356
357{DECDIGIT}*"."{DECDIGIT}+[dD] {
358  yylval.fixed_val = new IDL_Fixed(yytext, currentFile, yylineno);
359  return FIXED_PT_LITERAL;
360}
361
362{DECDIGIT}+[dD] {
363  yylval.fixed_val = new IDL_Fixed(yytext, currentFile, yylineno);
364  return FIXED_PT_LITERAL;
365}
366
367"//".*\n { Comment::add(yytext, currentFile, yylineno-1); }
368
369"/*" {
370  Comment::add(yytext, currentFile, yylineno);
371  BEGIN(comment);
372}
373
374<comment>[^*\n]*      { Comment::append(yytext); }
375<comment>"*"+[^*/\n]* { Comment::append(yytext); }
376<comment>\n           { Comment::append(yytext); }
377<comment>"*"+"/"      { Comment::append(yytext); BEGIN(INITIAL); }
378
379"__omni_pragma"{WS}+ {
380  BEGIN(omni_pragma);
381  return OMNI_PRAGMA;
382}
383
384<omni_pragma>{WS}+"__omni_endpragma" {
385  BEGIN(INITIAL);
386  return END_PRAGMA;
387}
388
389<omni_pragma>[^ \t\v\n\f\r]+ {
390  yylval.string_val = idl_strdup(yytext);
391  return UNKNOWN_PRAGMA_BODY;
392}
393<omni_pragma>{WS}+ {
394  yylval.string_val = idl_strdup(yytext);
395  return UNKNOWN_PRAGMA_BODY;
396}
397
398
399^{SPACE}*#{SPACE}*pragma{SPACE}*prefix{SPACE}* {
400  BEGIN(known_pragma);
401  return PRAGMA_PREFIX;
402}
403
404^{SPACE}*#{SPACE}*pragma{SPACE}*ID{SPACE}* {
405  BEGIN(known_pragma);
406  return PRAGMA_ID;
407}
408
409^{SPACE}*#{SPACE}*pragma{SPACE}*version{SPACE}* {
410  BEGIN(known_pragma);
411  return PRAGMA_VERSION;
412}
413
414<known_pragma>{SPACE}+ { /* Eat spaces and tabs */ }
415
416^{SPACE}*#{SPACE}*pragma{SPACE}* {
417  BEGIN(unknown_pragma);
418  return PRAGMA;
419}
420
421<unknown_pragma>([^\\\n\r]|(\\[^\n\r]))+ {
422  yylval.string_val = idl_strdup(yytext);
423  return UNKNOWN_PRAGMA_BODY;
424}
425
426<INITIAL,known_pragma,unknown_pragma>\\(\n|(\r\n)) {
427  /* Continue line if it ends with \ */
428}
429
430<known_pragma,unknown_pragma>\n|(\r\n) {
431  BEGIN(INITIAL);
432  return END_PRAGMA;
433}
434
435^{SPACE}*#{SPACE}*{DECDIGIT}+{SPACE}+{STR}{SPACE}+{DECDIGIT}*{SPACE}*\n {
436  parseLineDirective(yytext);
437}
438
439^{SPACE}*#{SPACE}*{DECDIGIT}+{SPACE}+{STR}{SPACE}*\n {
440  parseLineDirective(yytext);
441}
442
443^{SPACE}*#{SPACE}*{DECDIGIT}{SPACE}*\n {
444  parseLineDirective(yytext);
445}
446
447^{SPACE}*#line{SPACE}*{DECDIGIT}+{SPACE}+{STR}{SPACE}+{DECDIGIT}*{SPACE}*\n {
448  parseLineDirective(yytext);
449}
450
451^{SPACE}*#line{SPACE}*{DECDIGIT}+{SPACE}+{STR}{SPACE}*\n {
452  parseLineDirective(yytext);
453}
454
455^{SPACE}*#line{SPACE}*{DECDIGIT}{SPACE}*\n {
456  parseLineDirective(yytext);
457}
458
459<INITIAL>{WS} { /* Eat white space */ }
460
461. {
462  return yytext[0];
463}
464
465%%
466
467char octalToChar(char* s) {
468  unsigned long ret = strtoul(s+1, 0, 8);
469
470  if (ret > 255) {
471    IdlError(currentFile, yylineno, "Octal character value '%s' too big", s);
472  }
473
474  return ret;
475}
476
477char hexToChar(char* s)  {
478  unsigned long ret = strtoul(s+2, 0, 16);
479
480  return ret;
481}
482
483char escapeToChar(char* s) {
484  switch (s[1]) {
485  case 'n':  return '\n';
486  case 't':  return '\t';
487  case 'v':  return '\v';
488  case 'b':  return '\b';
489  case 'r':  return '\r';
490  case 'f':  return '\f';
491  case 'a':  return '\a';
492  case '\\': return '\\';
493  case '?':  return '?';
494  case '\'': return '\'';
495  case '\"': return '\"';
496  }
497  IdlWarning(currentFile, yylineno,
498	     "Behaviour for escape sequence '%s' is undefined by IDL; "
499	     "using '%c'", s, s[1]);
500  return s[1];
501}
502
503IDL_UShort octalToWChar(char* s) {
504  unsigned long ret = strtoul(s+1, 0, 8);
505
506  if (ret > 255) { // This really is meant to be 255
507    IdlError(currentFile, yylineno, "Octal character value '%s' too big", s);
508  }
509
510  return ret;
511}
512
513IDL_UShort hexToWChar(char* s) {
514  unsigned long ret = strtoul(s+2, 0, 16);
515
516  return ret;
517}
518
519IDL_UShort escapeToWChar(char* s) {
520  switch (s[1]) {
521  case 'n':  return '\n';
522  case 't':  return '\t';
523  case 'v':  return '\v';
524  case 'b':  return '\b';
525  case 'r':  return '\r';
526  case 'f':  return '\f';
527  case 'a':  return '\a';
528  case '\\': return '\\';
529  case '?':  return '?';
530  case '\'': return '\'';
531  case '\"': return '\"';
532  }
533  IdlWarning(currentFile, yylineno,
534	     "Behaviour for escape sequence '%s' is undefined by IDL; "
535	     "using '%c'.", s, s[1]);
536  return s[1];
537}
538
539char* escapedStringToString(char* s) {
540  int   len = strlen(s);
541  char* ret = new char[len+1];
542  char  tmp[8];
543
544  int from, to, i;
545
546  for (from=0, to=0; from < len; from++, to++) {
547
548    if (s[from] == '\\') {
549      tmp[0] = s[from++];
550
551      if ('0' <= s[from] && s[from] <= '7') {
552	// Octal
553	for (i=1;
554	     i < 4 && from < len && '0' <= s[from] && s[from] <= '7';
555	     from++, i++) tmp[i] = s[from];
556
557	tmp[i]  = '\0';
558	ret[to] = octalToChar(tmp);
559	from--;
560      }
561      else if (s[from] == 'x') {
562	// Hex
563	tmp[1] = s[from++];
564	for (i=2; i < 4 && from < len && isxdigit(s[from]); from++, i++)
565	  tmp[i] = s[from];
566
567	tmp[i]  = '\0';
568	ret[to] = hexToChar(tmp);
569	from--;
570      }
571      else if (s[from] == 'u') {
572	// Wide hex not allowed
573	IdlError(currentFile, yylineno,
574		 "\\u may only be used in wide characters and strings");
575	ret[to] = '!';
576      }
577      else {
578	tmp[1]  = s[from];
579	tmp[2]  = '\0';
580	ret[to] = escapeToChar(tmp);
581      }
582      if (ret[to] == '\0') {
583	IdlError(currentFile, yylineno, "String cannot contain \\0");
584	ret[to] = '!';
585      }
586    }
587    else ret[to] = s[from];
588  }
589  ret[to] = '\0';
590  return ret;
591}
592
593IDL_UShort* escapedStringToWString(char* s) {
594  int         len = strlen(s);
595  IDL_UShort* ret = new IDL_UShort[len+1];
596  char        tmp[8];
597
598  int from, to, i;
599
600  for (from=0, to=0; from < len; from++, to++) {
601
602    if (s[from] == '\\') {
603      tmp[0] = s[from++];
604
605      if ('0' <= s[from] && s[from] <= '7') {
606	// Octal
607	for (i=1;
608	     i < 4 && from < len && '0' <= s[from] && s[from] <= '7';
609	     from++, i++) tmp[i] = s[from];
610
611	tmp[i]  = '\0';
612	ret[to] = octalToWChar(tmp);
613	from--;
614      }
615      else if (s[from] == 'x') {
616	// Hex
617	tmp[1] = s[from++];
618	for (i=2; i < 4 && from < len && isxdigit(s[from]); from++, i++)
619	  tmp[i] = s[from];
620
621	tmp[i]  = '\0';
622	ret[to] = hexToWChar(tmp);
623	from--;
624      }
625      else if (s[from] == 'u') {
626	// Wide hex
627	tmp[1] = s[from++];
628	for (i=2; i < 6 && from < len && isxdigit(s[from]); from++, i++)
629	  tmp[i] = s[from];
630
631	tmp[i]  = '\0';
632	ret[to] = hexToWChar(tmp);
633	from--;
634      }
635      else {
636	tmp[1]  = s[from];
637	tmp[2]  = '\0';
638	ret[to] = escapeToWChar(tmp);
639      }
640      if (ret[to] == 0) {
641	IdlError(currentFile, yylineno,
642		 "Wide string cannot contain wide character zero");
643	ret[to] = '!';
644      }
645    }
646    else
647      ret[to] = s[from];
648  }
649  ret[to] = 0;
650  return ret;
651}
652
653void parseLineDirective(char* s) {
654  char* file    = new char[strlen(s) + 1];
655  long int line = 0, mode = 0;
656  int cnt       = sscanf(s, "# %ld \"%[^\"]\" %ld", &line, file, &mode);
657  if (cnt == 0)
658    // Retry with a real "#line" directive.
659    cnt = sscanf(s, "#line %ld \"%[^\"]\" %ld", &line, file, &mode);
660  assert(cnt >= 1);
661
662  if (cnt > 1) {
663    if (cnt == 3) {
664      if (mode == 1) {
665	// New #included file
666	++nestDepth;
667	mainFile = 0;
668	Prefix::newFile();
669      }
670      else if (mode == 2) {
671	// Return from #include
672	if (--nestDepth == 0) mainFile = 1;
673	Prefix::endFile();
674      }
675    }
676    delete [] currentFile;
677    // cccp escapes \ characters, so use the normal string parser
678    currentFile = escapedStringToString(file);
679    delete [] file;
680    if (mainFile)
681      AST::tree()->setFile(currentFile);
682  }
683  yylineno = line;
684}