12 &getopts("mtT:", \%options);
14 # $target = "../../types/robottype_eb2007.ortegen";
20 $force_roboorte_name = $ARGV[1];
35 @files = &get_files($target);
37 push(@files, $target);
41 foreach $ortegenfile (@files) {
42 $ortegenfilename = $ortegenfile;
43 $ortegenfilename =~ s#(.*[/]+)?([^/]+).ortegen#$2#gs;
45 if (defined($force_roboorte_name) and $one_file) {
46 $roboorte_name = $force_roboorte_name;
48 $roboorte_name = $ortegenfilename;
51 @ortegen = &parse_ortegen($ortegenfile);
52 # print Dumper(@ortegen);
53 @ortegen = &fill_default_values(@ortegen);
54 # print Dumper(@ortegen);
56 &generate_roboorte_header(@ortegen);
58 &generate_roboorte_library(@ortegen);
60 if ($options{"t"} or $options{"T"}) {
61 &generate_test_publisher(@ortegen);
62 &generate_test_subscriber(@ortegen);
65 push(@libnames, $roboorte_name);
66 push(@ortegenfilenames, $ortegenfilename);
70 &generate_makefile(@libnames);
81 print << "(END OF PRINT USAGE)";
82 Robot\'s ORTE library and test programs generator.
84 Usage: $0 <ORTEGEN directory or file> [force_roboorte_name]
87 \t-t create test files
88 \t-T <dir> test directory
91 1) generate libraries, test programs and makefiles for all ORTEGEN file in
92 the directory <some_dir>, place all test files to directory test/
94 \t $0 -T test -m <some_dir>
96 2) generate libraries, test programs and makefiles and use name <some_name>
99 \t $0 -t -m ../../types/file.ortegen <some_name>
107 # Get ORTEGENs files list from a directory
114 my(@file_list) = glob($dir."/*.ortegen");
120 # parse ORTE ORTEGEN file and return a data structure containing ORTE topics and their parameters
126 my ($ortegenfile) = @_;
131 unless (open(INFILE, "$ortegenfile")) {
132 print "Unable to open file $ortegenfile\n";
137 # removing C/C++ style comments
138 $line =~ s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#$2#gs;
139 # removing shell comments
142 next if $line =~ /^[\s]*$/;
146 @fields = qw/topic type strength deadline persistance minsep pubdelay/;
147 foreach $field(@fields) {
148 # Read the field value
149 ($val) = $line =~ /\b$field=([\S]+)/;
151 $line =~ s/$field=([\S]+)//g;
153 $ortevar{$field} = $val;
155 if (!$ortevar{"type"}) { die("$ortegenfile:$.: type not defined\n"); }
156 if (!$ortevar{"topic"}) { die("$ortegenfile:$.: topic not defined\n"); }
159 if ($line =~ /\S/) { die ("$ortegenfile:$.: unknown fields '$line'\nValid fields are: @fields\n"); }
161 push(@ortegen, \%ortevar);
168 sub fill_default_values {
171 foreach $var (@ortegen) {
172 if (!$var->{"persistence"}) { $var->{"persistence"} = $publication_persistence; }
173 if (!$var->{"strength"}) { $var->{"strength"} = $publication_strength; }
174 if (!$var->{"deadline"}) { $var->{"deadline"} = $subscription_deadline; }
175 if (!$var->{"minsep"}) { $var->{"minsep"} = $minimum_separation; }
176 if (!$var->{"pubdelay"}) { $var->{"pubdelay"} = $publication_callback_delay; }
177 if (!$var->{"deadline"}) { $var->{"deadline"} = $subscription_deadline; }
185 sub generate_roboorte_header {
187 my($headerfile) = $library_name_prefix.$roboorte_name.".h";
189 unless (open (OUTFILE, ">$headerfile")) {
190 print "Unable to create file $headerfile\n";
194 print OUTFILE << "(END)";
196 * Automatically generated RoboORTE library.
197 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
200 #ifndef $library_name_prefix$roboorte_name\_H
201 #define $library_name_prefix$roboorte_name\_H
206 #include <robottype.h>
207 #include <$ortegenfilename.h>
208 #include <roboorte.h>
210 #undef ROBOORTE_ROBOT_NAME
211 #define ROBOORTE_ROBOT_NAME $roboorte_name
213 #ifndef ROBOORTE_ROBOT_NAME
214 #error No ROBOORTE_ROBOT_NAME defined!
219 \tORTEDomain *$orte_domain;
222 \t/* orte data types */
225 foreach $var (@ortegen) {
226 print OUTFILE << "(END)";
227 \tstruct $var->{"type"}_type $var->{"topic"};
231 print OUTFILE << "(END)";
236 foreach $var (@ortegen) {
237 print OUTFILE << "(END)";
238 \tORTEPublication *$publication_prefix$var->{"topic"};
242 print OUTFILE << "(END)";
253 foreach $var (@ortegen) {
254 print OUTFILE << "(END)";
255 ROBOORTE_PUBLISHER_CREATE($var->{"topic"});
259 print OUTFILE << "(END)";
263 foreach $var (@ortegen) {
264 print OUTFILE << "(END)";
265 ROBOORTE_PUBLISHER_DESTROY($var->{"topic"});
269 print OUTFILE << "(END)";
273 foreach $var (@ortegen) {
274 print OUTFILE << "(END)";
275 ROBOORTE_SUBSCRIBER_CREATE($var->{"topic"});
279 print OUTFILE << "(END)";
284 #endif /* $library_name_prefix$roboorte_name\_H */
295 sub generate_roboorte_library {
297 my($libraryfile) = $library_name_prefix.$roboorte_name.".c";
299 unless (open (OUTFILE, ">$libraryfile")) {
300 print "Unable to create file $libraryfile\n";
304 print OUTFILE << "(END)";
306 * Automatically generated RoboORTE library.
307 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
310 #include "$library_name_prefix$roboorte_name.h"
312 /* ----------------------------------------------------------------------
314 * ---------------------------------------------------------------------- */
318 foreach $var (@ortegen) {
319 ($pmsec, $psec) = POSIX::modf($var->{"persistence"});
320 $pmsec = POSIX::floor($pmsec*1000);
321 ($dmsec, $dsec) = POSIX::modf($var->{"pubdelay"});
322 $dmsec = POSIX::floor($dmsec*1000);
323 print OUTFILE << "(END)";
324 ROBOORTE_PUBLISHER_CREATE($var->{"topic"})
326 \tNtpTime persistence, delay;
328 \t$var->{"type"}_type_register($data_arg_name->$orte_domain);
329 \tNtpTimeAssembFromMs(persistence, $psec, $pmsec);
330 \tNtpTimeAssembFromMs(delay, $dsec, $dmsec);
331 \t$data_arg_name->$publication_prefix$var->{"topic"} = ORTEPublicationCreate(
332 \t\t\t$data_arg_name->$orte_domain, "$var->{"topic"}", "$var->{"type"}",
333 \t\t\t&$data_arg_name->$var->{"topic"}, &persistence, $data_arg_name->strength,
334 \t\t\t$callback_name, $callback_arg, &delay);
341 print OUTFILE << "(END)";
342 /* ----------------------------------------------------------------------
344 * ---------------------------------------------------------------------- */
348 foreach $var (@ortegen) {
349 print OUTFILE << "(END)";
350 ROBOORTE_PUBLISHER_DESTROY($var->{"topic"})
352 \tORTEPublicationDestroy($data_arg_name->$publication_prefix$var->{"topic"});
359 print OUTFILE << "(END)";
360 /* ----------------------------------------------------------------------
362 * ---------------------------------------------------------------------- */
366 foreach $var (@ortegen) {
367 ($mmsec, $msec) = POSIX::modf($var->{"minsep"});
368 $mmsec = POSIX::floor($mmsec*1000);
369 ($dmsec, $dsec) = POSIX::modf($var->{"deadline"});
370 $dmsec = POSIX::floor($dmsec*1000);
371 print OUTFILE << "(END)";
372 ROBOORTE_SUBSCRIBER_CREATE($var->{"topic"})
374 \tORTESubscription *s;
375 \tNtpTime deadline, minimumSeparation;
377 \t$var->{"type"}_type_register($data_arg_name->$orte_domain);
379 \tNtpTimeAssembFromMs(deadline, $dsec, $dmsec);
380 \tNtpTimeAssembFromMs(minimumSeparation, $msec, $mmsec);
381 \ts = ORTESubscriptionCreate(
382 \t\t\t$data_arg_name->$orte_domain, $subscription_mode, $subscription_type,
383 \t\t\t"$var->{"topic"}", "$var->{"type"}",
384 \t\t\t&$data_arg_name->$var->{"topic"}, &deadline, &minimumSeparation,
385 \t\t\t$callback_name, $callback_arg, $multicast_ip_address);
392 print OUTFILE << "(END)";
394 /* ----------------------------------------------------------------------
395 * ORTE INITILIZATION AND DESTROY
396 * ---------------------------------------------------------------------- */
404 \tif ($data_arg_name->strength < 0)
405 \t\t$data_arg_name->strength = $publication_strength;
407 \tORTEVerbositySetOptions("ALL.0");
408 \t$data_arg_name->$orte_domain = ORTEDomainAppCreate(ORTE_DEFAULT_DOMAIN,
409 \t NULL, NULL, ORTE_FALSE);
410 \tif (!$data_arg_name->$orte_domain) {
411 \t\tprintf("ORTEDomainAppCreate failed!\\n");
420 \treturn ORTEDomainAppDestroy($data_arg_name->$orte_domain);
432 sub generate_makefile {
434 my($makefile) = "Makefile.omk";
436 unless (open (OUTFILE, ">$makefile")) {
437 print "Unable to create $makefile\n";
441 if ($testdir = $options{"T"}) {
442 $testmakefile = "$testdir/$makefile";
443 unless (open (MKOUTFILE, ">$testmakefile")) {
444 print "Unable to create $testmakefile\n";
447 print MKOUTFILE << "(END)";
449 # Automatically generated Makefile file.
450 # \@warning DO NOT EDIT!!!
453 # Robot's ORTE library
457 *MKOUTFILE = *OUTFILE;
458 print OUTFILE << "(END)";
459 # Automatically generated Makefile file.
460 # \@warning DO NOT EDIT!!!
463 # Robot's ORTE library
469 foreach $filename (@files) {
470 $testfilename1 = $test_publisher_name_prefix.$filename;
471 $testfilename2 = $test_subscriber_name_prefix.$filename;
472 $libraryname = $library_name_prefix.$filename;
474 print OUTFILE << "(END)";
475 lib_LIBRARIES += $libraryname
476 $libraryname\_SOURCES = $libraryname.c
477 include_HEADERS += $libraryname.h
481 if ($options{"t"} or $options{"T"}) {
482 print MKOUTFILE << "(END)";
483 test_PROGRAMS += $testfilename1
484 $testfilename1\_SOURCES = $testfilename1.c
485 $testfilename1\_LIBS = pthread $libraryname robottype $ortegenfilenames[$i] orte
487 test_PROGRAMS += $testfilename2
488 $testfilename2\_SOURCES = $testfilename2.c
489 $testfilename2\_LIBS = pthread $libraryname robottype $ortegenfilenames[$i] orte
497 print OUTFILE << "(END)";
501 \t\$(Q)rm -rf *.c *.h Makefile.omk test/
503 `cp -p Makefile $testdir`
505 print OUTFILE << "(END)";
507 \t\$(Q)rm -rf *.c *.h Makefile.omk
522 sub generate_test_publisher {
524 my($testfile) = $test_publisher_name_prefix.$roboorte_name.".c";
527 if ($testdir = $options{"T"}) {
528 $testfile = "$testdir/$testfile";
532 unless (open (OUTFILE, ">$testfile")) {
533 print "Unable to create file $testfile\n";
537 print OUTFILE << "(END)";
539 * Automatically generated test file for RoboORTE libraries.
540 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
549 #include <$library_name_prefix$roboorte_name.h>
551 /* ----------------------------------------------------------------------
552 * PUBLISHER CALLBACKS
553 * ---------------------------------------------------------------------- */
557 foreach $var (@ortegen) {
558 print OUTFILE << "(END)";
559 void send_$var->{"topic"}_cb(const ORTESendInfo *info, void *vinstance,
560 \t\t\tvoid *sendCallBackParam)
567 print OUTFILE << "(END)";
569 /* Thread process. Do the job. */
570 void *process(void *arg)
572 \tstruct $roboorte_name\_orte_data *orte = (struct $roboorte_name\_orte_data*)arg;
580 foreach $var (@ortegen) {
581 my(@var) = (@{$var->{"var"}});
582 print OUTFILE << "(END)";
583 \t\t\t/* $var->{"topic"} */
585 \t\t\t\tprintf("$var->{"topic"}:\\n");
587 foreach $var (@var) {
588 if ($var->{"type"} eq "double") {
589 print OUTFILE << "(END)";
590 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = ($var->{"type"})(rand() % 255);
591 \t\t\t\tprintf("\\t$var->{"topic"} = %f\\n", orte->$var->{"topic"}.$var->{"topic"});
593 } elsif ( $var->{"type"} eq "octet" ) {
594 print OUTFILE << "(END)";
595 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = (unsigned char)(rand() % 255);
596 \t\t\t\tprintf("\\t$var->{"topic"} = 0x%02x\\n", orte->$var->{"topic"}.$var->{"topic"});
598 } elsif ( $var->{"type"} eq "unsigned short" ) {
599 print OUTFILE << "(END)";
600 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = ($var->{"type"})(rand() % 255);
601 \t\t\t\tprintf("\\t$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
604 print OUTFILE << "(END)";
605 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = (int)(rand() % 255);
606 \t\t\t\tprintf("\\t$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
611 if (defined($publication_callback_enabled)) {
612 print OUTFILE << "(END)";
613 \t\t\t\t/*ORTEPublicationSend(orte->$publication_prefix$var->{"topic"});*/
618 print OUTFILE << "(END)";
619 \t\t\t\tORTEPublicationSend(orte->$publication_prefix$var->{"topic"});
628 print OUTFILE << "(END)";
634 \t\tusleep($publisher_thread_usleep);
639 void start_thread(struct $roboorte_name\_orte_data *orte)
645 \tretcode = pthread_create(&th, NULL, process, orte);
647 \t\tprintf("Failed to create thread %d\\n", retcode);
649 \tretcode = pthread_join(th, &retval);
651 \t\tprintf("Failed to join thread %d\\n", retcode);
654 struct $roboorte_name\_orte_data orte;
657 static void int_handler(int sig)
659 \t$roboorte_name\_roboorte_destroy(&orte);
667 \tsignal(SIGINT, int_handler);
669 \torte.strength = $publication_strength;
671 \t/* orte initialization */
672 \t$roboorte_name\_roboorte_init(&orte);
674 \t/* creating publishers */
677 foreach $var (@ortegen) {
678 if (defined($publication_callback_enabled)) {
679 $publication_callback = "send_".$var->{"topic"}."_cb";
681 $publication_callback = "NULL";
684 print OUTFILE << "(END)";
685 \t$roboorte_name\_publisher_$var->{"topic"}_create(&orte, $publication_callback, &orte);
689 print OUTFILE << "(END)";
691 \tprintf("Publishers: sending data.\\n");
693 \t/* start thread and do the job */
694 \tstart_thread(&orte);
696 \t/* orte domain destroy */
697 \t$roboorte_name\_roboorte_destroy(&orte);
712 sub generate_test_subscriber {
714 my($testfile) = $test_subscriber_name_prefix.$roboorte_name.".c";
716 if ($testdir = $options{"T"}) {
717 $testfile = "$testdir/$testfile";
721 unless (open (OUTFILE, ">$testfile")) {
722 print "Unable to create file $testfile\n";
726 print OUTFILE << "(END)";
728 * Automatically generated test file for RoboORTE libraries.
729 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
737 #include <sys/time.h>
739 #include <$library_name_prefix$roboorte_name.h>
748 \tgettimeofday(&tv, NULL);
749 \tcurtime = tv.tv_sec;
750 \tstrftime(buffer, 30, "[%T.", localtime(&curtime));
751 \tprintf("%s%ld]\\n", buffer, tv.tv_usec);
754 /* ----------------------------------------------------------------------
755 * SUBSCRIBER CALLBACKS
756 * ---------------------------------------------------------------------- */
760 foreach $var (@ortegen) {
761 print OUTFILE << "(END)";
762 void rcv_$var->{"topic"}_cb(const ORTERecvInfo *info, void *vinstance,
763 \t\t\tvoid *recvCallBackParam)
765 \tstruct $roboorte_name\_orte_data *orte =
766 \t\t\t(struct $roboorte_name\_orte_data *)recvCallBackParam;
768 \tswitch (info->status) {
771 if (defined($subscriber_print_data)) {
772 print OUTFILE << "(END)";
774 \t\t\tprintf("\\t$var->{"topic"}:\\n");
776 my(@var) = (@{$var->{"var"}});
777 foreach $var (@var) {
778 print OUTFILE << "(END)";
779 \t\t\t\tprintf("\\t\\t");
781 if ($var->{"type"} eq "double") {
782 print OUTFILE << "(END)";
783 \t\t\t\tprintf("$var->{"topic"} = %f\\n", orte->$var->{"topic"}.$var->{"topic"});
785 } elsif ( $var->{"type"} eq "octet" ) {
786 print OUTFILE << "(END)";
787 \t\t\t\tprintf("$var->{"topic"} = 0x%02x\\n", orte->$var->{"topic"}.$var->{"topic"});
790 print OUTFILE << "(END)";
791 \t\t\t\tprintf("$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
797 print OUTFILE << "(END)";
800 \t\t\tprintf("ORTE deadline occurred - $var->{"topic"} receive\\n");
808 print OUTFILE << "(END)";
809 struct $roboorte_name\_orte_data orte;
812 static void int_handler(int sig)
814 \t$roboorte_name\_roboorte_destroy(&orte);
820 \tsignal(SIGINT, int_handler);
822 \t/* orte initialization */
823 \t$roboorte_name\_roboorte_init(&orte);
825 \t/* creating subscribers */
828 foreach $var (@ortegen) {
829 print OUTFILE << "(END)";
830 \t$roboorte_name\_subscriber_$var->{"topic"}_create(&orte, rcv_$var->{"topic"}_cb, &orte);
834 unless (defined($subscriber_print_data)) {
835 print OUTFILE << "(END)";
836 \tprintf("Subscribers: debug print turned off.\\n");
839 print OUTFILE << "(END)";
841 \tprintf("Subscribers: waiting for data.\\n");
843 \t\tusleep($subscriber_wait_usleep);
846 \t/* orte domain destroy */
847 \t$roboorte_name\_roboorte_destroy(&orte);