508eb6ba5490463b2757cbb915410e80d9c22d10
[charm.git] / src / xlat-idl / be_produce.cc
1 // BE_produce.cc - Produce the work of the BE - does nothing in the
2 //                 dummy BE
3
4 #include        "idl.hh"
5 #include        "idl_extern.hh"
6 #include        "be.hh"
7
8 //----------------------------------------------------------------------
9 // TO DO
10
11 // test single class generation - DONE
12 // implement multi-class generation - DONE
13 // debug multi-file hello type program
14 // test multiple classes in a file - DONE
15 // primitive types: char, [unsigned] short, [unsigned] long, float, double- DONE
16 // struct's - DONE
17 // nested types - DONE for structs, etc.
18 // simple arrays - design done, code it. - DONE
19 // parameter passing: in, out, inout - design done, code it. - DONE
20 //   use futures to get back a value - DONE
21 // constructors - DONE
22 // can a constructor have inout parameters ? NO.  Why not ?
23 // Do we need to inherit ?  class myClass1 /*: public chare_object*/ {
24 // no, since user uses only stub, never the class.
25 // threaded keyword - DONE
26 // Actually, the word is just ignored; the user has to create a .ci
27 // file with the threaded stuff.
28
29 // intermixing itc++ and idl++ example
30
31 // const's - DONE
32 // enums - DONE, bug: spews twice, why ?
33
34 // return values
35 // cleanup M_Empty
36 // cleanup unnecessary params in return messages
37
38 // which items are used by the IDL, which items belong to the class
39 // being declared ?
40
41 // sequences: varsize arrays
42 // VARSIZE myClass1->myMethod1SETSIZE(-, 100, -)->myMethod1(a, b[], c)
43 // BOC's
44 // scoping
45 // structs within interfaces ?
46 // any - requires RTTI, right ?
47 // inheritance
48 // exceptions
49 // do away with user writing .ci file, idl need to understand message,
50 //   threaded.
51
52 //----------------------------------------------------------------------
53 #include <fstream.h>
54 #include <stdio.h>
55 #include <libgen.h>
56 #include <stdlib.h>
57
58 #include "idlString.hh"
59
60 const int MAX_STR_LEN = 10000;
61
62 #include<assert.h>
63
64 // Assumes s can grow to MAX_STR_LEN long.
65 // Basically, a safe form of strcat().
66 static void
67 string_append(char *const s, const char *const a)
68 {
69   assert( strlen(s) + strlen(a) < MAX_STR_LEN );
70   int i=0, j=0;
71   for(i = strlen(s), j=0; a[j]!='\0'; i++, j++)
72     s[i] = a[j];
73   s[i] = '\0';
74 }
75
76 static void
77 DebugPrint(char *s)
78 {
79   cerr << s << endl;
80 }
81
82 //----------------------------------------------------------------------
83 // Replace \1 by a1, \2 by a2, etc. in string b.  Sends output to
84 // outStream.
85 static void
86 spew(ostream& outStream, const char*b,
87      char *a1 = "ERROR", char *a2 = "ERROR",
88      char *a3 = "ERROR", char *a4 = "ERROR", char *a5 = "ERROR")
89 {
90   int i;
91   for(i=0; i<strlen(b); i++){
92     switch(b[i]){
93     case '\01':
94       outStream << a1;
95       break;
96     case '\02':
97       outStream << a2;
98       break;
99     case '\03':
100       outStream << a3;
101       break;
102     case '\04':
103       outStream << a4;
104       break;
105     case '\05':
106       outStream << a5;
107       break;
108     default:
109       outStream << b[i];
110     }
111   }
112 }
113
114 // Replace \1 by a1, \2 by a2, etc. in string b, and appends the
115 // result to outString.  Assumes outString is MAX_STR_LEN long.
116 static void
117 spew(char outString[], const char*b,
118      char *a1 = "ERROR", char *a2 = "ERROR",
119      char *a3 = "ERROR", char *a4 = "ERROR", char *a5 = "ERROR")
120 {
121   int eosi = strlen(outString); // one past end of string index
122   int i;
123   for(i=0; i<strlen(b); i++){
124     assert(eosi < MAX_STR_LEN-1);
125     switch(b[i]){
126     case '\01':
127       outString[eosi] = '\0';
128       string_append(outString, a1);
129       eosi += strlen(a1);
130       break;
131     case '\02':
132       outString[eosi] = '\0';
133       string_append(outString, a2);
134       eosi += strlen(a2);
135       break;
136     case '\03':
137       outString[eosi] = '\0';
138       string_append(outString, a3);
139       eosi += strlen(a3);
140       break;
141     case '\04':
142       outString[eosi] = '\0';
143       string_append(outString, a4);
144       eosi += strlen(a4);
145       break;
146     case '\05':
147       outString[eosi] = '\0';
148       string_append(outString, a5);
149       eosi += strlen(a5);
150       break;
151     default:
152       outString[eosi++] = b[i];
153     }
154   }
155 }
156
157 //----------------------------------------------------------------------
158 // Given "path/file.ext" we return "file".
159 // @@ Given "path/file.b.ext" we return "file.b".
160 // Caller must delete the returned string.
161 char *
162 get_basename_noextension(char *pathname)
163 {
164         char c = '/';
165         int i = 0;
166
167         for(i=strlen(pathname)-1; i>=0; i--)
168           if (pathname[i] == c)
169             break;
170         assert(i != 0);
171
172         i++;
173         char *basenm = new char[strlen(pathname) - i];
174
175         int j;
176         for(j=0; pathname[i]; i++, j++)
177           if (pathname[i] != '.')
178             basenm[j] = pathname[i];
179           else {
180             basenm[j] = '\0';
181             break;
182           }
183
184         cout << "MODULE " << basenm << endl;
185         return basenm;
186 }
187
188 // If the file is a/b/c/m.idl
189 //  we return a/b/c/m
190 // If the file is a/b/c/m.n.idl
191 //  we return a/b/c/m.n
192 // Caller must delete the returned string.
193 char *
194 get_fullname_noextension(char *pathname)
195 {
196         char c = '.';
197         int i = 0;
198
199         for(i=strlen(pathname)-1; i>=0; i--)
200           if (pathname[i] == c)
201             break;
202         assert(i != 0);
203
204         char *fullnm = new char[i+1];
205         strncpy(fullnm, pathname, i);
206         fullnm[i] = '\0';
207
208         return fullnm;
209 }
210
211 //----------------------------------------------------------------------
212 // Files to output to
213
214 ofstream *MESGH; // messages.h
215 ofstream *SKELH; // skeleton.h
216 ofstream *SKELC; // skeleton.C
217 ofstream *SKELCI; // front of skeleton.ci
218 ofstream *SKELCIREST; // tail of skeleton.ci
219 ofstream *STUBH; // stub.h
220 ofstream *STUBC; // stub.C
221 ofstream *STUBCI; // stub.ci
222 ofstream *STUBCIREST; // tail of stub.ci
223
224 // Global variables
225 char *fileBaseNameNoExt = 0;
226 char *fullNameNoExt = 0;
227
228 //----------------------------------------------------------------------
229 //This is the actual code that we output.  We use the spew function to
230 //replace \01, \02, etc. by the desired values.
231
232 // header stuff
233 const char *SKELHDR10 = // filename
234 "#ifndef \01_SKELETON_H\n"
235 "#define \01_SKELETON_H\n"
236 "// \01_skeleton.h\n"
237 "// The skeleton basically contains the class and forwards all messages\n"
238 "// received to it by invoking local function calls.\n"
239 "\n"
240 "//#include \"\01_messages.h\"\n"
241 "#include \"\01_skeleton.top.h\"\n"
242 "\n"
243 ;
244
245 // declare skeleton class and system-defined functions
246 const char *SKELHDR20 = // classname
247 "class \01_skeleton : public skel_object {\n"
248 "  private:\n"
249 "    \01 *myObj1;\n"
250 "\n"
251 "  public:\n"
252 "//    \01_skeleton(M_Empty *m);\n"
253 "    void delete_\01_skeleton(M_Empty *m);\n"
254 "\n"
255 ;
256
257 // declare user-defined functions
258 const char *SKELHDR30 = // method return type, name, message type
259 "    \01 \02(\03 *m);\n"
260 ;
261
262 // end classname
263 const char *SKELHDR40 =
264 "};\n"
265 ;
266
267 // end filename
268 const char *SKELHDR50 =
269 "\n"
270 "#endif\n"
271 ;
272
273 //----------------------------------------------------------------------
274
275 // header stuff
276 const char *SKELCEE10 = // filename
277 "// \01_skeleton.C\n"
278 "\n"
279 "#include \"\01_skeleton.h\"\n"
280 "\n"
281 ;
282
283 // define system-defined functions
284 const char *SKELCEE20 = // classname
285 "//----------------------------------------\n"
286 "void \01_skeleton::delete_\01_skeleton(M_Empty *m) {\n"
287 "  delete m;\n"
288 "}\n"
289 "\n"
290 ;
291
292 // define user-defined functions, call local object
293 // classname, methodname, message type, return type
294 const char *SKELCEE30 = 
295 "//----------------------------------------\n"
296 "\04 \01_skeleton::\02(\03 *m) {\n"
297 "  myObj1->\02("
298 ;
299
300 // define user-defined constructor, call local object
301 // classname, methodname, message type, return type
302 const char *SKELCEE35 = 
303 "//----------------------------------------\n"
304 "\04 \01_skeleton::\02(\03 *m) {\n"
305 "  myObj1 = new \05("
306 ;
307
308 // list arguments
309 const char *SKELCEE40 = // argument name
310 "m->\01"
311 ;
312
313 // list arguments
314 // const char *SKELCEE42 = // array argument name, size
315 // "m->\01[\02]"
316 // ;
317
318 // also introduce comma's between arguments
319 const char *SKELCEE45 = //
320 ", "
321 ;
322
323 // end parameters
324 const char *SKELCEE50 =
325 ");\n"
326 ;
327
328 // return value stuff
329 const char *SKELCEE52 = // return message type
330 "  \01 *mret = new (MsgIndex(\01)) \01;\n"
331 ;
332
333 // assign arguments to return message elements
334 const char *SKELCEE53 = // argument name
335 "  mret->\01 = m->\01;\n"
336 ;
337
338 // return message
339 const char *SKELCEE54 =
340 "  return mret;\n"
341 ;
342
343 // end method
344 const char *SKELCEE55 =
345 "  delete m;\n"
346 "}\n"
347 "\n"
348 ;
349
350 // end filename
351 const char *SKELCEE60 = // filename
352 "//----------------------------------------\n"
353 "#include \"\01_skeleton.bot.h\"\n"
354 ;
355
356 //----------------------------------------------------------------------
357
358 // header stuff
359 const char *SKELCI10 = // filename
360 "// \01_skeleton.ci\n"
361 "\n"
362 // @@ should be extern, but then we need message.ci
363 "message M_Empty;\n"
364 ;
365
366 // declare marshalling messages
367 const char *SKELCI20 = // message type
368 "message \01;\n"
369 "\n"
370 ;
371
372 // declare system-defined functions
373 const char *SKELCI30 = // class name
374 "chare \01_skeleton {\n"
375 "//  entry \01_skeleton(M_Empty *);\n"
376 "  entry delete_\01_skeleton(M_Empty *);\n"
377 "\n"
378 ;
379
380 // declare user-defined functions
381 const char *SKELCI40 = // operation name, message type, special return type
382 "  \03 entry \01(\02 *);\n"
383 ;
384
385 // end classname and filename
386 const char *SKELCI50 =
387 "};\n"
388 ;
389
390 //----------------------------------------------------------------------
391
392 // class specific messages
393
394 // header and system-defined stuff
395 const char *MESGOP10 = // filename
396 "#ifndef \01_MESSAGE_H\n"
397 "#define \01_MESSAGE_H\n"
398 "//#include \"ckdefs.h\"\n"
399 "//#include \"chare.h\"\n"
400 "//#include \"c++interface.h\"\n"
401 "#include \"charm++.h\"\n"
402 "\n"
403 "#ifndef COMMON_TEMPLATE\n"
404 "#define COMMON_TEMPLATE\n"
405 "template<class T>\n"
406 "void\n"
407 "copy_array(T to[], T from[], int size)\n"
408 "{\n"
409 "  for (int i=0; i < size; i++)\n"
410 "    to[i] = from[i];\n"
411 "};\n"
412 "#endif\n"
413 "\n"
414 "\n"
415 // @@ there should be a global messages file.
416 "#ifndef MESSAGE_H\n"
417 "#define MESSAGE_H\n"
418 "class skel_object;\n"
419 "class M_Empty;\n"
420 "// Right now contains nothing\n"
421 "class skel_object : public chare_object {\n"
422 "};\n"
423 "\n"
424 "class M_Empty : public comm_object {\n"
425 "};\n"
426 "#endif\n"
427 "\n"
428 "#include \"\01.h\"\n"
429 "\n"
430 ;
431
432 //define messages
433 const char *MESGOP20 = // messagename
434 "class \01 : public comm_object {\n"
435 "public:\n"
436 ;
437
438 const char *MESGOP30 = // argument type, name
439 "    \01 \02;\n"
440 ;
441
442 const char *MESGOP35 = // array argument type, name, size
443 "    \01 \02[\03];\n"
444 ;
445
446 // end messagename
447 const char *MESGOP40 =
448 "};\n"
449 ;
450
451 // end filename
452 const char *MESGOP50 =
453 "\n"
454 "#endif\n"
455 "\n"
456 ;
457
458 //----------------------------------------------------------------------
459 // @@ not yet implemented
460 const char *MESGCEE10 =
461 "\n"
462 "\n"
463 ;
464
465 //----------------------------------------------------------------------
466
467 // header stuff
468 const char *STUBHDR10 = // filename
469 "#ifndef \01_STUB_H\n"
470 "#define \01_STUB_H\n"
471 "\n"
472 "#include \"\01_skeleton.h\"\n"
473 "\n"
474 ;
475
476 // declare the stub class and system-defined functions
477 const char *STUBHDR20 = // classname
478 "class \01_stub : public chare_object {\n"
479 "  int shouldDelete; //virtual\n"
480 "  ChareIDType chare_Id; // virtual\n"
481 "public:\n"
482 "  \01_stub(int pe);\n"
483 "//  \01_stub(void);\n"
484 "  \01_stub(ChareIDType id);\n"
485 "  ~\01_stub(void);\n"
486 "  ChareIDType getGlobalID() { return chare_Id; }\n"
487 "\n"
488 ;
489
490 // declare user-defined functions
491 const char *STUBHDR30 = // method return type, name
492 "  \01 \02("
493 ;
494
495 // pass by value
496 const char *STUBHDR40 = // argument type
497 "\01 "
498 ;
499
500 // pass by reference
501 const char *STUBHDR41 = // argument type
502 "\01 &"
503 ;
504
505 const char *STUBHDR42 = // array argument type, size
506 "\01[\02] "
507 ;
508
509 // also introduce comma's between arguments
510 const char *STUBHDR45 =
511 ", "
512 ;
513
514 // end arguments
515 const char *STUBHDR50 =
516 ");\n"
517 ;
518
519 // declare system-defined helper function, if needed
520 const char *STUBHDR55 = // return message type with ptr, marshall message type,
521  // methodname
522 "  \01 \03helper(\02 *);\n"
523 ;
524
525 // end classname
526 const char *STUBHDR60 =
527 "};\n"
528 ;
529
530 // end filename
531 const char *STUBHDR70 =
532 "\n"
533 "#endif\n"
534 ;
535
536 //----------------------------------------------------------------------
537
538 // header stuff
539 const char *STUBCEE10 = // filename
540 "// \01_stub.C\n"
541 "\n"
542 "#include \"\01_stub.h\"\n"
543 "#include \"\01_skeleton.h\"\n"
544 "#include \"\01_stub.top.h\"\n"
545 "//#include \"charmFuturesInclude.h\"\n"
546 "\n"
547 ;
548
549 // define system-defined functions
550 const char *STUBCEE20 = // classname
551 "//\01_stub::\01_stub(int pe) {\n"
552 "//  // create new chare of type \01_skeleton on PE\n"
553 "//  // by sending a message of type M_Empty\n"
554 "//  // and store returned chareID in chareId;\n"
555 "//  M_Empty *msg = new (MsgIndex(M_Empty)) M_Empty;\n"
556 "//  new_chare2(\01_skeleton,M_Empty,msg,&chare_Id,pe);\n"
557 "//\n"
558 "//  shouldDelete = 1;\n"
559 "//}\n"
560 "\n"
561 "//\01_stub::\01_stub(void) {\n"
562 "//  // create new chare of type \01_skeleton on any PE\n"
563 "//  // by sending a message of type M_Empty\n"
564 "//  // and store returned chareID in chareId;\n"
565 "//  M_Empty *msg = new (MsgIndex(M_Empty)) M_Empty;\n"
566 "//  new_chare2(\01_skeleton,M_Empty,msg,&chare_Id,0);\n"
567 "//\n"
568 "//  shouldDelete = 1;\n"
569 "//}\n"
570 "\n"
571 "\01_stub::\01_stub(ChareIDType id) {\n"
572 "  chare_Id = id;\n"
573 "  shouldDelete = 0;\n"
574 "}\n"
575 "\n"
576 "\01_stub::~\01_stub(void) {\n"
577 "  if(shouldDelete) {\n"
578 "    //M_Empty *m = new (MsgIndex(M_Empty)) M_Empty;\n"
579 "    //CSendMsg(\01_skeleton, delete_\01_skeleton, m, &chare_Id);\n"
580 "  } else {\n"
581 "    // do nothing\n"
582 "  }\n"
583 "}\n"
584 "\n"
585 "//------------------------------\n"
586 ;
587
588 // begin to define user-defined function
589 const char *STUBCEE30 = // class name, method return type, method name
590 "\02 \01_stub::\03("
591 ;
592
593 // OR begin to define user-defined constructor
594 const char *STUBCEE35 = // classname
595 "\01_stub::\01_stub("
596 ;
597
598 // @@ make sure out/inout parameters are references
599
600 // list parameters
601 const char *STUBCEE40 = // argument type, name
602 "\01 \02"
603 ;
604
605 // list parameters,  pass by reference
606 const char *STUBCEE41 = // argument type, name
607 "\01 &\02"
608 ;
609
610 // list parameters
611 const char *STUBCEE42 = // array argument type, name, size
612 "\01 \02[\03]"
613 ;
614
615 // also introduce comma's between parameters
616 const char *STUBCEE45 = //
617 ", "
618 ;
619
620 // end parameters
621 const char *STUBCEE50 =
622 ") {\n"
623 ;
624
625 // begin function body
626 const char *STUBCEE60 = // class name, method name, message type
627 //"  // CPrintf(\"\01_stub::\02: Message received %f\\n\", arg0);\n"
628 "  \03 *m = new (MsgIndex(\03)) \03;\n"
629 ;
630
631 // // assign arguments to message elements
632 // const char *STUBCEE70 = // arguments
633 // "  m->%s = %s;\n"
634 // ;
635
636 // assign arguments to message elements
637 const char *STUBCEE71 = // arguments
638 "  m->\01 = \01;\n"
639 ;
640
641 // // assign arguments to message elements
642 // const char *STUBCEE75 = // arguments
643 // "  copy_array(m->%s, %s, %s);\n"
644 // ;
645
646 // assign array arguments to message elements
647 const char *STUBCEE76 = // argument name, array size
648 "  copy_array(m->\01, \01, \02);\n"
649 ;
650
651 // send off the asynchronous message
652 const char *STUBCEE80 = //class name,  method name
653 "  CSendMsg(\01_skeleton, \02, \03, m, &chare_Id);\n"
654 ;
655
656 // OR send off a synchronous message
657 const char *STUBCEE82 = // return message type, method name
658 "  \01 * result;\n"
659 "  result = \02helper(m);\n"
660 "\n"
661 ;
662
663 // assign return message elements to arguments 
664 const char *STUBCEE84 = // arguments
665 "  \01 = result->\01;\n"
666 ;
667
668 // assign array message elements to arguments
669 const char *STUBCEE86 = // argument name, array size
670 "  copy_array(\01, result->\01, \02);\n"
671 ;
672
673 // OR create the skeleton
674 const char *STUBCEE88 = //class name
675 // @@ what about specific PE's ?  We need to generate another constructor.
676 "  // create new chare of type \01_skeleton on PE\n"
677 "  // by sending a message of type M_Empty\n"
678 "  // and store returned chareID in chareId;\n"
679 "  new_chare2(\01_skeleton,\02,m,&chare_Id,0);\n"
680 "\n"
681 "  shouldDelete = 1;\n"
682 "\n"
683 ;
684
685 // end user-defined function
686 const char *STUBCEE90 =
687 "}\n"
688 ;
689
690 // if needed, helper function
691 const char *STUBCEE92 = // return message type, marshall message type,
692  // class name, method name
693 "\01 * \03_stub::\04helper(\02 *m) {\n"
694 "  \01 * result;\n"
695 "  result = (\01 *) CRemoteCall(\03_skeleton,\04,\02,m,&chare_Id);\n"
696 "  return result;\n"
697 "}\n"
698 "\n"
699 ;
700
701 // if needed, helper function without return type
702 const char *STUBCEE94 = // return message type (void), marshall message type,
703  // class name, method name
704 "\01 \03_stub::\04helper(\02 *m) {\n"
705 "  \01 result;\n"
706 "  result = (\01 *) CRemoteCallFn(GetEntryPtr(\03_skeleton,\n"
707 "                                                     \04, \02), m, &chare_Id);\n"
708 "  return result;\n"
709 "}\n"
710 "\n"
711 ;
712
713 // end
714 const char *STUBCEE95 = // filename
715 "\n"
716 "#include \"\01_stub.bot.h\"\n"
717 ;
718
719 //----------------------------------------------------------------------
720
721 // declare marshalling messages
722 const char *STUBCI20 = // message type
723 "extern message \01;\n"
724 ;
725
726 // declare system-defined functions
727 const char *STUBCI30 = // class name
728 "\n"
729 "chare \01_stub {\n"
730 ;
731
732 // declare system-defined helper function, if needed
733 const char *STUBCI40 = // operation name, message type, special return type
734 "  threaded \03 entry \01helper(\02 *);\n"
735 ;
736
737 // end classname and filename
738 const char *STUBCI50 =
739 "};\n"
740 ;
741
742 //----------------------------------------------------------------------
743
744 // Traverse the method's parameters.
745 // Output code for:
746 //   1. the marshall message
747 //   2. the stub function (.h, .C)
748 //   3. the skeleton.C local invocation of the method
749 void
750 BE_produce_parameters(be_operation *bop,
751                       char stubcPass1B[],
752                       char mesghPass2[],
753                       char skelcPass2[],
754                       char stubcPass2[])
755 {
756   UTL_ScopeActiveIterator   *i;
757   AST_Decl                  *d;
758
759   // @@ what about the return value ?
760
761   i = new UTL_ScopeActiveIterator(bop, UTL_Scope::IK_decls);
762   int argNum = -1;
763   while (!(i->is_done())) {
764     d = i->item();
765     argNum++;
766
767     if (d->node_type() == AST_Decl::NT_argument) {
768       be_argument *a = be_argument::narrow_from_decl(d);
769       //      cout << "NT_argument" << endl;
770       char argName[100];
771       sprintf(argName, "%s%d", "arg", argNum);
772
773       if (a->isArray()) {
774         be_array *ar = be_array::narrow_from_decl(a->field_type());
775
776         char *arrayType = ar->base_type()->local_name()->get_string();
777         unsigned long arraySizeNum = ar->dims()[0]->ev()->u.ulval;
778         char arraySize[100];
779         strcpy(arraySize,"");
780         sprintf(arraySize, "%u", arraySizeNum);
781         spew(*MESGH, MESGOP35, arrayType, argName, arraySize);
782         if (bop->isReturnMessageNeeded())
783           spew(mesghPass2, MESGOP35, arrayType, argName, arraySize);
784         spew(*SKELC, SKELCEE40, argName);
785         if (bop->isReturnMessageNeeded())
786           spew(skelcPass2, SKELCEE53, argName);
787         spew(*STUBH, STUBHDR42, arrayType, arraySize);
788         spew(*STUBC, STUBCEE42, arrayType, argName, arraySize);
789
790         //sprintf(ta, STUBCEE75, argName, argName, arraySize);
791         spew(stubcPass1B, STUBCEE76, argName, arraySize);
792         if (bop->isReturnMessageNeeded())
793           spew(stubcPass2, STUBCEE86, argName, arraySize);
794       } else {
795         char *argType = a->field_type()->local_name()->get_string();
796         spew(*MESGH, MESGOP30, argType, argName);
797         if (bop->isReturnMessageNeeded())
798           spew(mesghPass2, MESGOP30, argType, argName);
799         spew(*SKELC, SKELCEE40, argName);
800         if (bop->isReturnMessageNeeded())
801           spew(skelcPass2, SKELCEE53, argName);
802
803         // do we need to use pass by reference for the parameter
804         if(a->direction() == AST_Argument::dir_IN) {
805           spew(*STUBH, STUBHDR40, argType);
806           spew(*STUBC, STUBCEE40, argType, argName);
807         } else {
808           spew(*STUBH, STUBHDR41, argType);
809           spew(*STUBC, STUBCEE41, argType, argName);
810         }
811
812         //sprintf(ta, STUBCEE70, argName);
813         spew(stubcPass1B, STUBCEE71, argName);
814         if (bop->isReturnMessageNeeded())
815           spew(stubcPass2, STUBCEE84, argName);
816       }
817       //      string_append(stubcPass1B, ta);
818
819       //   o << direction_to_string(pd_direction) << " ";
820       //   AST_Field::dump(o);
821     } else {
822       cerr << "LIMIT: Only arguments within method parameter list\n";
823     }
824
825     i->next();
826     if (!(i->is_done())) { // output commas between parameters
827       spew(*SKELC, SKELCEE45);
828       spew(*STUBH, STUBHDR45);
829       spew(*STUBC, STUBCEE45);
830     }
831   }
832   delete i;
833
834 }
835
836 // There are three types of methods:
837 // - a constructor (no return values, creates a chare)
838 // - an asynchronous call (no return values)
839 // - a synchronous call (has a return value)
840 // Furthermore, the method may be non-threaded (default), or threaded.
841 void
842 BE_produce_operation(AST_Decl *d_in, AST_Interface *parent_interface)
843   /* An operation is basically a C++ method. */
844 {
845   //AST_Operation *op = AST_Operation::narrow_from_decl(d_in);
846   be_operation *bop = be_operation::narrow_from_decl(d_in);
847
848   if (bop->isConstructor())
849     cerr << "DEBUG: isConstructor ";
850
851   if (bop->isMarshallMessageNeeded())
852     cerr << "DEBUG: isMarshallMessageNeeded ";
853
854   if (bop->isReturnMessageNeeded())
855     cerr << "DEBUG: isReturnMessageNeeded ";
856
857   if (bop->isThreaded())
858     cerr << "DEBUG: isThreaded found thread" << endl;
859   else
860     cerr << endl;
861
862   ostream &o(cout);
863
864   UTL_ScopeActiveIterator   *i;
865   UTL_StrlistActiveIterator *si;
866   UTL_ExceptlistActiveIterator *ei;
867   AST_Decl                  *d;
868   AST_Exception             *e;
869   String                    *s;
870
871   // @@ if not threaded, set a flag to disallow use of futures in the function.
872 //   if (pd_flags == OP_oneway)
873 //     o << "oneway ";
874 //   else if (pd_flags == OP_idempotent)
875 //     o << "idempotent ";
876
877   char *classname = parent_interface->local_name()->get_string();
878   char *methodname = bop->local_name()->get_string();
879   char *skelmethodname = new char[MAX_STR_LEN];
880   strcpy(skelmethodname, methodname);
881   char *stubmethodname = new char[MAX_STR_LEN];
882   strcpy(stubmethodname, methodname);
883   // If we have a constructor myClass::myClass, we need to change the
884   // methodname to the constructor name for a stub and a skeleton.
885   if (bop->isConstructor()) {
886     strcat(skelmethodname, "_skeleton"); // in case of a ret mesg
887     strcat(stubmethodname, "_stub");
888   }
889
890   // Create a message to marshall the method's parameters in.
891   char marshallMesgTypeName[MAX_STR_LEN];
892   sprintf(marshallMesgTypeName, "M%sM%d", classname,
893           bop->getMarshallMessageNumber());
894   //  bop->p_marshallMesgTypeName = marshallMesgTypeName;
895
896   // @@ document this: if there is no return value, the caller must
897   // assume an asynchronous call was made to this function.
898
899   // @@ I added the local_
900   // Method's return type.
901   char *methodReturnTypeName = bop->return_type()->local_name()->get_string();
902   if (bop->isConstructor()) {
903     methodReturnTypeName = "";
904   }
905
906   // If needed, create a message to marshall the method's return
907   // parameters in.
908   char returnMarshallMesgTypeName[MAX_STR_LEN];
909   strcpy(returnMarshallMesgTypeName,"void");
910   char returnMarshallMesgTypeNameWithPtr[MAX_STR_LEN];
911   strcpy(returnMarshallMesgTypeNameWithPtr,"void");
912   if (bop->isConstructor()) {
913     strcpy(returnMarshallMesgTypeName,"");
914     strcpy(returnMarshallMesgTypeNameWithPtr,"");
915   } else if (bop->isReturnMessageNeeded()) { // either a retval, or a retarg
916     sprintf(returnMarshallMesgTypeName, "M%sM%d", classname, 
917             bop->getReturnMessageNumber());
918     sprintf(returnMarshallMesgTypeNameWithPtr, "M%sM%d *", classname, 
919             bop->getReturnMessageNumber());
920   } else {
921     // they're already void.
922   }
923
924   // Marshall, return messages
925   // We always have a marshalling message since charmxi expects one
926   spew(*MESGH, MESGOP20, marshallMesgTypeName);
927   spew(*SKELCI, SKELCI20, marshallMesgTypeName);
928   spew(*STUBCI, STUBCI20, marshallMesgTypeName);
929   char mesghPass2[MAX_STR_LEN];
930   strcpy(mesghPass2,"");
931   if (bop->isReturnMessageNeeded())
932     spew(mesghPass2, MESGOP20, returnMarshallMesgTypeName);
933
934   // Output the method's return type and name.
935   spew(*SKELH, SKELHDR30,
936        returnMarshallMesgTypeNameWithPtr, skelmethodname, marshallMesgTypeName);
937   if (bop->isConstructor())
938     spew(*SKELC, SKELCEE35,
939          classname, skelmethodname, marshallMesgTypeName, 
940          returnMarshallMesgTypeNameWithPtr, methodname);
941   else
942     spew(*SKELC, SKELCEE30,
943          classname, skelmethodname, marshallMesgTypeName, 
944          returnMarshallMesgTypeNameWithPtr);
945   char skelcPass2[MAX_STR_LEN];
946   strcpy(skelcPass2,"");
947   if (bop->isReturnMessageNeeded()) {
948      // create retmsg instance
949     spew(skelcPass2, SKELCEE52, returnMarshallMesgTypeName);
950     // declare helper function
951     spew(*STUBH, STUBHDR55, returnMarshallMesgTypeNameWithPtr,
952          marshallMesgTypeName, stubmethodname);
953   }
954
955   // declare user function
956   spew(*STUBH, STUBHDR30, methodReturnTypeName, stubmethodname);
957   spew(*STUBC, STUBCEE30, classname, methodReturnTypeName, stubmethodname);
958
959   if (bop->isReturnMessageNeeded()) {
960     // declare retmsg
961     spew(*SKELCI, SKELCI20, returnMarshallMesgTypeName);
962     spew(*STUBCI, STUBCI20, returnMarshallMesgTypeName);
963     // declare EP
964     spew(*SKELCIREST, SKELCI40, skelmethodname, marshallMesgTypeName,
965          returnMarshallMesgTypeNameWithPtr);
966     spew(*STUBCIREST, STUBCI40, stubmethodname, marshallMesgTypeName,
967          returnMarshallMesgTypeNameWithPtr);
968   } else {
969     // do not declare the stub ep since no stub helper function is needed.
970     spew(*SKELCIREST, SKELCI40, skelmethodname, marshallMesgTypeName, "");
971   }
972
973   // FIRST PASS
974
975   // Output the stuff for the parameters.
976   char stubcPass1B[MAX_STR_LEN];
977   strcpy(stubcPass1B,"");
978   char stubcPass2[MAX_STR_LEN];
979   strcpy(stubcPass2,"");
980   BE_produce_parameters(bop, stubcPass1B, mesghPass2, skelcPass2, stubcPass2);
981
982   // Output the closing stuff for the method, i.e. parentheses, etc.
983   spew(*SKELC, SKELCEE50);
984   spew(*MESGH, MESGOP40, classname);
985   spew(*STUBH, STUBHDR50);
986   spew(*STUBC, STUBCEE50);
987   spew(*STUBC, STUBCEE60,
988        classname, stubmethodname, marshallMesgTypeName);
989   spew(*STUBC, stubcPass1B);  // body of the method
990
991   if(!bop->isReturnMessageNeeded()/* && !bop->is_threaded()*/) // invoke the remote call to the skeleton
992     if (bop->isConstructor()) // constructor
993       spew(*STUBC, STUBCEE88, classname, marshallMesgTypeName);
994     else // async. message
995       spew(*STUBC, STUBCEE80, classname, skelmethodname, marshallMesgTypeName);
996   else // sync message
997     if (bop->isConstructor()) // constructor
998       spew(*STUBC, STUBCEE88, "ERROR", "ERROR"); // constructor cannot have retval @@ but it can be threaded, right ?
999     else
1000       spew(*STUBC, STUBCEE82, returnMarshallMesgTypeName, stubmethodname);
1001
1002   // SECOND PASS
1003   // rest of SKELC, STUBC, MESGH; i.e. return message stuff, if needed.
1004   if (bop->isReturnMessageNeeded()/* || bop->is_threaded()*/) {
1005     spew(mesghPass2, MESGOP40, classname);
1006     spew(skelcPass2, SKELCEE54);
1007   }
1008   spew(*MESGH, mesghPass2); 
1009   spew(*SKELC, skelcPass2);
1010   spew(*STUBC, stubcPass2);
1011
1012   spew(*SKELC, SKELCEE55);
1013   spew(*STUBC, STUBCEE90);
1014   if (bop->isReturnMessageNeeded()/* || bop->is_threaded()*/) // output the helper function for the op
1015     spew(*STUBC, STUBCEE92, returnMarshallMesgTypeName, marshallMesgTypeName,
1016          classname, stubmethodname);
1017
1018 //   i = new UTL_ScopeActiveIterator(op, UTL_Scope::IK_decls);
1019 //   op->return_type()->name()->dump(o);
1020 //   o << " ";
1021 //   op->local_name()->dump(o);
1022 //   o << "(";
1023 //   while (!(i->is_done())) {
1024 //     d = i->item();
1025 //     d->dump(o);
1026 //     i->next();
1027 //     if (!(i->is_done()))
1028 //       o << ", ";
1029 //   }
1030 //   delete i;
1031 //   o << ")";
1032
1033   // @@ We will deal with exceptions later
1034 //   if (op->exceptions() != NULL) {
1035 //     o << " raises(";
1036 //     ei = new UTL_ExceptlistActiveIterator(op->exceptions());
1037 //     while (!(ei->is_done())) {
1038 //       e = ei->item();
1039 //       ei->next();
1040 //       e->local_name()->dump(o);
1041 //       if (!(ei->is_done()))
1042 //      o << ", ";
1043 //     }
1044 //     delete ei;
1045 //     o << ")";
1046 //   }
1047 //   if (op->context() != NULL) {
1048 //     o << " context(";
1049 //     si = new UTL_StrlistActiveIterator(op->context());
1050 //     while (!(si->is_done())) {
1051 //       s = si->item();
1052 //       si->next();
1053 //       o << s->get_string();
1054 //       if (!(si->is_done()))
1055 //      o << ", ";
1056 //     }
1057 //     delete si;
1058 //     o << ")";
1059 //   }
1060 }
1061
1062 //----------------------------------------------------------------------
1063 void
1064 BE_produce_attribute(AST_Decl *d)
1065 {
1066   be_attribute *a = be_attribute::narrow_from_decl(d);
1067   cerr << "WARNING: Attributes unimplemented as yet." << endl;
1068   //exit (-1);
1069
1070 //   cout << "NT_attr " << a->field_type()->local_name()->get_string() << " "
1071 //        << a->local_name()->get_string() << endl;
1072
1073 //   o << (pd_readonly == I_TRUE ? "readonly" : "") << " attribute ";
1074 //   AST_Field::dump(o);
1075 }
1076
1077 //----------------------------------------------------------------------
1078 void
1079 BE_produce_interface(AST_Decl *d)
1080   /* An interface is basically a C++ class */
1081 {
1082   UTL_ScopeActiveIterator       *i;
1083   AST_Interface                 *m;
1084   ostream &o(cout);
1085
1086   m = AST_Interface::narrow_from_decl(d);
1087
1088   char *classname = m->local_name()->get_string();
1089   spew(*SKELH, SKELHDR20, classname);
1090   spew(*SKELC, SKELCEE20, classname);
1091   spew(*STUBH, STUBHDR20, classname);
1092   spew(*STUBC, STUBCEE20, classname);
1093   spew(*SKELCIREST, SKELCI30, classname);
1094   spew(*STUBCIREST, STUBCI30, classname);
1095
1096   //  if (UTL_Scope::decls_used() > 0) {
1097     i = new UTL_ScopeActiveIterator(m, UTL_Scope::IK_both);
1098     int count = 0;
1099     while (!(i->is_done())) {
1100       d = i->item();
1101       count++;
1102
1103       switch(d->node_type()){
1104       case AST_Decl::NT_attr:
1105         BE_produce_attribute(d);
1106         break;
1107       case AST_Decl::NT_op:
1108         BE_produce_operation(d, m);
1109         break;
1110       default:
1111         cerr << "LIMIT: Only Attributes and Operations within interface\n";
1112         break;
1113       }
1114
1115 //       if (!d->imported()) {
1116 //      cout << "count = " << count << endl;
1117 //      idl_global->indent()->skip_to(o);
1118 //      d->dump(o);
1119 //      o << ";\n";
1120 //       } else {
1121 //      cout << "count = " << count << " IMPORTED" << endl;
1122 //       }
1123
1124       i->next();
1125     }
1126     delete i;
1127     //  }
1128   spew(*SKELH, SKELHDR40);
1129   spew(*STUBH, STUBHDR60);
1130   spew(*SKELCIREST, SKELCI50);
1131   spew(*STUBCIREST, STUBCI50);
1132
1133 }
1134
1135 //----------------------------------------------------------------------
1136 void
1137 BE_produce_module(AST_Decl *d)
1138 {
1139   UTL_ScopeActiveIterator       *i;
1140   AST_Module                    *m;
1141   ostream &o(cout);
1142
1143   m = AST_Module::narrow_from_decl(d);
1144   //  if (UTL_Scope::decls_used() > 0) {
1145     i = new UTL_ScopeActiveIterator(m, UTL_Scope::IK_both);
1146     int count = 0;
1147     while (!(i->is_done())) {
1148       d = i->item();
1149       count++;
1150
1151       switch(d->node_type()){
1152       case AST_Decl::NT_interface:
1153         //cout << "NT_interface\n";
1154         BE_produce_interface(d);
1155         break;
1156       default:
1157         if (!d->imported()) {
1158           cerr << "LIMIT: Only Interfaces within Modules at top level\n";
1159         }
1160         break;
1161       }
1162
1163       i->next();
1164     }
1165     delete i;
1166     //  }
1167 }
1168
1169 //----------------------------------------------------------------------
1170 /*
1171   Output occurs at several levels of the hierarchy:
1172
1173   File Level
1174     Module Level (Basically a namespace)
1175       Interface Level (Basically a class)
1176         Operation Level (Basically a method)
1177           Parameter Level (Basically a list of parameters for the method)
1178
1179   In each case, we output when:
1180   1. Entering the level
1181   2. Within the level
1182   3. Leaving the level
1183  */
1184
1185 // Create the various files that the BE outputs.  Output the
1186 // file-level opening stuff.
1187 void
1188 initialize()
1189 {
1190   fullNameNoExt = get_fullname_noextension(
1191                       idl_global->main_filename()->get_string());
1192   // cout << "DEBUG:" << fullNameNoExt << endl;
1193   fileBaseNameNoExt = get_basename_noextension(
1194                       idl_global->main_filename()->get_string());
1195   // cout << "DEBUG:" << fileBaseNameNoExt << endl;
1196
1197   char filename[MAX_STR_LEN];
1198
1199   sprintf(filename, "%s_messages.h", fullNameNoExt);
1200   MESGH = new ofstream(filename);
1201   spew(*MESGH, MESGOP10, fullNameNoExt);
1202
1203   sprintf(filename, "%s_skeleton.h", fullNameNoExt);
1204   SKELH = new ofstream(filename);
1205   spew(*SKELH, SKELHDR10, fileBaseNameNoExt);
1206
1207   sprintf(filename, "%s_skeleton.C", fullNameNoExt);
1208   SKELC = new ofstream(filename);
1209   spew(*SKELC, SKELCEE10, fileBaseNameNoExt);
1210
1211   sprintf(filename, "%s_skeleton.ci", fullNameNoExt);
1212   SKELCI = new ofstream(filename);
1213   spew(*SKELCI, SKELCI10, fileBaseNameNoExt);
1214
1215   sprintf(filename, "%s_skeleton.ci.rest", fullNameNoExt);
1216   SKELCIREST = new ofstream(filename);
1217
1218   sprintf(filename, "%s_stub.h", fullNameNoExt);
1219   STUBH = new ofstream(filename);
1220   spew(*STUBH, STUBHDR10, fileBaseNameNoExt);
1221
1222   sprintf(filename, "%s_stub.C", fullNameNoExt);
1223   STUBC = new ofstream(filename);
1224   spew(*STUBC, STUBCEE10, fileBaseNameNoExt);
1225
1226   sprintf(filename, "%s_stub.ci", fullNameNoExt);
1227   STUBCI = new ofstream(filename);
1228
1229   sprintf(filename, "%s_stub.ci.rest", fullNameNoExt);
1230   STUBCIREST = new ofstream(filename);
1231 }
1232
1233 // At the top level we can have modules, interfaces, constants or type
1234 // declarations. @@
1235 void
1236 BE_produce_top_level()
1237 {
1238   // PROCESS the root/file level of the AST
1239   UTL_ScopeActiveIterator       *i;
1240   AST_Decl                      *d;
1241   ostream &o(cout);
1242
1243   //  if (UTL_Scope::decls_used() > 0) {
1244     i = new UTL_ScopeActiveIterator(idl_global->root(), UTL_Scope::IK_both);
1245
1246     //    o << GTDEVEL("\n/* Declarations0: */\n");
1247     int count = 0;
1248     while (!(i->is_done())) {
1249       d = i->item();
1250       count++;
1251
1252       switch(d->node_type()){
1253       case AST_Decl::NT_module:
1254         //cout << "NT_module\n";
1255         BE_produce_module(d);
1256         break;
1257       case AST_Decl::NT_interface:
1258         //cout << "NT_interface\n";
1259         BE_produce_interface(d);
1260         break;
1261       case AST_Decl::NT_const:
1262       case AST_Decl::NT_struct:
1263         if (!d->imported()) {
1264           d->dump(o);
1265           o << ";" << endl << endl;
1266         }
1267         break;
1268       default:
1269         if (!d->imported()) {
1270           cerr << "LIMIT: Only Modules and Interfaces at top level\n";
1271           d->dump(cout); o << ";" << endl << endl;
1272         }
1273         break;
1274       }
1275
1276 //       if (!d->imported()) {
1277 //      cout << "count = " << count << endl;
1278 //      idl_global->indent()->skip_to(o);
1279 //      d->dump(o);
1280 //      o << ";\n";
1281 //       } else {
1282 //      //      cout << "count = " << count << " IMPORTED" << endl;
1283 //       }
1284       i->next();
1285     }
1286     delete i;
1287     //  }
1288 }
1289
1290 // Output the file-level closing stuff; Close the output files.
1291 void
1292 clean_up()
1293 {
1294   spew(*MESGH, MESGOP50);
1295   delete MESGH;
1296
1297   spew(*SKELH, SKELHDR50);
1298   delete SKELH;
1299
1300   char cleanUpCommands[MAX_STR_LEN];
1301   sprintf(cleanUpCommands, "cat %s_skeleton.h >> %s_messages.h; "
1302           "mv %s_messages.h %s_skeleton.h", fullNameNoExt, fullNameNoExt,
1303           fullNameNoExt, fullNameNoExt);
1304   assert(system(cleanUpCommands) == 0);
1305
1306   spew(*SKELC, SKELCEE60, fileBaseNameNoExt);
1307   delete SKELC;
1308
1309   delete SKELCI;
1310   delete SKELCIREST;
1311   sprintf(cleanUpCommands, "cat %s_skeleton.ci.rest >> %s_skeleton.ci; "
1312           "rm %s_skeleton.ci.rest", fullNameNoExt, fullNameNoExt,
1313           fullNameNoExt);
1314   assert(system(cleanUpCommands) == 0);
1315
1316   spew(*STUBH, STUBHDR70);
1317   delete STUBH;
1318
1319   spew(*STUBC, STUBCEE95, fileBaseNameNoExt);
1320   delete STUBC;
1321
1322   delete STUBCI;
1323   delete STUBCIREST;
1324   sprintf(cleanUpCommands, "cat %s_stub.ci.rest >> %s_stub.ci; "
1325           "rm %s_stub.ci.rest", fullNameNoExt, fullNameNoExt,
1326           fullNameNoExt);
1327   assert(system(cleanUpCommands) == 0);
1328
1329   delete fullNameNoExt;
1330   delete fileBaseNameNoExt;
1331 }
1332
1333 /*
1334  * Do the work of this BE.
1335  */
1336 void
1337 BE_produce()
1338 {
1339   initialize();
1340
1341   BE_produce_top_level();
1342   
1343   clean_up();
1344 }
1345
1346 //----------------------------------------------------------------------
1347 /*
1348  * Abort this run of the BE
1349  */
1350 void
1351 BE_abort()
1352 {
1353 }
1354
1355 /*
1356
1357 COPYRIGHT
1358
1359 Copyright 1992, 1993, 1994 Sun Microsystems, Inc.  Printed in the United
1360 States of America.  All Rights Reserved.
1361
1362 This product is protected by copyright and distributed under the following
1363 license restricting its use.
1364
1365 The Interface Definition Language Compiler Front End (CFE) is made
1366 available for your use provided that you include this license and copyright
1367 notice on all media and documentation and the software program in which
1368 this product is incorporated in whole or part. You may copy and extend
1369 functionality (but may not remove functionality) of the Interface
1370 Definition Language CFE without charge, but you are not authorized to
1371 license or distribute it to anyone else except as part of a product or
1372 program developed by you or with the express written consent of Sun
1373 Microsystems, Inc. ("Sun").
1374
1375 The names of Sun Microsystems, Inc. and any of its subsidiaries or
1376 affiliates may not be used in advertising or publicity pertaining to
1377 distribution of Interface Definition Language CFE as permitted herein.
1378
1379 This license is effective until terminated by Sun for failure to comply
1380 with this license.  Upon termination, you shall destroy or return all code
1381 and documentation for the Interface Definition Language CFE.
1382
1383 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
1384 ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
1385 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
1386 DEALING, USAGE OR TRADE PRACTICE.
1387
1388 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
1389 ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES
1390 TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
1391
1392 SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
1393 RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
1394 INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF.
1395
1396 IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
1397 ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
1398 DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
1399
1400 Use, duplication, or disclosure by the government is subject to
1401 restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
1402 Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
1403 52.227-19.
1404
1405 Sun, Sun Microsystems and the Sun logo are trademarks or registered
1406 trademarks of Sun Microsystems, Inc.
1407
1408 SunSoft, Inc.
1409 2550 Garcia Avenue
1410 Mountain View, California  94043
1411
1412 NOTE:
1413
1414 SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
1415 trademarks or registered trademarks of Sun Microsystems, Inc.
1416
1417  */
1418
1419 // #pragma ident "%@(#)BE_produce.cc    1.16% %92/06/10% Sun Microsystems"