blob: d98549ceaf727b6484af60b470ef4e7b446e338d [file] [log] [blame]
require File.dirname(__FILE__) + "/parser.rb"
module Contents
class HasEntry < SimpleField
end
class Priority < SimpleField
def initialize
super :is_number
end
end
class OutputFile
def fillin_initials
@args_struct = nil # string
@status_struct = nil # string
@action_name = nil # string
@actions = []
@has = []
end
def fillin_defaults
@action_name = @base unless @action_name
@actions.push @action_name if @actions.empty?
@args_struct.add_hidden_field 'timespec', 'set_time'
@status_struct.add_hidden_field 'timespec', 'set_time'
end
def parse_token token, tokenizer
case token
when 'args'
throw :syntax_error, '"args" redefined' if @args_struct
@args_struct = Struct.parse tokenizer
when 'status'
throw :syntax_error, '"status" redefined' if @status_struct
@status_struct = Struct.parse tokenizer
when 'action_name'
throw :syntax_error, '"action_name" redefined' if @action_name
@action_name = NameField.parse tokenizer
when 'async_queue'
@actions.push(NameField.parse tokenizer)
when 'has'
@has.push(HasEntry.parse tokenizer)
when 'priority'
throw :syntax_error, '"priority" redefined' if @priority
@priority = Priority.parse tokenizer
else
throw :syntax_error, "unsupported field \"#{token}\""
end
end
def check_format tokenizer
tokenizer.item_missing("args") unless @args_struct
tokenizer.item_missing("status") unless @status_struct
tokenizer.item_missing("priority") unless @priority
end
def superclass
"aos::AsyncAction<#{@args_struct.name}, #{@status_struct.name}>"
end
def impl_class
@action_name + '_t'
end
def handle_class
@action_name + 'Handle'
end
def write_header
f = File.open(filename('h'), "w+")
f.puts <<END
#ifndef AOS_GENERATED_ASYNC_ACTION_#{impl_class}_H_
#define AOS_GENERATED_ASYNC_ACTION_#{impl_class}_H_
// This file is autogenerated.
// Edit #{@filename} to change its contents.
#include "aos/common/messages/QueueHolder.h"
#include "aos/atom_code/async_action/AsyncAction.h"
#include "aos/atom_code/async_action/AsyncActionHandle.h"
namespace #{$namespace} {
#{@args_struct.writer}
#{@status_struct.writer}
class #{impl_class} : public #{superclass} {
virtual void DoAction(#{@args_struct.name} &args __attribute__((unused))){
DoAction(#{@args_struct.params_from 'args'});
}
void DoAction(#{@args_struct.params});
#{@has.grep('OnStart').empty? ? '' : "virtual void OnStart();"}
#{@has.grep('OnEnd').empty? ? '' : "virtual void OnEnd();"}
using #{superclass}::PostStatus;
inline void PostStatus(#{@status_struct.params}){
#{@status_struct.copy_params_into 'new_stat'}
PostStatus(new_stat);
}
public:
#{impl_class}(const std::string name) : #{superclass}(name) {}
#ifdef AOS_#{impl_class}_HEADER_FRAG
AOS_#{impl_class}_HEADER_FRAG
#endif
};
class #{handle_class} : public aos::AsyncActionHandle {
friend class ::AsyncActionTest;
private:
const std::string name;
#{superclass} *instance;
#{superclass} &GetInstance(){
if(instance == NULL){
instance = new #{superclass}(name);
}
return *instance;
}
#{@status_struct.name} temp_status;
void Free(){
if(instance != NULL){
delete instance;
instance = NULL;
}
}
public:
inline uint16_t Start(#{@args_struct.name} &args){
return GetInstance().Start(args);
}
inline uint16_t Start(#{@args_struct.params}){
#{@args_struct.copy_params_into 'args_struct'}
return Start(args_struct);
}
inline void Execute(#{@args_struct.name} &args){
GetInstance().Join(GetInstance().Start(args));
}
inline bool Execute(#{@args_struct.params}){
#{@args_struct.copy_params_into 'args_struct'}
Execute(args_struct);
return GetStatus();
}
inline bool IsDone(){
return GetInstance().IsDone();
}
inline bool IsDone(int32_t count){
return GetInstance().IsDone(count);
}
inline uint16_t Join(){
return GetInstance().Join();
}
inline uint16_t Join(int32_t count){
return GetInstance().Join(count);
}
inline bool GetStatus(#{@status_struct.name} &status_out) __attribute__ ((warn_unused_result)){
return GetInstance().GetStatus(status_out);
}
inline bool GetStatus(#{@status_struct.name} &status_out, int32_t count) __attribute__ ((warn_unused_result)){
return GetInstance().GetStatus(status_out, count);
}
inline bool GetStatus() __attribute__ ((warn_unused_result)){
return GetInstance().GetStatus(temp_status);
}
inline bool GetStatus(int32_t count) __attribute__ ((warn_unused_result)){
return GetInstance().GetStatus(temp_status, count);
}
inline bool GetNextStatus(#{@status_struct.name} &status_out) __attribute__ ((warn_unused_result)){
return GetInstance().GetNextStatus(status_out);
}
inline bool GetNextStatus(#{@status_struct.name} &status_out, int32_t count) __attribute__ ((warn_unused_result)){
return GetInstance().GetNextStatus(status_out, count);
}
inline bool GetNextStatus() __attribute__ ((warn_unused_result)){
return GetInstance().GetNextStatus(temp_status);
}
inline bool GetNextStatus(int32_t count) __attribute__ ((warn_unused_result)){
return GetInstance().GetNextStatus(temp_status, count);
}
inline const #{@status_struct.name} &GetLastStatus(){
return temp_status;
}
inline void Stop(){
GetInstance().Stop();
}
inline void Stop(int32_t count){
GetInstance().Stop(count);
}
#{handle_class}(const std::string name) : name(name), instance(NULL) {}
};
#{(@actions.collect do |a|
<<END2
extern #{handle_class} #{a};
END2
end).join('')}
} // namespace #{$namespace}
#endif
END
f.close
end
def write_cpp
f = File.open(filename('cc'), "w+")
f.puts <<END
// This file is autogenerated.
// Edit #{@filename} to change its contents.
#include "#{filename 'h'}"
namespace #{$namespace} {
#{(@actions.collect do |a|
<<END2
#{handle_class} #{a}("#{a}");
END2
end).join("\n")}
} // namespace #{$namespace}
END
f.close
end
def write_main
f = File.open(filename('main'), "w+")
f.puts <<END
// This file is autogenerated.
// Edit #{@filename} to change its contents.
#include "#{filename 'h'}"
#include "aos/atom_code/async_action/AsyncActionRunner.h"
#include <string>
#include <cstring>
#include <iostream>
int main(int argc, char **argv) {
aos::Init();
std::string name = "#{@action_name}";
if(argc > 1)
name = std::string(argv[1]);
#{$namespace}::#{impl_class} action(name);
int rv = aos::AsyncActionRunner::Run(action, #{@priority});
aos::Cleanup();
return rv;
}
END
f.close
end
end
end
write_file_out