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>
210 struct ${roboorte_name}_orte_data {
211 \tORTEDomain *$orte_domain;
214 \t/* orte data types */
217 foreach $var (@ortegen) {
218 print OUTFILE << "(END)";
219 \tstruct $var->{"type"}_type $var->{"topic"};
223 print OUTFILE << "(END)";
228 foreach $var (@ortegen) {
229 print OUTFILE << "(END)";
230 \tORTEPublication *$publication_prefix$var->{"topic"};
234 print OUTFILE << "(END)";
240 int ${roboorte_name}_roboorte_init(struct ${roboorte_name}_orte_data *data) __attribute ((warn_unused_result));
241 int ${roboorte_name}_roboorte_destroy(struct ${roboorte_name}_orte_data *data);
245 foreach $var (@ortegen) {
246 print OUTFILE << "(END)";
247 void ${roboorte_name}_publisher_$var->{"topic"}_create(struct ${roboorte_name}_orte_data *data, ORTESendCallBack callback, void *arg);
251 print OUTFILE << "(END)";
255 foreach $var (@ortegen) {
256 print OUTFILE << "(END)";
257 void ${roboorte_name}_publisher_$var->{"topic"}_destroy(struct ${roboorte_name}_orte_data *data);
261 print OUTFILE << "(END)";
265 foreach $var (@ortegen) {
266 print OUTFILE << "(END)";
267 void ${roboorte_name}_subscriber_$var->{"topic"}_create(struct ${roboorte_name}_orte_data *data, ORTERecvCallBack callback, void *arg);
271 print OUTFILE << "(END)";
276 #endif /* $library_name_prefix$roboorte_name\_H */
287 sub generate_roboorte_library {
289 my($libraryfile) = $library_name_prefix.$roboorte_name.".c";
291 unless (open (OUTFILE, ">$libraryfile")) {
292 print "Unable to create file $libraryfile\n";
296 print OUTFILE << "(END)";
298 * Automatically generated RoboORTE library.
299 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
302 #include "$library_name_prefix$roboorte_name.h"
305 /* ----------------------------------------------------------------------
307 * ---------------------------------------------------------------------- */
311 foreach $var (@ortegen) {
312 ($pmsec, $psec) = POSIX::modf($var->{"persistence"});
313 $pmsec = POSIX::floor($pmsec*1000);
314 ($dmsec, $dsec) = POSIX::modf($var->{"pubdelay"});
315 $dmsec = POSIX::floor($dmsec*1000);
316 print OUTFILE << "(END)";
317 void ${roboorte_name}_publisher_$var->{"topic"}_create(struct ${roboorte_name}_orte_data *data, ORTESendCallBack callback, void *arg)
319 \tNtpTime persistence, delay;
321 \t$var->{"type"}_type_register($data_arg_name->$orte_domain);
322 \tNtpTimeAssembFromMs(persistence, $psec, $pmsec);
323 \tNtpTimeAssembFromMs(delay, $dsec, $dmsec);
324 \t$data_arg_name->$publication_prefix$var->{"topic"} = ORTEPublicationCreate(
325 \t\t\t$data_arg_name->$orte_domain, "$var->{"topic"}", "$var->{"type"}",
326 \t\t\t&$data_arg_name->$var->{"topic"}, &persistence, $data_arg_name->strength,
327 \t\t\t$callback_name, $callback_arg, &delay);
334 print OUTFILE << "(END)";
335 /* ----------------------------------------------------------------------
337 * ---------------------------------------------------------------------- */
341 foreach $var (@ortegen) {
342 print OUTFILE << "(END)";
343 void ${roboorte_name}_publisher_$var->{"topic"}_destroy(struct ${roboorte_name}_orte_data *data)
345 \tORTEPublicationDestroy($data_arg_name->$publication_prefix$var->{"topic"});
352 print OUTFILE << "(END)";
353 /* ----------------------------------------------------------------------
355 * ---------------------------------------------------------------------- */
359 foreach $var (@ortegen) {
360 ($mmsec, $msec) = POSIX::modf($var->{"minsep"});
361 $mmsec = POSIX::floor($mmsec*1000);
362 ($dmsec, $dsec) = POSIX::modf($var->{"deadline"});
363 $dmsec = POSIX::floor($dmsec*1000);
364 print OUTFILE << "(END)";
365 void ${roboorte_name}_subscriber_$var->{"topic"}_create(struct ${roboorte_name}_orte_data *data, ORTERecvCallBack callback, void *arg)
367 \tORTESubscription *s;
368 \tNtpTime deadline, minimumSeparation;
370 \t$var->{"type"}_type_register($data_arg_name->$orte_domain);
372 \tNtpTimeAssembFromMs(deadline, $dsec, $dmsec);
373 \tNtpTimeAssembFromMs(minimumSeparation, $msec, $mmsec);
374 \ts = ORTESubscriptionCreate(
375 \t\t\t$data_arg_name->$orte_domain, $subscription_mode, $subscription_type,
376 \t\t\t"$var->{"topic"}", "$var->{"type"}",
377 \t\t\t&$data_arg_name->$var->{"topic"}, &deadline, &minimumSeparation,
378 \t\t\t$callback_name, $callback_arg, $multicast_ip_address);
385 print OUTFILE << "(END)";
387 /* ----------------------------------------------------------------------
388 * ORTE INITILIZATION AND DESTROY
389 * ---------------------------------------------------------------------- */
391 int ${roboorte_name}_roboorte_init(struct ${roboorte_name}_orte_data *data)
395 \tORTEDomainProp prop;
398 \tif ($data_arg_name->strength <= 0)
399 \t\t$data_arg_name->strength = $publication_strength;
401 if ((s = getenv("ORTE_STRENGTH"))) {
403 long l = strtol(s, &end, 10);
408 \tORTEVerbositySetOptions("ALL.0");
409 \tORTEDomainPropDefaultGet(&prop);
410 \tNTPTIME_BUILD(prop.baseProp.refreshPeriod, $refresh_period);
411 \tNTPTIME_BUILD(prop.baseProp.expirationTime, $expiration_time);
412 \t$data_arg_name->$orte_domain = ORTEDomainAppCreate(ORTE_DEFAULT_DOMAIN,
413 \t &prop, NULL, ORTE_FALSE);
414 \tif (!$data_arg_name->$orte_domain) {
415 \t\tprintf("ORTEDomainAppCreate failed!\\n");
422 int ${roboorte_name}_roboorte_destroy(struct ${roboorte_name}_orte_data *data)
424 \treturn ORTEDomainAppDestroy($data_arg_name->$orte_domain);
436 sub generate_makefile {
438 my($makefile) = "Makefile.omk";
440 unless (open (OUTFILE, ">$makefile")) {
441 print "Unable to create $makefile\n";
445 if ($testdir = $options{"T"}) {
446 $testmakefile = "$testdir/$makefile";
447 unless (open (MKOUTFILE, ">$testmakefile")) {
448 print "Unable to create $testmakefile\n";
451 print MKOUTFILE << "(END)";
453 # Automatically generated Makefile file.
454 # \@warning DO NOT EDIT!!!
457 # Robot's ORTE library
461 *MKOUTFILE = *OUTFILE;
462 print OUTFILE << "(END)";
463 # Automatically generated Makefile file.
464 # \@warning DO NOT EDIT!!!
467 # Robot's ORTE library
473 foreach $filename (@files) {
474 $testfilename1 = $test_publisher_name_prefix.$filename;
475 $testfilename2 = $test_subscriber_name_prefix.$filename;
476 $libraryname = $library_name_prefix.$filename;
478 print OUTFILE << "(END)";
479 lib_LIBRARIES += $libraryname
480 $libraryname\_SOURCES = $libraryname.c
481 include_HEADERS += $libraryname.h
485 if ($options{"t"} or $options{"T"}) {
486 print MKOUTFILE << "(END)";
487 test_PROGRAMS += $testfilename1
488 $testfilename1\_SOURCES = $testfilename1.c
489 $testfilename1\_LIBS = pthread $libraryname robottype $ortegenfilenames[$i] orte
491 test_PROGRAMS += $testfilename2
492 $testfilename2\_SOURCES = $testfilename2.c
493 $testfilename2\_LIBS = pthread $libraryname robottype $ortegenfilenames[$i] orte
501 print OUTFILE << "(END)";
505 \t\$(Q)rm -rf *.c *.h Makefile.omk test/
507 `cp -p Makefile $testdir`
509 print OUTFILE << "(END)";
511 \t\$(Q)rm -rf *.c *.h Makefile.omk
526 sub generate_test_publisher {
528 my($testfile) = $test_publisher_name_prefix.$roboorte_name.".c";
531 if ($testdir = $options{"T"}) {
532 $testfile = "$testdir/$testfile";
536 unless (open (OUTFILE, ">$testfile")) {
537 print "Unable to create file $testfile\n";
541 print OUTFILE << "(END)";
543 * Automatically generated test file for RoboORTE libraries.
544 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
553 #include <$library_name_prefix$roboorte_name.h>
555 /* ----------------------------------------------------------------------
556 * PUBLISHER CALLBACKS
557 * ---------------------------------------------------------------------- */
561 foreach $var (@ortegen) {
562 print OUTFILE << "(END)";
563 void send_$var->{"topic"}_cb(const ORTESendInfo *info, void *vinstance,
564 \t\t\tvoid *sendCallBackParam)
571 print OUTFILE << "(END)";
573 /* Thread process. Do the job. */
574 void *process(void *arg)
576 \tstruct $roboorte_name\_orte_data *orte = (struct $roboorte_name\_orte_data*)arg;
584 foreach $var (@ortegen) {
585 my(@var) = (@{$var->{"var"}});
586 print OUTFILE << "(END)";
587 \t\t\t/* $var->{"topic"} */
589 \t\t\t\tprintf("$var->{"topic"}:\\n");
591 foreach $var (@var) {
592 if ($var->{"type"} eq "double") {
593 print OUTFILE << "(END)";
594 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = ($var->{"type"})(rand() % 255);
595 \t\t\t\tprintf("\\t$var->{"topic"} = %f\\n", orte->$var->{"topic"}.$var->{"topic"});
597 } elsif ( $var->{"type"} eq "octet" ) {
598 print OUTFILE << "(END)";
599 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = (unsigned char)(rand() % 255);
600 \t\t\t\tprintf("\\t$var->{"topic"} = 0x%02x\\n", orte->$var->{"topic"}.$var->{"topic"});
602 } elsif ( $var->{"type"} eq "unsigned short" ) {
603 print OUTFILE << "(END)";
604 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = ($var->{"type"})(rand() % 255);
605 \t\t\t\tprintf("\\t$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
608 print OUTFILE << "(END)";
609 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = (int)(rand() % 255);
610 \t\t\t\tprintf("\\t$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
615 if (defined($publication_callback_enabled)) {
616 print OUTFILE << "(END)";
617 \t\t\t\t/*ORTEPublicationSend(orte->$publication_prefix$var->{"topic"});*/
622 print OUTFILE << "(END)";
623 \t\t\t\tORTEPublicationSend(orte->$publication_prefix$var->{"topic"});
632 print OUTFILE << "(END)";
638 \t\tusleep($publisher_thread_usleep);
643 void start_thread(struct $roboorte_name\_orte_data *orte)
649 \tretcode = pthread_create(&th, NULL, process, orte);
651 \t\tprintf("Failed to create thread %d\\n", retcode);
653 \tretcode = pthread_join(th, &retval);
655 \t\tprintf("Failed to join thread %d\\n", retcode);
658 struct $roboorte_name\_orte_data orte;
661 static void int_handler(int sig)
663 \t$roboorte_name\_roboorte_destroy(&orte);
671 \tsignal(SIGINT, int_handler);
673 \torte.strength = $publication_strength;
675 \t/* orte initialization */
676 \t$roboorte_name\_roboorte_init(&orte);
678 \t/* creating publishers */
681 foreach $var (@ortegen) {
682 if (defined($publication_callback_enabled)) {
683 $publication_callback = "send_".$var->{"topic"}."_cb";
685 $publication_callback = "NULL";
688 print OUTFILE << "(END)";
689 \t$roboorte_name\_publisher_$var->{"topic"}_create(&orte, $publication_callback, &orte);
693 print OUTFILE << "(END)";
695 \tprintf("Publishers: sending data.\\n");
697 \t/* start thread and do the job */
698 \tstart_thread(&orte);
700 \t/* orte domain destroy */
701 \t$roboorte_name\_roboorte_destroy(&orte);
716 sub generate_test_subscriber {
718 my($testfile) = $test_subscriber_name_prefix.$roboorte_name.".c";
720 if ($testdir = $options{"T"}) {
721 $testfile = "$testdir/$testfile";
725 unless (open (OUTFILE, ">$testfile")) {
726 print "Unable to create file $testfile\n";
730 print OUTFILE << "(END)";
732 * Automatically generated test file for RoboORTE libraries.
733 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
741 #include <sys/time.h>
743 #include <$library_name_prefix$roboorte_name.h>
752 \tgettimeofday(&tv, NULL);
753 \tcurtime = tv.tv_sec;
754 \tstrftime(buffer, 30, "[%T.", localtime(&curtime));
755 \tprintf("%s%ld]\\n", buffer, tv.tv_usec);
758 /* ----------------------------------------------------------------------
759 * SUBSCRIBER CALLBACKS
760 * ---------------------------------------------------------------------- */
764 foreach $var (@ortegen) {
765 print OUTFILE << "(END)";
766 void rcv_$var->{"topic"}_cb(const ORTERecvInfo *info, void *vinstance,
767 \t\t\tvoid *recvCallBackParam)
769 \tstruct $roboorte_name\_orte_data *orte =
770 \t\t\t(struct $roboorte_name\_orte_data *)recvCallBackParam;
772 \tswitch (info->status) {
775 if (defined($subscriber_print_data)) {
776 print OUTFILE << "(END)";
778 \t\t\tprintf("\\t$var->{"topic"}:\\n");
780 my(@var) = (@{$var->{"var"}});
781 foreach $var (@var) {
782 print OUTFILE << "(END)";
783 \t\t\t\tprintf("\\t\\t");
785 if ($var->{"type"} eq "double") {
786 print OUTFILE << "(END)";
787 \t\t\t\tprintf("$var->{"topic"} = %f\\n", orte->$var->{"topic"}.$var->{"topic"});
789 } elsif ( $var->{"type"} eq "octet" ) {
790 print OUTFILE << "(END)";
791 \t\t\t\tprintf("$var->{"topic"} = 0x%02x\\n", orte->$var->{"topic"}.$var->{"topic"});
794 print OUTFILE << "(END)";
795 \t\t\t\tprintf("$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
801 print OUTFILE << "(END)";
804 \t\t\tprintf("ORTE deadline occurred - $var->{"topic"} receive\\n");
812 print OUTFILE << "(END)";
813 struct $roboorte_name\_orte_data orte;
816 static void int_handler(int sig)
818 \t$roboorte_name\_roboorte_destroy(&orte);
824 \tsignal(SIGINT, int_handler);
826 \t/* orte initialization */
827 \t$roboorte_name\_roboorte_init(&orte);
829 \t/* creating subscribers */
832 foreach $var (@ortegen) {
833 print OUTFILE << "(END)";
834 \t$roboorte_name\_subscriber_$var->{"topic"}_create(&orte, rcv_$var->{"topic"}_cb, &orte);
838 unless (defined($subscriber_print_data)) {
839 print OUTFILE << "(END)";
840 \tprintf("Subscribers: debug print turned off.\\n");
843 print OUTFILE << "(END)";
845 \tprintf("Subscribers: waiting for data.\\n");
847 \t\tusleep($subscriber_wait_usleep);
850 \t/* orte domain destroy */
851 \t$roboorte_name\_roboorte_destroy(&orte);