Merge pull request #1844 from jrw972/monterey
[ACE_TAO.git] / TAO / TAO_IDL / be / be_helper.cpp
blob153a99add45cfcf21899745716794ff9eeefc74e
2 //=============================================================================
3 /**
4 * @file be_helper.cpp
6 * Provides helper classes to print generated code to the output
8 * @author Aniruddha Gokhale Improvements by Carlos O'Ryan
9 */
10 //=============================================================================
12 #include "be_helper.h"
13 #include "be_codegen.h"
14 #include "be_extern.h"
15 #include "ast_expression.h"
16 #include "idl_defines.h"
17 #include "utl_identifier.h"
18 #include "utl_idlist.h"
19 #include "utl_string.h"
20 #include "ace/OS_NS_string.h"
21 #include "ace/OS_NS_ctype.h"
22 #include "../../tao/Version.h"
24 static const char copyright[] =
25 "// -*- C++ -*-\n"
26 "/**\n"
27 " * Code generated by the The ACE ORB (TAO) IDL Compiler v" TAO_VERSION "\n"
28 " * TAO and the TAO IDL Compiler have been developed by:\n"
29 " * Center for Distributed Object Computing\n"
30 " * Washington University\n"
31 " * St. Louis, MO\n"
32 " * USA\n"
33 " * and\n"
34 " * Distributed Object Computing Laboratory\n"
35 " * University of California at Irvine\n"
36 " * Irvine, CA\n"
37 " * USA\n"
38 " * and\n"
39 " * Institute for Software Integrated Systems\n"
40 " * Vanderbilt University\n"
41 " * Nashville, TN\n"
42 " * USA\n"
43 " * https://www.isis.vanderbilt.edu/\n"
44 " *\n"
45 " * Information about TAO is available at:\n"
46 " * https://www.dre.vanderbilt.edu/~schmidt/TAO.html\n"
47 " **/";
49 TAO_NL::TAO_NL (void)
51 ACE_UNUSED_ARG (copyright);
54 TAO_NL_2::TAO_NL_2 (void)
56 ACE_UNUSED_ARG (copyright);
59 TAO_INDENT::TAO_INDENT (int do_now)
60 : do_now_ (do_now)
64 TAO_UNINDENT::TAO_UNINDENT (int do_now)
65 : do_now_ (do_now)
69 const TAO_NL be_nl;
70 const TAO_NL_2 be_nl_2;
71 const TAO_INDENT be_idt;
72 const TAO_INDENT be_idt_nl (1);
73 const TAO_UNINDENT be_uidt;
74 const TAO_UNINDENT be_uidt_nl (1);
76 // Methods of the TAO_OutStream class.
78 TAO_OutStream::TAO_OutStream (void)
79 : fp_ (0),
80 st_ (TAO_CLI_HDR),
81 indent_level_ (0)
83 for (unsigned long i = 0; i < be_global->tab_size (); ++i)
85 this->tab_unit_str_ += ' ';
89 TAO_OutStream::~TAO_OutStream (void)
91 // Close the underlying I/O handle only if it exists.
92 if (this->fp_ != 0)
94 ACE_OS::fclose (this->fp_);
95 this->fp_ = 0;
98 indent_level_ = 0;
102 TAO_OutStream::open (const char *fname,
103 TAO_OutStream::STREAM_TYPE st)
105 if (fname != 0)
107 // File name exists, open an I/O file handle.
108 this->fp_ = ACE_OS::fopen (fname, "w");
110 if (this->fp_ != 0)
112 this->st_ = st;
113 // Put the copyright notice. Not for the gperf's temp input
114 // file.
115 if (st != TAO_OutStream::TAO_GPERF_INPUT)
117 ACE_OS::fprintf (this->fp_,
118 "%s\n",
119 copyright);
122 return 0;
124 else
126 return -1;
129 else
131 return -1;
135 // Set and get the stream type.
136 void
137 TAO_OutStream::stream_type (TAO_OutStream::STREAM_TYPE st)
139 this->st_ = st;
142 TAO_OutStream::STREAM_TYPE
143 TAO_OutStream::stream_type (void)
145 return this->st_;
148 // Return the underlying lowlevel file pointer.
149 // indentation.
150 FILE *&
151 TAO_OutStream::file (void)
153 return this->fp_;
157 TAO_OutStream::incr_indent (unsigned short flag)
159 ++indent_level_;
161 if (flag != 0)
163 return this->indent ();
165 else
167 // Do not indent output.
168 return 0;
172 // Indentation
174 TAO_OutStream::decr_indent (unsigned short flag)
176 --this->indent_level_;
177 // Just in case somebody gets "unindent happy".
178 if (this->indent_level_ < 0)
180 // ACE_DEBUG ((LM_DEBUG, "negative indentation?\n"));
181 this->indent_level_ = 0;
183 if (flag != 0)
185 return this->indent ();
187 else
189 // Do not indent output.
190 return 0;
195 TAO_OutStream::reset (void)
197 this->indent_level_ = 0;
198 return 0;
201 // Indented print.
203 TAO_OutStream::indent (void)
205 // Based on the current indentation level, leave appropriate number of blank
206 // spaces in the output.
207 if (this->indent_level_ > 0)
209 for (int i = 0; i < this->indent_level_; i++)
211 ACE_OS::fprintf (this->fp_, "%s", this->tab_unit_str_.c_str ());
215 return 0;
219 TAO_OutStream::nl (void)
221 ACE_OS::fprintf (this->fp_, "\n");
222 this->indent ();
223 return 0;
226 // Macro generation.
228 TAO_OutStream::gen_ifdef_macro (const char *flat_name,
229 const char *suffix,
230 bool add_stream_type_suffix)
232 static char macro [NAMEBUFSIZE];
234 ACE_OS::memset (macro,
235 '\0',
236 NAMEBUFSIZE);
238 ACE_OS::sprintf (macro,
239 "_%s_",
240 tao_cg->upcase (flat_name));
242 if (suffix != 0)
244 ACE_OS::strcat (macro, "_");
245 ACE_OS::strcat (macro, tao_cg->upcase (suffix));
246 ACE_OS::strcat (macro, "_");
249 // Append a suffix representing the stream type.
250 if (add_stream_type_suffix)
252 switch (this->st_)
254 case TAO_OutStream::TAO_CLI_HDR:
255 ACE_OS::strcat (macro, "CH_");
256 break;
257 case TAO_OutStream::TAO_CLI_INL:
258 ACE_OS::strcat (macro, "CI_");
259 break;
260 case TAO_OutStream::TAO_CLI_IMPL:
261 ACE_OS::strcat (macro, "CS_");
262 break;
263 case TAO_OutStream::TAO_SVR_HDR:
264 ACE_OS::strcat (macro, "SH_");
265 break;
266 case TAO_OutStream::TAO_IMPL_HDR:
267 ACE_OS::strcat (macro, "IH_");
268 break;
269 case TAO_OutStream::TAO_IMPL_SKEL:
270 ACE_OS::strcat (macro, "IS_");
271 break;
272 case TAO_OutStream::TAO_SVR_INL:
273 ACE_OS::strcat (macro, "SI_");
274 break;
275 case TAO_OutStream::TAO_SVR_IMPL:
276 ACE_OS::strcat (macro, "SS_");
277 break;
278 default:
279 return -1;
283 *this << "\n\n#if !defined (" << macro << ")\n";
284 *this << "#define " << macro;
286 return 0;
290 TAO_OutStream::gen_endif (void)
292 *this << "\n\n#endif /* end #if !defined */";
294 return 0;
297 // Printf style variable argument print.
299 TAO_OutStream::print (const char *format, ...)
301 int result = 0;
302 va_list ap;
303 va_start (ap, format);
304 ACE_OSCALL (::vfprintf (this->fp_,
305 format,
306 ap),
307 int,
309 result);
310 va_end (ap);
312 return result;
315 TAO_OutStream &
316 TAO_OutStream::operator<< (const char *str)
318 ACE_OS::fprintf (this->fp_, "%s", str);
319 return *this;
322 TAO_OutStream &
323 TAO_OutStream::operator<< (char ch)
325 ACE_OS::fprintf (this->fp_, "%c", ch);
326 return *this;
329 TAO_OutStream &
330 TAO_OutStream::operator<< (const ACE_CString &str)
332 ACE_OS::fprintf (this->fp_, "%s", str.c_str ());
333 return *this;
336 TAO_OutStream &
337 TAO_OutStream::operator<< (const ACE_CDR::UShort num)
339 ACE_OS::fprintf (this->fp_,
340 "%hu",
341 num);
343 return *this;
346 TAO_OutStream &
347 TAO_OutStream::operator<< (const ACE_CDR::Short num)
349 ACE_OS::fprintf (this->fp_,
350 "%hd",
351 num);
353 return *this;
356 TAO_OutStream &
357 TAO_OutStream::operator<< (const ACE_CDR::ULong num)
359 ACE_OS::fprintf (this->fp_,
360 "%lu",
361 (unsigned long) num);
363 return *this;
366 TAO_OutStream &
367 TAO_OutStream::operator<< (const ACE_CDR::Long num)
369 ACE_OS::fprintf (this->fp_,
370 "%ld",
371 (long) num);
373 return *this;
376 TAO_OutStream &
377 TAO_OutStream::operator<< (const ACE_CDR::ULongLong num)
379 ACE_OS::fprintf (this->fp_,
380 ACE_UINT64_FORMAT_SPECIFIER_ASCII,
381 num);
383 return *this;
386 TAO_OutStream &
387 TAO_OutStream::operator<< (const ACE_CDR::LongLong num)
389 ACE_OS::fprintf (this->fp_,
390 ACE_INT64_FORMAT_SPECIFIER_ASCII,
391 num);
393 return *this;
396 TAO_OutStream &
397 TAO_OutStream::operator<< (const TAO_NL&)
399 ACE_OS::fprintf (this->fp_ ,
400 "\n");
401 this->indent ();
403 return *this;
406 TAO_OutStream &
407 TAO_OutStream::operator<< (const TAO_NL_2&)
409 ACE_OS::fprintf (this->fp_ ,
410 "\n");
411 ACE_OS::fprintf (this->fp_ ,
412 "\n");
413 this->indent ();
414 return *this;
417 TAO_OutStream &
418 TAO_OutStream::operator<< (const TAO_INDENT& i)
420 this->incr_indent (0);
422 if (i.do_now_)
424 this->nl ();
427 return *this;
430 TAO_OutStream &
431 TAO_OutStream::operator<< (const TAO_UNINDENT& i)
433 this->decr_indent (0);
435 if (i.do_now_)
437 this->nl ();
440 return *this;
443 TAO_OutStream &
444 TAO_OutStream::operator<< (Identifier *id)
446 return this->print (id);
449 TAO_OutStream &
450 TAO_OutStream::operator<< (UTL_IdList *id)
452 return this->print (id);
455 TAO_OutStream &
456 TAO_OutStream::operator<< (AST_Expression *expr)
458 return this->print (expr);
461 TAO_OutStream &
462 TAO_OutStream::print (Identifier *id)
464 ACE_OS::fprintf (this->fp_, "%s", id->get_string ());
466 return *this;
469 TAO_OutStream &
470 TAO_OutStream::print (UTL_IdList *idl)
472 bool first = true;
473 bool second = false;
474 Identifier *id = 0;
476 for (UTL_IdListActiveIterator i (idl); !i.is_done (); i.next ())
478 if (!first)
480 *this << "::";
482 else if (second)
484 first = second = false;
487 // Print the identifier.
488 id = i.item ();
489 *this << id;
491 if (first)
493 if (ACE_OS::strcmp (id->get_string (), "") != 0
494 && ACE_OS::strcmp (id->get_string (), "::") != 0)
496 // Does not start with a "".
497 first = false;
499 else
501 second = true;
506 return *this;
509 template <typename IntType>
510 void
511 signed_int_helper (TAO_OutStream &os, IntType value, IntType min, const char *specifier)
514 * It seems that in C/C++ the minus sign and the bare number are parsed
515 * separately for negative integer literals. This can cause compilers
516 * to complain when using the minimum value of a signed integer because
517 * the number without the minus sign is 1 past the max signed value.
519 * https://stackoverflow.com/questions/65007935
521 * Apparently the workaround is to write it as `VALUE_PLUS_ONE - 1`.
523 const bool min_value = value == min;
524 if (min_value) ++value;
525 os.print (specifier, value);
526 if (min_value) os.print (" - 1");
529 TAO_OutStream&
530 TAO_OutStream::print (AST_Expression *expr)
532 AST_Expression::AST_ExprValue *ev = expr->ev ();
534 /// Never happens as far as I know, but just in case...
535 if (ev == 0)
537 ACE_ERROR ((LM_ERROR,
538 ACE_TEXT ("TAO_OutStream::print() - ")
539 ACE_TEXT ("expression not evaluated\n")));
541 return *this;
544 switch (ev->et)
546 case AST_Expression::EV_short:
547 this->TAO_OutStream::print (ACE_INT32_FORMAT_SPECIFIER_ASCII, ev->u.sval);
548 break;
549 case AST_Expression::EV_ushort:
550 this->TAO_OutStream::print (ACE_INT32_FORMAT_SPECIFIER_ASCII "%c", ev->u.usval, 'U');
551 break;
552 case AST_Expression::EV_long:
553 signed_int_helper<ACE_CDR::Long> (
554 *this, ev->u.lval, ACE_INT32_MIN, ACE_INT32_FORMAT_SPECIFIER_ASCII);
555 break;
556 case AST_Expression::EV_ulong:
557 this->TAO_OutStream::print (ACE_UINT32_FORMAT_SPECIFIER_ASCII "%c", ev->u.ulval, 'U');
558 break;
559 case AST_Expression::EV_longlong:
560 this->TAO_OutStream::print ("ACE_INT64_LITERAL (");
561 signed_int_helper<ACE_CDR::LongLong> (
562 *this, ev->u.llval, ACE_INT64_MIN, ACE_INT64_FORMAT_SPECIFIER_ASCII);
563 this->TAO_OutStream::print (")");
564 break;
565 case AST_Expression::EV_ulonglong:
566 this->TAO_OutStream::print ("ACE_UINT64_LITERAL (");
567 this->TAO_OutStream::print (ACE_UINT64_FORMAT_SPECIFIER_ASCII,
568 ev->u.ullval);
569 this->TAO_OutStream::print (")");
570 break;
571 case AST_Expression::EV_float:
572 this->TAO_OutStream::print ("%f%c", ev->u.fval, 'F');
573 break;
574 case AST_Expression::EV_double:
575 this->TAO_OutStream::print ("%24.16G", ev->u.dval);
576 break;
577 case AST_Expression::EV_longdouble:
578 break;
579 case AST_Expression::EV_char:
580 // isprint() sees \ and ' as printable characters
581 // so we have to test for them first.
582 if (ev->u.cval == '\\')
583 this->TAO_OutStream::print ("'\\\\'");
584 else if (ev->u.cval == '\'')
585 this->TAO_OutStream::print ("'\\''");
587 // This handles hex and octal escape sequences
588 // that would print out as weird characters.
589 else if (ACE_OS::ace_isprint (ev->u.cval))
590 this->TAO_OutStream::print ("'%c'", ev->u.cval);
591 else if (ACE_OS::ace_iscntrl (ev->u.cval))
592 switch (ev->u.cval)
594 case '\n':
595 this->TAO_OutStream::print ("'\\n'");
596 break;
597 case '\t':
598 this->TAO_OutStream::print ("'\\t'");
599 break;
600 case '\r':
601 this->TAO_OutStream::print ("'\\r'");
602 break;
603 case '\v':
604 this->TAO_OutStream::print ("'\\v'");
605 break;
606 case '\f':
607 this->TAO_OutStream::print ("'\\f'");
608 break;
609 case '\b':
610 this->TAO_OutStream::print ("'\\b'");
611 break;
612 case '\a':
613 this->TAO_OutStream::print ("'\\a'");
614 break;
615 case '\?':
616 this->TAO_OutStream::print ("'?'");
617 break;
618 default:
619 this->TAO_OutStream::print ("'\\x%x'", ev->u.oval);
621 else
622 this->TAO_OutStream::print ("'\\x%x'", ev->u.oval);
623 break;
624 case AST_Expression::EV_wchar:
625 this->TAO_OutStream::print ("L'%lc'", ev->u.wcval);
626 break;
627 case AST_Expression::EV_octet:
628 this->TAO_OutStream::print ("0x%02x", ev->u.oval);
629 break;
630 case AST_Expression::EV_bool:
631 this->TAO_OutStream::print ("%s", ev->u.bval ? "true" : "false");
632 break;
633 case AST_Expression::EV_string:
634 this->TAO_OutStream::print ("\"%s\"", ev->u.strval->get_string ());
635 break;
636 case AST_Expression::EV_wstring:
637 this->TAO_OutStream::print ("L\"%s\"", ev->u.wstrval);
638 break;
639 case AST_Expression::EV_enum:
640 this->print (expr->n ());
641 break;
642 case AST_Expression::EV_int8:
643 this->TAO_OutStream::print ("%d", ev->u.int8val);
644 break;
645 case AST_Expression::EV_uint8:
646 this->TAO_OutStream::print ("%uu", ev->u.uint8val);
647 break;
648 default:
649 break;
652 return *this;
655 void TAO_OutStream::insert_comment (const char *file, int line)
657 *this << be_nl << "// TAO_IDL - Generated from" << be_nl
658 << "// " << file << ':' << static_cast<ACE_CDR::ULong> (line)
659 << be_nl_2;