| 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 |
| |