Changes to attempt to silence bcc64x
[ACE_TAO.git] / TAO / TAO_IDL / be / be_helper.cpp
blobec79ce3ee3bf8525ed46d006d3c85099c45bce61
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 ()
51 ACE_UNUSED_ARG (copyright);
54 TAO_NL_2::TAO_NL_2 ()
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 ()
79 : fp_ (nullptr),
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 ()
91 // Close the underlying I/O handle only if it exists.
92 if (this->fp_ != nullptr)
94 ACE_OS::fclose (this->fp_);
95 this->fp_ = nullptr;
98 indent_level_ = 0;
102 TAO_OutStream::open (const char *fname,
103 TAO_OutStream::STREAM_TYPE st)
105 if (fname != nullptr)
107 // File name exists, open an I/O file handle.
108 this->fp_ = ACE_OS::fopen (fname, "w");
110 if (this->fp_ != nullptr)
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 ()
145 return this->st_;
148 // Return the underlying lowlevel file pointer.
149 // indentation.
150 FILE *&
151 TAO_OutStream::file ()
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 ()
197 this->indent_level_ = 0;
198 return 0;
201 // Indented print.
203 TAO_OutStream::indent ()
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 ()
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 != nullptr)
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 ()
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,
308 result);
309 va_end (ap);
311 return result;
314 TAO_OutStream &
315 TAO_OutStream::operator<< (const char *str)
317 ACE_OS::fprintf (this->fp_, "%s", str);
318 return *this;
321 TAO_OutStream &
322 TAO_OutStream::operator<< (char ch)
324 ACE_OS::fprintf (this->fp_, "%c", ch);
325 return *this;
328 TAO_OutStream &
329 TAO_OutStream::operator<< (const ACE_CString &str)
331 ACE_OS::fprintf (this->fp_, "%s", str.c_str ());
332 return *this;
335 TAO_OutStream &
336 TAO_OutStream::operator<< (const ACE_CDR::UShort num)
338 ACE_OS::fprintf (this->fp_,
339 "%hu",
340 num);
342 return *this;
345 TAO_OutStream &
346 TAO_OutStream::operator<< (const ACE_CDR::Short num)
348 ACE_OS::fprintf (this->fp_,
349 "%hd",
350 num);
352 return *this;
355 TAO_OutStream &
356 TAO_OutStream::operator<< (const ACE_CDR::ULong num)
358 ACE_OS::fprintf (this->fp_,
359 "%lu",
360 (unsigned long) num);
362 return *this;
365 TAO_OutStream &
366 TAO_OutStream::operator<< (const ACE_CDR::Long num)
368 ACE_OS::fprintf (this->fp_,
369 "%ld",
370 (long) num);
372 return *this;
375 TAO_OutStream &
376 TAO_OutStream::operator<< (const ACE_CDR::ULongLong num)
378 ACE_OS::fprintf (this->fp_,
379 ACE_UINT64_FORMAT_SPECIFIER_ASCII,
380 num);
382 return *this;
385 TAO_OutStream &
386 TAO_OutStream::operator<< (const ACE_CDR::LongLong num)
388 ACE_OS::fprintf (this->fp_,
389 ACE_INT64_FORMAT_SPECIFIER_ASCII,
390 num);
392 return *this;
395 TAO_OutStream &
396 TAO_OutStream::operator<< (const TAO_NL&)
398 ACE_OS::fprintf (this->fp_ ,
399 "\n");
400 this->indent ();
402 return *this;
405 TAO_OutStream &
406 TAO_OutStream::operator<< (const TAO_NL_2&)
408 ACE_OS::fprintf (this->fp_ ,
409 "\n");
410 ACE_OS::fprintf (this->fp_ ,
411 "\n");
412 this->indent ();
413 return *this;
416 TAO_OutStream &
417 TAO_OutStream::operator<< (const TAO_INDENT& i)
419 this->incr_indent (0);
421 if (i.do_now_)
423 this->nl ();
426 return *this;
429 TAO_OutStream &
430 TAO_OutStream::operator<< (const TAO_UNINDENT& i)
432 this->decr_indent (0);
434 if (i.do_now_)
436 this->nl ();
439 return *this;
442 TAO_OutStream &
443 TAO_OutStream::operator<< (Identifier *id)
445 return this->print (id);
448 TAO_OutStream &
449 TAO_OutStream::operator<< (UTL_IdList *id)
451 return this->print (id);
454 TAO_OutStream &
455 TAO_OutStream::operator<< (AST_Expression *expr)
457 return this->print (expr);
460 TAO_OutStream &
461 TAO_OutStream::print (Identifier *id)
463 ACE_OS::fprintf (this->fp_, "%s", id->get_string ());
465 return *this;
468 TAO_OutStream &
469 TAO_OutStream::print (UTL_IdList *idl)
471 bool first = true;
472 bool second = false;
473 Identifier *id = nullptr;
475 for (UTL_IdListActiveIterator i (idl); !i.is_done (); i.next ())
477 if (!first)
479 *this << "::";
481 else if (second)
483 first = second = false;
486 // Print the identifier.
487 id = i.item ();
488 *this << id;
490 if (first)
492 if (ACE_OS::strcmp (id->get_string (), "") != 0
493 && ACE_OS::strcmp (id->get_string (), "::") != 0)
495 // Does not start with a "".
496 first = false;
498 else
500 second = true;
505 return *this;
508 template <typename IntType>
509 void
510 signed_int_helper (TAO_OutStream &os, IntType value, IntType min, const char *specifier)
513 * It seems that in C/C++ the minus sign and the bare number are parsed
514 * separately for negative integer literals. This can cause compilers
515 * to complain when using the minimum value of a signed integer because
516 * the number without the minus sign is 1 past the max signed value.
518 * https://stackoverflow.com/questions/65007935
520 * Apparently the workaround is to write it as `VALUE_PLUS_ONE - 1`.
522 const bool min_value = value == min;
523 if (min_value) ++value;
524 os.print (specifier, value);
525 if (min_value) os.print (" - 1");
528 TAO_OutStream&
529 TAO_OutStream::print (AST_Expression *expr)
531 AST_Expression::AST_ExprValue *ev = expr->ev ();
533 /// Never happens as far as I know, but just in case...
534 if (ev == nullptr)
536 ACE_ERROR ((LM_ERROR,
537 ACE_TEXT ("TAO_OutStream::print() - ")
538 ACE_TEXT ("expression not evaluated\n")));
540 return *this;
543 switch (ev->et)
545 case AST_Expression::EV_short:
546 this->TAO_OutStream::print (ACE_INT32_FORMAT_SPECIFIER_ASCII, ev->u.sval);
547 break;
548 case AST_Expression::EV_ushort:
549 this->TAO_OutStream::print (ACE_INT32_FORMAT_SPECIFIER_ASCII "%c", ev->u.usval, 'U');
550 break;
551 case AST_Expression::EV_long:
552 signed_int_helper<ACE_CDR::Long> (
553 *this, ev->u.lval, ACE_INT32_MIN, ACE_INT32_FORMAT_SPECIFIER_ASCII);
554 break;
555 case AST_Expression::EV_ulong:
556 this->TAO_OutStream::print (ACE_UINT32_FORMAT_SPECIFIER_ASCII "%c", ev->u.ulval, 'U');
557 break;
558 case AST_Expression::EV_longlong:
559 this->TAO_OutStream::print ("ACE_INT64_LITERAL (");
560 signed_int_helper<ACE_CDR::LongLong> (
561 *this, ev->u.llval, ACE_INT64_MIN, ACE_INT64_FORMAT_SPECIFIER_ASCII);
562 this->TAO_OutStream::print (")");
563 break;
564 case AST_Expression::EV_ulonglong:
565 this->TAO_OutStream::print ("ACE_UINT64_LITERAL (");
566 this->TAO_OutStream::print (ACE_UINT64_FORMAT_SPECIFIER_ASCII,
567 ev->u.ullval);
568 this->TAO_OutStream::print (")");
569 break;
570 case AST_Expression::EV_float:
571 this->TAO_OutStream::print ("%f%c", ev->u.fval, 'F');
572 break;
573 case AST_Expression::EV_double:
574 this->TAO_OutStream::print ("%24.16G", ev->u.dval);
575 break;
576 case AST_Expression::EV_longdouble:
577 break;
578 case AST_Expression::EV_char:
579 // isprint() sees \ and ' as printable characters
580 // so we have to test for them first.
581 if (ev->u.cval == '\\')
582 this->TAO_OutStream::print ("'\\\\'");
583 else if (ev->u.cval == '\'')
584 this->TAO_OutStream::print ("'\\''");
586 // This handles hex and octal escape sequences
587 // that would print out as weird characters.
588 else if (ACE_OS::ace_isprint (ev->u.cval))
589 this->TAO_OutStream::print ("'%c'", ev->u.cval);
590 else if (ACE_OS::ace_iscntrl (ev->u.cval))
591 switch (ev->u.cval)
593 case '\n':
594 this->TAO_OutStream::print ("'\\n'");
595 break;
596 case '\t':
597 this->TAO_OutStream::print ("'\\t'");
598 break;
599 case '\r':
600 this->TAO_OutStream::print ("'\\r'");
601 break;
602 case '\v':
603 this->TAO_OutStream::print ("'\\v'");
604 break;
605 case '\f':
606 this->TAO_OutStream::print ("'\\f'");
607 break;
608 case '\b':
609 this->TAO_OutStream::print ("'\\b'");
610 break;
611 case '\a':
612 this->TAO_OutStream::print ("'\\a'");
613 break;
614 case '\?':
615 this->TAO_OutStream::print ("'?'");
616 break;
617 default:
618 this->TAO_OutStream::print ("'\\x%x'", ev->u.oval);
620 else
621 this->TAO_OutStream::print ("'\\x%x'", ev->u.oval);
622 break;
623 case AST_Expression::EV_wchar:
624 this->TAO_OutStream::print ("L'%lc'", ev->u.wcval);
625 break;
626 case AST_Expression::EV_octet:
627 this->TAO_OutStream::print ("0x%02x", ev->u.oval);
628 break;
629 case AST_Expression::EV_bool:
630 this->TAO_OutStream::print ("%s", ev->u.bval ? "true" : "false");
631 break;
632 case AST_Expression::EV_string:
633 this->TAO_OutStream::print ("\"%s\"", ev->u.strval->get_string ());
634 break;
635 case AST_Expression::EV_wstring:
636 this->TAO_OutStream::print ("L\"%s\"", ev->u.wstrval);
637 break;
638 case AST_Expression::EV_enum:
639 this->print (expr->n ());
640 break;
641 case AST_Expression::EV_int8:
642 this->TAO_OutStream::print ("%d", ev->u.int8val);
643 break;
644 case AST_Expression::EV_uint8:
645 this->TAO_OutStream::print ("%uu", ev->u.uint8val);
646 break;
647 default:
648 break;
651 return *this;
654 void TAO_OutStream::insert_comment (const char *file, int line)
656 *this << be_nl << "// TAO_IDL - Generated from" << be_nl
657 << "// " << file << ':' << static_cast<ACE_CDR::ULong> (line)
658 << be_nl_2;