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"
304 /* ----------------------------------------------------------------------
306 * ---------------------------------------------------------------------- */
310 foreach $var (@ortegen) {
311 ($pmsec, $psec) = POSIX::modf($var->{"persistence"});
312 $pmsec = POSIX::floor($pmsec*1000);
313 ($dmsec, $dsec) = POSIX::modf($var->{"pubdelay"});
314 $dmsec = POSIX::floor($dmsec*1000);
315 print OUTFILE << "(END)";
316 void ${roboorte_name}_publisher_$var->{"topic"}_create(struct ${roboorte_name}_orte_data *data, ORTESendCallBack callback, void *arg)
318 \tNtpTime persistence, delay;
320 \t$var->{"type"}_type_register($data_arg_name->$orte_domain);
321 \tNtpTimeAssembFromMs(persistence, $psec, $pmsec);
322 \tNtpTimeAssembFromMs(delay, $dsec, $dmsec);
323 \t$data_arg_name->$publication_prefix$var->{"topic"} = ORTEPublicationCreate(
324 \t\t\t$data_arg_name->$orte_domain, "$var->{"topic"}", "$var->{"type"}",
325 \t\t\t&$data_arg_name->$var->{"topic"}, &persistence, $data_arg_name->strength,
326 \t\t\t$callback_name, $callback_arg, &delay);
333 print OUTFILE << "(END)";
334 /* ----------------------------------------------------------------------
336 * ---------------------------------------------------------------------- */
340 foreach $var (@ortegen) {
341 print OUTFILE << "(END)";
342 void ${roboorte_name}_publisher_$var->{"topic"}_destroy(struct ${roboorte_name}_orte_data *data)
344 \tORTEPublicationDestroy($data_arg_name->$publication_prefix$var->{"topic"});
351 print OUTFILE << "(END)";
352 /* ----------------------------------------------------------------------
354 * ---------------------------------------------------------------------- */
358 foreach $var (@ortegen) {
359 ($mmsec, $msec) = POSIX::modf($var->{"minsep"});
360 $mmsec = POSIX::floor($mmsec*1000);
361 ($dmsec, $dsec) = POSIX::modf($var->{"deadline"});
362 $dmsec = POSIX::floor($dmsec*1000);
363 print OUTFILE << "(END)";
364 void ${roboorte_name}_subscriber_$var->{"topic"}_create(struct ${roboorte_name}_orte_data *data, ORTERecvCallBack callback, void *arg)
366 \tORTESubscription *s;
367 \tNtpTime deadline, minimumSeparation;
369 \t$var->{"type"}_type_register($data_arg_name->$orte_domain);
371 \tNtpTimeAssembFromMs(deadline, $dsec, $dmsec);
372 \tNtpTimeAssembFromMs(minimumSeparation, $msec, $mmsec);
373 \ts = ORTESubscriptionCreate(
374 \t\t\t$data_arg_name->$orte_domain, $subscription_mode, $subscription_type,
375 \t\t\t"$var->{"topic"}", "$var->{"type"}",
376 \t\t\t&$data_arg_name->$var->{"topic"}, &deadline, &minimumSeparation,
377 \t\t\t$callback_name, $callback_arg, $multicast_ip_address);
384 print OUTFILE << "(END)";
386 /* ----------------------------------------------------------------------
387 * ORTE INITILIZATION AND DESTROY
388 * ---------------------------------------------------------------------- */
390 int ${roboorte_name}_roboorte_init(struct ${roboorte_name}_orte_data *data)
393 \tORTEDomainProp prop;
396 \tif ($data_arg_name->strength <= 0)
397 \t\t$data_arg_name->strength = $publication_strength;
399 \tORTEVerbositySetOptions("ALL.0");
400 \tORTEDomainPropDefaultGet(&prop);
401 \tNTPTIME_BUILD(prop.baseProp.refreshPeriod, $refresh_period);
402 \tNTPTIME_BUILD(prop.baseProp.expirationTime, $expiration_time);
403 \t$data_arg_name->$orte_domain = ORTEDomainAppCreate(ORTE_DEFAULT_DOMAIN,
404 \t &prop, NULL, ORTE_FALSE);
405 \tif (!$data_arg_name->$orte_domain) {
406 \t\tprintf("ORTEDomainAppCreate failed!\\n");
413 int ${roboorte_name}_roboorte_destroy(struct ${roboorte_name}_orte_data *data)
415 \treturn ORTEDomainAppDestroy($data_arg_name->$orte_domain);
427 sub generate_makefile {
429 my($makefile) = "Makefile.omk";
431 unless (open (OUTFILE, ">$makefile")) {
432 print "Unable to create $makefile\n";
436 if ($testdir = $options{"T"}) {
437 $testmakefile = "$testdir/$makefile";
438 unless (open (MKOUTFILE, ">$testmakefile")) {
439 print "Unable to create $testmakefile\n";
442 print MKOUTFILE << "(END)";
444 # Automatically generated Makefile file.
445 # \@warning DO NOT EDIT!!!
448 # Robot's ORTE library
452 *MKOUTFILE = *OUTFILE;
453 print OUTFILE << "(END)";
454 # Automatically generated Makefile file.
455 # \@warning DO NOT EDIT!!!
458 # Robot's ORTE library
464 foreach $filename (@files) {
465 $testfilename1 = $test_publisher_name_prefix.$filename;
466 $testfilename2 = $test_subscriber_name_prefix.$filename;
467 $libraryname = $library_name_prefix.$filename;
469 print OUTFILE << "(END)";
470 lib_LIBRARIES += $libraryname
471 $libraryname\_SOURCES = $libraryname.c
472 include_HEADERS += $libraryname.h
476 if ($options{"t"} or $options{"T"}) {
477 print MKOUTFILE << "(END)";
478 test_PROGRAMS += $testfilename1
479 $testfilename1\_SOURCES = $testfilename1.c
480 $testfilename1\_LIBS = pthread $libraryname robottype $ortegenfilenames[$i] orte
482 test_PROGRAMS += $testfilename2
483 $testfilename2\_SOURCES = $testfilename2.c
484 $testfilename2\_LIBS = pthread $libraryname robottype $ortegenfilenames[$i] orte
492 print OUTFILE << "(END)";
496 \t\$(Q)rm -rf *.c *.h Makefile.omk test/
498 `cp -p Makefile $testdir`
500 print OUTFILE << "(END)";
502 \t\$(Q)rm -rf *.c *.h Makefile.omk
517 sub generate_test_publisher {
519 my($testfile) = $test_publisher_name_prefix.$roboorte_name.".c";
522 if ($testdir = $options{"T"}) {
523 $testfile = "$testdir/$testfile";
527 unless (open (OUTFILE, ">$testfile")) {
528 print "Unable to create file $testfile\n";
532 print OUTFILE << "(END)";
534 * Automatically generated test file for RoboORTE libraries.
535 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
544 #include <$library_name_prefix$roboorte_name.h>
546 /* ----------------------------------------------------------------------
547 * PUBLISHER CALLBACKS
548 * ---------------------------------------------------------------------- */
552 foreach $var (@ortegen) {
553 print OUTFILE << "(END)";
554 void send_$var->{"topic"}_cb(const ORTESendInfo *info, void *vinstance,
555 \t\t\tvoid *sendCallBackParam)
562 print OUTFILE << "(END)";
564 /* Thread process. Do the job. */
565 void *process(void *arg)
567 \tstruct $roboorte_name\_orte_data *orte = (struct $roboorte_name\_orte_data*)arg;
575 foreach $var (@ortegen) {
576 my(@var) = (@{$var->{"var"}});
577 print OUTFILE << "(END)";
578 \t\t\t/* $var->{"topic"} */
580 \t\t\t\tprintf("$var->{"topic"}:\\n");
582 foreach $var (@var) {
583 if ($var->{"type"} eq "double") {
584 print OUTFILE << "(END)";
585 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = ($var->{"type"})(rand() % 255);
586 \t\t\t\tprintf("\\t$var->{"topic"} = %f\\n", orte->$var->{"topic"}.$var->{"topic"});
588 } elsif ( $var->{"type"} eq "octet" ) {
589 print OUTFILE << "(END)";
590 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = (unsigned char)(rand() % 255);
591 \t\t\t\tprintf("\\t$var->{"topic"} = 0x%02x\\n", orte->$var->{"topic"}.$var->{"topic"});
593 } elsif ( $var->{"type"} eq "unsigned short" ) {
594 print OUTFILE << "(END)";
595 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = ($var->{"type"})(rand() % 255);
596 \t\t\t\tprintf("\\t$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
599 print OUTFILE << "(END)";
600 \t\t\t\torte->$var->{"topic"}.$var->{"topic"} = (int)(rand() % 255);
601 \t\t\t\tprintf("\\t$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
606 if (defined($publication_callback_enabled)) {
607 print OUTFILE << "(END)";
608 \t\t\t\t/*ORTEPublicationSend(orte->$publication_prefix$var->{"topic"});*/
613 print OUTFILE << "(END)";
614 \t\t\t\tORTEPublicationSend(orte->$publication_prefix$var->{"topic"});
623 print OUTFILE << "(END)";
629 \t\tusleep($publisher_thread_usleep);
634 void start_thread(struct $roboorte_name\_orte_data *orte)
640 \tretcode = pthread_create(&th, NULL, process, orte);
642 \t\tprintf("Failed to create thread %d\\n", retcode);
644 \tretcode = pthread_join(th, &retval);
646 \t\tprintf("Failed to join thread %d\\n", retcode);
649 struct $roboorte_name\_orte_data orte;
652 static void int_handler(int sig)
654 \t$roboorte_name\_roboorte_destroy(&orte);
662 \tsignal(SIGINT, int_handler);
664 \torte.strength = $publication_strength;
666 \t/* orte initialization */
667 \t$roboorte_name\_roboorte_init(&orte);
669 \t/* creating publishers */
672 foreach $var (@ortegen) {
673 if (defined($publication_callback_enabled)) {
674 $publication_callback = "send_".$var->{"topic"}."_cb";
676 $publication_callback = "NULL";
679 print OUTFILE << "(END)";
680 \t$roboorte_name\_publisher_$var->{"topic"}_create(&orte, $publication_callback, &orte);
684 print OUTFILE << "(END)";
686 \tprintf("Publishers: sending data.\\n");
688 \t/* start thread and do the job */
689 \tstart_thread(&orte);
691 \t/* orte domain destroy */
692 \t$roboorte_name\_roboorte_destroy(&orte);
707 sub generate_test_subscriber {
709 my($testfile) = $test_subscriber_name_prefix.$roboorte_name.".c";
711 if ($testdir = $options{"T"}) {
712 $testfile = "$testdir/$testfile";
716 unless (open (OUTFILE, ">$testfile")) {
717 print "Unable to create file $testfile\n";
721 print OUTFILE << "(END)";
723 * Automatically generated test file for RoboORTE libraries.
724 * \@warning DO NOT EDIT!!! Instead modify the *.ortegen and config file.
732 #include <sys/time.h>
734 #include <$library_name_prefix$roboorte_name.h>
743 \tgettimeofday(&tv, NULL);
744 \tcurtime = tv.tv_sec;
745 \tstrftime(buffer, 30, "[%T.", localtime(&curtime));
746 \tprintf("%s%ld]\\n", buffer, tv.tv_usec);
749 /* ----------------------------------------------------------------------
750 * SUBSCRIBER CALLBACKS
751 * ---------------------------------------------------------------------- */
755 foreach $var (@ortegen) {
756 print OUTFILE << "(END)";
757 void rcv_$var->{"topic"}_cb(const ORTERecvInfo *info, void *vinstance,
758 \t\t\tvoid *recvCallBackParam)
760 \tstruct $roboorte_name\_orte_data *orte =
761 \t\t\t(struct $roboorte_name\_orte_data *)recvCallBackParam;
763 \tswitch (info->status) {
766 if (defined($subscriber_print_data)) {
767 print OUTFILE << "(END)";
769 \t\t\tprintf("\\t$var->{"topic"}:\\n");
771 my(@var) = (@{$var->{"var"}});
772 foreach $var (@var) {
773 print OUTFILE << "(END)";
774 \t\t\t\tprintf("\\t\\t");
776 if ($var->{"type"} eq "double") {
777 print OUTFILE << "(END)";
778 \t\t\t\tprintf("$var->{"topic"} = %f\\n", orte->$var->{"topic"}.$var->{"topic"});
780 } elsif ( $var->{"type"} eq "octet" ) {
781 print OUTFILE << "(END)";
782 \t\t\t\tprintf("$var->{"topic"} = 0x%02x\\n", orte->$var->{"topic"}.$var->{"topic"});
785 print OUTFILE << "(END)";
786 \t\t\t\tprintf("$var->{"topic"} = %d\\n", orte->$var->{"topic"}.$var->{"topic"});
792 print OUTFILE << "(END)";
795 \t\t\tprintf("ORTE deadline occurred - $var->{"topic"} receive\\n");
803 print OUTFILE << "(END)";
804 struct $roboorte_name\_orte_data orte;
807 static void int_handler(int sig)
809 \t$roboorte_name\_roboorte_destroy(&orte);
815 \tsignal(SIGINT, int_handler);
817 \t/* orte initialization */
818 \t$roboorte_name\_roboorte_init(&orte);
820 \t/* creating subscribers */
823 foreach $var (@ortegen) {
824 print OUTFILE << "(END)";
825 \t$roboorte_name\_subscriber_$var->{"topic"}_create(&orte, rcv_$var->{"topic"}_cb, &orte);
829 unless (defined($subscriber_print_data)) {
830 print OUTFILE << "(END)";
831 \tprintf("Subscribers: debug print turned off.\\n");
834 print OUTFILE << "(END)";
836 \tprintf("Subscribers: waiting for data.\\n");
838 \t\tusleep($subscriber_wait_usleep);
841 \t/* orte domain destroy */
842 \t$roboorte_name\_roboorte_destroy(&orte);