| /**************************************************************************** | |
| ** OrangeBot Project | |
| ***************************************************************************** | |
| ** / | |
| ** / | |
| ** / | |
| ** ______ \ | |
| ** \ | |
| ** \ | |
| ***************************************************************************** | |
| ** UNIVERSAL PARSER | |
| ***************************************************************************** | |
| ** Author: Orso Eric | |
| ** Creation Date: 2019-06-17 | |
| ** Last Edit Date: 2020-01-15 | |
| ** Revision: 2 | |
| ** Version: 5.0 | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ** DESCRIPTION | |
| ***************************************************************************** | |
| ** Do a universal parser that does not require malloc/free and do not use explicit dictionary | |
| ** I create a special register command function in which the message and an handler is provided | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ** COMMAND RULES | |
| ***************************************************************************** | |
| ** ADD COMMAND TO PARSER | |
| ** A command is composed by fixed alphanumeric chars and argument descriptors | |
| ** Each command is associated with a unique function callback | |
| ** A command can only start with letters | |
| ** | |
| ** EXAMPLE ADD COMMAND TO PARSER | |
| ** myparser.add_cmd("P", (void *)&my_ping_handler ); | |
| ** Add a new command that is triggered when the string P\0 is received. | |
| ** function my_ping_handler will be automatically executed when the \0 is processed | |
| ** myparser.parse( 'P' ); | |
| ** myparser.parse( '\0' ); | |
| ** send manually bytes to the parser to test the system | |
| ***************************************************************************** | |
| ** Command restriction: | |
| ** >Can only start with a letter | |
| ** >Valid arguments are %u %s %U %S %d %D | |
| ** >There can be no commands with same start but two different argument type. Only the first one will be considered in case | |
| ** PWM%d... | |
| ** PWM%u... | |
| ** The parser has no way of knowing if the incoming input (example 10) is meant for one command or the other | |
| ** >After valid ID access parameters using Parser Macros | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ** KNOWN BUG | |
| ***************************************************************************** | |
| ** | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ** INCLUDES | |
| ****************************************************************************/ | |
| //#include <iostream> | |
| //Class Header | |
| /**************************************************************************** | |
| ** NAMESPACES | |
| ****************************************************************************/ | |
| namespace Orangebot | |
| { | |
| /**************************************************************************** | |
| ** GLOBAL VARIABILES | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** CONSTRUCTORS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /***************************************************************************/ | |
| //! @brief Empty Constructor | |
| //! Uniparser | void | |
| /***************************************************************************/ | |
| // @param | |
| //! @return no return | |
| //! @details | |
| //! Empty constructor | |
| /***************************************************************************/ | |
| Uniparser::Uniparser( void ) | |
| { | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //! @details algorithm: | |
| //Initialize structure to safe values | |
| this -> init(); | |
| //Pass a terminator to the parser to have it initialize itself | |
| this -> parse( '\0' ); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| return; | |
| } //end constructor: | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** DESTRUCTORS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /***************************************************************************/ | |
| //! @brief Empty Destructor | |
| //! Uniparser | void | |
| /***************************************************************************/ | |
| // @param | |
| //! @return no return | |
| //! @details | |
| //! Empty destructor | |
| /***************************************************************************/ | |
| Uniparser::~Uniparser( void ) | |
| { | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //! @details algorithm: | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| return; | |
| } //end destructor: | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** OPERATORS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** SETTERS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** GETTERS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /***************************************************************************/ | |
| //! @brief Public Getter | |
| //! get_error | void | |
| /***************************************************************************/ | |
| //! @return Err_codes | error code | |
| //! @details | |
| //! Get current error code of the parser | |
| /***************************************************************************/ | |
| Err_codes Uniparser::get_error( void ) | |
| { | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| return this -> g_err; | |
| } //end destructor: get_error | void | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** TESTERS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** PUBLIC METHODS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! add_command | const char *, void * | |
| /***************************************************************************/ | |
| //! @param cmd | const char * Text that will trigger the command | |
| //! @param handler | void * Pointer to callback function for this command | |
| //! @return bool | false: OK | true: fail | |
| //! @details | |
| //! Add a string and a function pointer to the parser | |
| //! @todo check that command is valid | |
| /***************************************************************************/ | |
| bool Uniparser::add_cmd( const char *cmd, void *handler ) | |
| { | |
| DENTER_ARG("cmd: %p >%s<\n", (void *)cmd, cmd ); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //index | |
| uint8_t t; | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //if: input is invalid | |
| if ((cmd == nullptr) || (handler == nullptr)) | |
| { | |
| this -> g_err = ERR_INVALID_CMD; | |
| DRETURN_ARG("ERR%d: ERR_INVALID_CMD\n", this -> g_err); | |
| return true; //fail | |
| } | |
| //If: num command is invalid | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && ((this -> g_num_cmd < 0) || (this->g_num_cmd >= UNIPARSER_MAX_CMD)) ) | |
| { | |
| this -> g_err = ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //if: maximum number of command has been reached | |
| if (this -> g_num_cmd >= (UNIPARSER_MAX_CMD-1)) | |
| { | |
| this -> g_err = ERR_ADD_MAX_CMD; | |
| DRETURN_ARG("ERR%d: ERR_ADD_MAX_CMD in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| // check the validity of the string | |
| bool f_ret = this -> chk_cmd((const uint8_t *)cmd); | |
| //If: command had a syntax error | |
| if (f_ret == true) | |
| { | |
| DRETURN_ARG("command didnt get past argument descriptor check\n"); | |
| return true; //FAIL | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Fetch currently used command | |
| t = this -> g_num_cmd; | |
| //Link command handler and command text | |
| this -> g_cmd_txt[t] = (uint8_t *)cmd; | |
| this -> g_cmd_handler[t] = handler; | |
| DPRINT("Command >%s< with handler >%p< has been added with index: %d\n", cmd, (void *)handler, t); | |
| //A command has been added | |
| this -> g_num_cmd = t +1; | |
| DPRINT("Total number of commands: %d\n", this -> g_num_cmd); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN(); | |
| return false; | |
| } //end method: add_command | const char *, void * | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! parse | char | |
| /***************************************************************************/ | |
| //! @param data | uint8_t | incoming character to be processed through the universal parser | |
| //! @return bool | false = OK | true = A runtime error occurred | |
| //! @details | |
| //! Intricate FSM. The objective is to check the incoming character against | |
| //! charaters inside the various commands and decode a command when a \0 is detected | |
| /***************************************************************************/ | |
| bool Uniparser::parse( uint8_t data ) | |
| { | |
| if ((data < '0') || (data > 'z')) | |
| { | |
| DENTER_ARG("exe: >0x%x<\n", data ); | |
| } | |
| else | |
| { | |
| DENTER_ARG("exe: >0x%x< >%c<\n", data, data ); | |
| } | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //when true, reset the FMS | |
| bool f_rst_fsm = false; | |
| //Index of the handler to be executer | |
| int8_t exe_index = -1; | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // CLEAR ERROR | |
| //---------------------------------------------------------------- | |
| // User was notified of the error during previous call | |
| // Errors should have triggered an FSM reset to return in working condition | |
| // I can clear the error and keep churning bytes | |
| //If: an error was reported | |
| if (this -> g_err != Err_codes::NO_ERR) | |
| { | |
| //Clear the error | |
| DPRINT("%d | Clear Error: %d\n", __LINE__, this -> g_err); | |
| this -> g_err = Err_codes::NO_ERR; | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // TERMINATOR | |
| //---------------------------------------------------------------- | |
| //! @details when terminator is detected, close the command. | |
| //! I either have a full match, or the command is invalid and I have to reset the FSM | |
| //If: input terminator from user | |
| if (data == '\0') | |
| { | |
| DPRINT("%d | Terminator detected | Number of partial matches: %d\n", __LINE__, this -> g_num_match); | |
| //counter | |
| uint8_t t; | |
| //If: i was decoding an argument | |
| if (this -> g_status == Orangebot::Parser_status::PARSER_ARG) | |
| { | |
| //I'm done decoding | |
| DPRINT("%d | Terminator after ARG\n", __LINE__); | |
| //Close current argument and update the argument detector FSM. | |
| bool f_ret = this -> close_arg(); | |
| //if could not close argument | |
| if (f_ret == true) | |
| { | |
| //I can recover from this. | |
| //no matches and reset the FSM. | |
| this -> g_num_match = 0; | |
| } | |
| } | |
| //Index inside the command | |
| uint8_t cmd_index; | |
| //if: I have at least one parser_tmp.id_index entry | |
| if (this -> g_num_match > 0) | |
| { | |
| DPRINT("%d | Scanning partially matched commands for terminators\n", __LINE__); | |
| //For: scan all commands | |
| for (t = 0;t<this -> g_num_cmd;t++) | |
| { | |
| //Fetch command index | |
| cmd_index = this -> g_cmd_index[t]; | |
| //If: this command is a partial match | |
| if (cmd_index > 0) | |
| { | |
| //If: i was decoding an argument | |
| if (this -> g_status == Parser_status::PARSER_ARG) | |
| { | |
| //If: index is not pointing to an argument descriptor inside the command | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[t][cmd_index] != '%')) | |
| { | |
| DPRINT("ERR: This command should have an argument descriptor in this position. | cmd: %d | cmd_index: %d | actual content: >0x%x<\n", t, cmd_index, this -> g_cmd_txt[t][cmd_index]); | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //The argument has been closed. I need to skip the argument descriptor "%?" | |
| cmd_index += 2; | |
| //With argument closed I'm now doing an ID matching for terminator. Can be skipped since it's the last char | |
| this -> g_status = Parser_status::PARSER_ID; | |
| //I should write back the index. Can be skipped since it's the last char | |
| this -> g_cmd_index[t] = cmd_index; | |
| } | |
| //Check match against the character after the one already matched. | |
| //If: the next command data would be the terminator '\0' | |
| if ( this -> g_cmd_txt[t][ cmd_index ] == '\0') | |
| { | |
| //If there is a pending execution already | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (exe_index != -1)) | |
| { | |
| //this should never happen | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //Issue execution of the callback function linked | |
| exe_index = t; | |
| DPRINT("Valid command ID%d decoded\n", t); | |
| //I can stop the search | |
| t = this -> g_num_cmd; | |
| } | |
| //If: command would keep on going | |
| else | |
| { | |
| DPRINT("%d | no match in %x cmd %x | ", __LINE__ ,data , this -> g_cmd_txt[t][ cmd_index ] ); | |
| } | |
| } //End If: this command is a partial match | |
| } //End For: scan all commands | |
| } //end if: I have at least one parser_tmp.id_index entry | |
| //If I have just one match. g_num_match now holds the index of the match shifted by one | |
| else if (this -> g_num_match < 0) | |
| { | |
| //decode command index | BUGFIX: -1 means only one match of command ID 0 | |
| t = -this -> g_num_match -1; | |
| DPRINT("just one partial match: %d\n", t); | |
| //Fetch command index | |
| cmd_index = this -> g_cmd_index[t]; | |
| //If: i was decoding an argument | |
| if (this -> g_status == Parser_status::PARSER_ARG) | |
| { | |
| //If: index is not pointing to an argument descriptor inside the command | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[t][cmd_index] != '%')) | |
| { | |
| DPRINT("ERR: This command should have an argument descriptor in this position. | cmd: %d | cmd_index: %d | actual content: >0x%x<\n", t, cmd_index, this -> g_cmd_txt[t][cmd_index]); | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //The argument has been closed. I need to skip the argument descriptor "%?" | |
| cmd_index += 2; | |
| //With argument closed I'm now doing an ID matching for terminator. Can be skipped since it's the last char | |
| //this -> g_status == Parser_status::PARSER_ID; | |
| } | |
| //BUGFIX: this branch can now be executed with null pointer if dictionary is yet to be initialized. This is not a pedantic check | |
| //Check match against the character after the one already matched. | |
| //If: the next command data would be the terminator '\0' | |
| if ((this -> g_cmd_txt[t] != nullptr) && (this -> g_cmd_txt[t][ cmd_index ] == '\0')) | |
| { | |
| //If there is a pending execution already | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (exe_index != -1)) | |
| { | |
| //this should never happen | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //Issue execution of the callback function linked | |
| exe_index = t; | |
| DPRINT("%d | Valid command ID%d decoded\n", __LINE__, t); | |
| //I can stop the search | |
| t = this -> g_num_cmd; | |
| } | |
| //BUGFIX: this branch can now be executed with null pointer if dictionary is yet to be initialized. This is not a pedantic check | |
| //if: I'm given a terminator but dictionary does not contain a terminator | |
| else | |
| { | |
| if (this -> g_cmd_txt[t] != nullptr) | |
| { | |
| //This happen if user gives a command that lack one char | |
| DPRINT("%d | no match. given: >0x%x< expected: >0x%x<\n" ,__LINE__, data , this -> g_cmd_txt[t][ cmd_index ] ); | |
| } | |
| else | |
| { | |
| //This happen if user gives a command that lack one char | |
| DPRINT("%d | Dictionary entry is nullptr. Maybe dictionary is yet to be initialized? Dictionary entry: %d\n",__LINE__, t ); | |
| } | |
| //Issue a FSM reset | |
| f_rst_fsm = true; | |
| } //End if: I'm given a terminator but dictionary does not contain a terminator | |
| } //End If: I have just one match g_num_match now holds the index of the match shifted by one | |
| //If: exactly zero matches. | |
| else | |
| { | |
| DPRINT("%d | No partial matches\n", __LINE__ ); | |
| } | |
| //Issue a FSM reset | |
| f_rst_fsm = true; | |
| } //End If: input terminator from user | |
| //-------------------------------------------------------------------------- | |
| // PARSER_IDLE | |
| //-------------------------------------------------------------------------- | |
| // Only letters can be used as first character in a command | |
| // This section matches the first character in each command | |
| // This section takes care of initializing g_cmd_index[] to valid partial match values | |
| //If: PARSER_IDLE | |
| else if (this -> g_status == Parser_status::PARSER_IDLE) | |
| { | |
| DPRINT("%d | PARSER_IDLE\n", __LINE__); | |
| //If: letter First character in a command can only be a letter | |
| if (IS_LETTER( data )) | |
| { | |
| //counter | |
| uint8_t t; | |
| //for each command | |
| for (t = 0; t < this -> g_num_cmd;t++) | |
| { | |
| //if: dictionary is unlinked | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[t] == nullptr)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("%d | ERR%d: ERR_GENERIC\n", __LINE__, this -> g_err ); | |
| return true; //fail | |
| } | |
| //If: partial match | |
| if (this -> g_cmd_txt[t][0] == data) | |
| { | |
| //A partial match has been found | |
| this -> g_num_match++; | |
| //Match has been found up to first character. Point to the next unmatched char | |
| this -> g_cmd_index[t] = 1; | |
| //Next, I'm matching ID entries | |
| this -> g_status = Parser_status::PARSER_ID; | |
| //TIP: I can't speculatively detect % here because two commands may have the same first section and diverge later. | |
| DPRINT("%d | Match command %d, total partial matches: %d\n", __LINE__, t, this -> g_num_match); | |
| } | |
| //if: no match | |
| else | |
| { | |
| //special code for no match found | |
| this -> g_cmd_index[t] = 0; | |
| } | |
| } //end for: each command | |
| } //End If: letter | |
| //Non letter can never be a first character | |
| else | |
| { | |
| //Issue a FSM reset | |
| f_rst_fsm = true; | |
| } | |
| } //End If: PARSER_IDLE | |
| //-------------------------------------------------------------------------- | |
| // ID matching | |
| //-------------------------------------------------------------------------- | |
| //if: I'm ID matching | |
| else if (this -> g_status == Parser_status::PARSER_ID) | |
| { | |
| DPRINT("%d | PARSER_ID ", __LINE__); | |
| //! @todo only go ARG if a command has an arg descriptor if there are number or sign. allow number or sign to be used as command ID | |
| //if: I'm being fed an argument | |
| if (IS_NUMBER( data ) || IS_SIGN( data )) | |
| { | |
| DPRINT_NOTAB("- ARG | num_match %d\n", this -> g_num_match); | |
| //if: I have at least one partial match | |
| if (this -> g_num_match > 0) | |
| { | |
| //for each dictionary command | |
| for (uint8_t t = 0;t < this -> g_num_cmd;t++) | |
| { | |
| //if: the command is a partial match | |
| if (this -> g_cmd_index[t] > 0) | |
| { | |
| //Search in the dictionary for a % entry. An argument descriptor | |
| if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == '%') | |
| { | |
| //Do not increment index but go in ARG parsing mode | |
| this -> g_status = Parser_status::PARSER_ARG; | |
| //Do not advance index until argument decoding is complete | |
| DPRINT("%d | ARG begins | command: %d\n", __LINE__, t); | |
| //Add an argument using current partial match as template | |
| bool f_ret = this -> add_arg( t ); | |
| //if: adding argument failed | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) | |
| { | |
| this -> error_handler( Err_codes::ERR_ADD_ARG ); | |
| DPRINT("%d | ERR Failed to add an argument\n", __LINE__ ); | |
| //I can recover from this by resetting the FSM | |
| f_rst_fsm = true; | |
| } | |
| //initialize agrument | |
| this -> accumulate_arg( data ); | |
| //argument detection make the detection unique. Remove all other partial matches | BUGFIX: now negative index is shifted by one | |
| this -> g_num_match = -t -1; | |
| //Single match has been found. Break the cycle | |
| t = UNIPARSER_MAX_CMD; | |
| } | |
| //If: this dictionary entry does not contain an argument descriptor | |
| else | |
| { | |
| //Prune away the partial match | |
| this -> g_cmd_index[t] = 0; | |
| DPRINT("%d | Prune away partial match: %d | ", __LINE__, t); | |
| //if: I still have partial matches after pruning | |
| if (this -> g_num_match >= 2) | |
| { | |
| //One fewer partial match | |
| this -> g_num_match--; | |
| DPRINT_NOTAB(" num_match: %d\n", this -> g_num_match ); | |
| } | |
| //if: all partial matches have been pruned away | |
| else | |
| { | |
| //No more commands. Reset the machine | |
| f_rst_fsm = true; | |
| //No more matches. Can breack cycle early | |
| t = UNIPARSER_MAX_CMD; | |
| DPRINT_NOTAB("%d | Last partial match has been pruned away... RESET\n", __LINE__); | |
| //! @todo command refeed function. Safe and refeed last char to detect other partial commands | |
| } | |
| } //End If: this dictionary entry does not contain an argument descriptor | |
| } //End if: the command is a partial match | |
| //If: this commnd did not match to begin with | |
| else | |
| { | |
| //do nothing | |
| } | |
| } //end for each dictionary command | |
| } //end if: I have at least one partial match | |
| //If I only have one match | BUGFIX: single match is now shifted by one | |
| else if (this -> g_num_match < 0) | |
| { | |
| //decode command index | |
| uint8_t t = -this -> g_num_match -1; | |
| //Search in the dictionary for a % entry. An argument descriptor | |
| if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == '%') | |
| { | |
| //! This is the first char of an argument | |
| //Do not increment index but go in ARG parsing mode | |
| this -> g_status = Parser_status::PARSER_ARG; | |
| //Do not advance index until argument decoding is complete | |
| DPRINT("%d | ARG begins | command: %d\n", __LINE__, t); | |
| //Add an argument using current partial match as template | |
| bool f_ret = this -> add_arg( t ); | |
| //if: adding argument failed | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| //I can recover from this by resetting the FSM | |
| f_rst_fsm = true; | |
| } | |
| //! accumulate argument character inside argument. | |
| f_ret = this -> accumulate_arg( data ); | |
| //if: adding argument failed | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| //I can recover from this by resetting the FSM | |
| f_rst_fsm = true; | |
| } | |
| } | |
| } //If I only have one match | |
| //If: I had no matches to begin with | |
| else | |
| { | |
| //DO nothing | |
| } | |
| } //end if: I'm being fed an argument | |
| //if: I'm matching a non argument non terminator | |
| else | |
| { | |
| DPRINT_NOTAB("- ID\n"); | |
| //if: I have at least one partial match | |
| if (this -> g_num_match > 0) | |
| { | |
| //If I have just one match, I can upgrade num_match to skip for next time | |
| bool f_match = (this -> g_num_match == 1); | |
| //for each dictionary command | |
| for (uint8_t t = 0;t < this -> g_num_cmd;t++) | |
| { | |
| //if: the command is a partial match | |
| if (this -> g_cmd_index[t] > 0) | |
| { | |
| //check that the dictionary holds the same value as data | |
| if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == data) | |
| { | |
| //Advance to the next dictionary entry for this command | |
| this -> g_cmd_index[t]++; | |
| //if: This is the sole partial match surviving | |
| if (f_match == true) | |
| { | |
| //Save the index inside num match to skip the for next time | BUGFIX: Now single match is shifted by one | |
| this -> g_num_match = -t -1; | |
| //Single match has been found. Break the cycle | |
| t = UNIPARSER_MAX_CMD; | |
| DPRINT("%d | Only one partial match remains. Num_match: %d\n", __LINE__, this -> g_num_match); | |
| } | |
| } | |
| //Else: this dictionary entry does not contain an argument descriptor | |
| else | |
| { | |
| //Prune away the partial match | |
| this -> g_cmd_index[t] = 0; | |
| DPRINT("%d | Prune away partial match: %d | ", __LINE__, t); | |
| //if: I still have partial matches after pruning | |
| if (this -> g_num_match >= 2) | |
| { | |
| //One fewer partial match | |
| this -> g_num_match--; | |
| DPRINT_NOTAB(" num_match: %d\n", this -> g_num_match ); | |
| } | |
| //if: all partial matches have been pruned away | |
| else | |
| { | |
| //No more commands. Reset the machine | |
| f_rst_fsm = true; | |
| //No more matches. Can breack cycle early | |
| t = UNIPARSER_MAX_CMD; | |
| DPRINT_NOTAB("Last partial match has been pruned away... RESET\n"); | |
| //! @todo replay system. Safe and refeed last char to detect other partial commands | |
| } | |
| } | |
| } //End if: the command is a partial match | |
| //if: the command was pruned away long ago | |
| else | |
| { | |
| //do nothing | |
| } | |
| } //end for each dictionary command | |
| } //end if: I have at least one partial match | |
| //BUGFIX: If the only match is also entry 0 | |
| //If I only have one match | |
| else //if (this -> g_num_match <= 0) | |
| { | |
| //decode command index | BUGFIX: Now single match is shifted by one | |
| uint8_t t = -this -> g_num_match -1; | |
| //check that the dictionary holds the same value as data | |
| if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == data) | |
| { | |
| //Match! Scan next entry | |
| this -> g_cmd_index[t]++; | |
| DPRINT("%d | Match still valid...\n", __LINE__); | |
| } | |
| //no match | |
| else | |
| { | |
| //Last partial match has been pruned away. Issue a FSM reset | |
| f_rst_fsm = true; | |
| DPRINT("%d | Last match was pruned away. Expected >0x%x< got >0x%x< instead\n", __LINE__, this -> g_cmd_txt[t][ this -> g_cmd_index[t] ], data); | |
| } | |
| } //If I only have one match | |
| } //end if: I'm matching a non argument non terminator | |
| } //end if: I'm ID matching | |
| //-------------------------------------------------------------------------- | |
| // ARG decoder | |
| //-------------------------------------------------------------------------- | |
| //if: I'm decoding arguments | |
| else if (this -> g_status == Parser_status::PARSER_ARG) | |
| { | |
| DPRINT("%d | PARSER_ARG\n", __LINE__); | |
| //If: I'm fed a number | |
| if (IS_NUMBER(data)) | |
| { | |
| //! accumulate argument character inside argument. | |
| bool f_ret = this -> accumulate_arg( data ); | |
| //if: adding argument failed | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| //I can recover from this by resetting the FSM | |
| f_rst_fsm = true; | |
| } | |
| //Do not advance to next dictionary entry | |
| } //If: I'm fed a number | |
| //if: I'm fed a non number | |
| else | |
| { | |
| DPRINT("Closing argument\n"); | |
| //! Exit argument mode | |
| //Close current argument and update argument FSM | |
| this -> close_arg(); | |
| //BUGFIX: If the only match is also entry 0 | |
| //if: I have multiple matches. I should have just one match by this point. | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_num_match > 0)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| //I can recover from this by resetting the FSM | |
| f_rst_fsm = true; | |
| } | |
| else | |
| { | |
| //After argument, I can only have one match. | BUGFIX: Now single match is shifted by one | |
| uint8_t cmd_id = -this -> g_num_match -1; | |
| //Update the parser index by skipping % and the argument descriptor | |
| this -> g_cmd_index[ cmd_id ] += 2; | |
| uint8_t u8_index = this -> g_cmd_index[ cmd_id ]; | |
| //Get the next cmd match | |
| uint8_t u8_next_cmd_id = this -> g_cmd_txt[ cmd_id ][ u8_index ]; | |
| DPRINT("%d | Expected CMD ID %d | Got CMD ID %d\n", __LINE__, this -> g_cmd_txt[ cmd_id ][ u8_index ], data); | |
| //check that the dictionary holds the same value as data | |
| if (u8_next_cmd_id == data) | |
| { | |
| //Advance to the next dictionary entry for this command | |
| this -> g_cmd_index[ cmd_id ]++; | |
| } | |
| //No match | |
| else | |
| { | |
| DPRINT("%d | Pruning away last match\n", __LINE__ ); | |
| //I can recover from this by resetting the FSM | |
| f_rst_fsm = true; | |
| } | |
| this -> g_status = Parser_status::PARSER_ID; | |
| } | |
| } //if: I'm fed a non number | |
| } //if: I'm decoding arguments | |
| //---------------------------------------------------------------- | |
| // FSM RESET | |
| //---------------------------------------------------------------- | |
| //! @detail | |
| //! FSM reset. Clear up the machine for the next clean execution | |
| //If: a reset was issued | |
| if (f_rst_fsm == true) | |
| { | |
| DPRINT("%d | FSM RESET\n", __LINE__); | |
| //Clear reset flag | |
| f_rst_fsm = false; | |
| //Status becomes IDLE | |
| this -> g_status = Orangebot::Parser_status::PARSER_IDLE; | |
| //I have no partial matches anymore | |
| this -> g_num_match = 0; | |
| //If I don't have a pending execution | |
| if (exe_index == -1) | |
| { | |
| //Reset the argument decoder and prepare for a new command | |
| this -> init_arg_decoder(); | |
| } | |
| } //If: a reset was issued | |
| //---------------------------------------------------------------- | |
| // HANDLER EXECUTION | |
| //---------------------------------------------------------------- | |
| //! @detail | |
| //! FSM reset. Clear up the machine for the next clean execution | |
| //If: an execution event has been launched | |
| if (exe_index > -1) | |
| { | |
| //if execution index is out of range. | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (exe_index == this -> g_num_cmd)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| DPRINT("%d | Executing handler of command %d | num arguments: %d\n", __LINE__, exe_index, this -> g_arg_fsm_status.num_arg); | |
| //Execute handler of given function. Automatically deduce arguments from argument vector | |
| this -> execute_callback( this ->g_cmd_handler[exe_index] ); | |
| //Reset the argument decoder and prepare for a new command | |
| this -> init_arg_decoder(); | |
| } //If: a reset was issued | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| //Trace Return from main | |
| DRETURN_ARG("Err_code: %d\n", this -> g_err); | |
| //Inform the caller that an error occurred | |
| return (this -> g_err != Err_codes::NO_ERR); | |
| } //end method: parse | char | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** PUBLIC STATIC METHODS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /**************************************************************************** | |
| ***************************************************************************** | |
| ** PRIVATE METHODS | |
| ***************************************************************************** | |
| ****************************************************************************/ | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! init | void | |
| /***************************************************************************/ | |
| //! @return no return | |
| //! @details | |
| //! initialize structure | |
| /***************************************************************************/ | |
| inline void Uniparser::init( void ) | |
| { | |
| DENTER(); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //counter | |
| uint8_t t; | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //! @details initialize structure | |
| //No commands are currently loaded inside the parser | |
| this -> g_num_cmd = 0; | |
| //for: each possible command | |
| for (t = 0;t < UNIPARSER_MAX_CMD;t++) | |
| { | |
| //command has no txt identifier linked | |
| this -> g_cmd_txt[t] = nullptr; | |
| //command has no function handler linked | |
| this -> g_cmd_handler[t] = nullptr; | |
| } | |
| //I have no partial matches | |
| this -> g_num_match = 0; | |
| //FSM begins in idle | |
| this -> g_status = Orangebot::Parser_status::PARSER_IDLE; | |
| //No error | |
| this -> g_err = Orangebot::Err_codes::NO_ERR; | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| //Trace Return from main | |
| DRETURN(); | |
| return; //OK | |
| } //end method: init | void | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! init_arg_decoder | void | |
| /***************************************************************************/ | |
| //! @details | |
| //! initialize argument decoder for a new command | |
| /***************************************************************************/ | |
| inline void Uniparser::init_arg_decoder( void ) | |
| { | |
| //Trace Enter with arguments | |
| DENTER(); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //! @details algorithm: | |
| //Prepare the argument descriptor. zero arguments are in store | |
| this -> g_arg_fsm_status.num_arg = 0; | |
| //First free slot in the argument vector is the first byte | |
| this -> g_arg_fsm_status.arg_index = 0; | |
| //if sign is not specified, default argument sign is plus | |
| this -> g_arg_fsm_status.arg_sign = false; | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| //Trace Return vith return value | |
| DRETURN(); | |
| return; //OK | |
| } //end method: init_arg_decoder | void | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! chk_cmd | const uint8_t * | |
| /***************************************************************************/ | |
| //! @param cmd | | |
| //! @return syntax error | bool | false: OK | true: error detected. Code handled by the error handler | |
| //! @details | |
| //! Check command syntax to prevent bad commands from being loaded in the dictionary | |
| //! Saves runtime check for bad dictionary entries | |
| /***************************************************************************/ | |
| bool Uniparser::chk_cmd( const uint8_t *cmd ) | |
| { | |
| //Trace Enter with arguments | |
| DENTER_ARG("cmd: %p\n", (void *)cmd); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //Counter | |
| uint8_t t; | |
| //Total argument size used | |
| uint8_t arg_cnt = 0; | |
| //Number of arguments | |
| uint8_t arg_type_cnt = 0; | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If a null pointer function handler was given | |
| if (cmd == nullptr) | |
| { | |
| this -> error_handler( Err_codes::SYNTAX_BAD_POINTER ); | |
| DRETURN_ARG("ERR%d: | Bad handler function pointer\n", Err_codes::SYNTAX_BAD_POINTER); | |
| return true; //FAIL | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //if: first char is not a letter | |
| if (!IS_LETTER( cmd[0] )) | |
| { | |
| this -> error_handler( Err_codes::SYNTAX_FIRST_NOLETTER ); | |
| DRETURN_ARG("ERR%d | First character of a command must be a letter\n", Err_codes::SYNTAX_FIRST_NOLETTER); | |
| return true; //FAIL | |
| } | |
| //Initialize counter | |
| t = 1; | |
| //While: parsing is not done | |
| while ((cmd[t] != '\0') && (t < UNIPARSER_MAX_CMD_LENGTH)) | |
| { | |
| //if: argument descriptor | |
| if (cmd[t] == '%') | |
| { | |
| //!Check number of arguments | |
| //i have an argument descriptor | |
| arg_type_cnt++; | |
| //if: exceed number of arguments | |
| if (arg_type_cnt > UNIPARSER_MAX_ARGS) | |
| { | |
| this -> error_handler( Err_codes::SYNTAX_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR%d in line %d | too many arguments in this command %d\n", Err_codes::SYNTAX_TOO_MANY_ARGS, __LINE__, arg_type_cnt); | |
| return true; //FAIL | |
| } | |
| //!Check back to back arguments | |
| //if: two arguments back to back | |
| if ( (t >= 2) && (cmd[t -2] == '%') ) | |
| { | |
| this -> error_handler( Err_codes::SYNTAX_ARG_BACKTOBACK ); | |
| DRETURN_ARG("ERR%d in line %d | Two back to back arguments were given. Add a character in between them\n", Err_codes::SYNTAX_ARG_BACKTOBACK, __LINE__); | |
| return true; //FAIL | |
| } | |
| //!Check total size of arguments | |
| //Skip the argument descriptor | |
| t++; | |
| //Switch: argument type | |
| switch( cmd[t] ) | |
| { | |
| //Decode type | |
| case Arg_type::ARG_U8: | |
| { | |
| //Accumulate | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| break; | |
| } | |
| //Decode type | |
| case Arg_type::ARG_S8: | |
| { | |
| //Accumulate | |
| arg_cnt += Arg_size::ARG_S8_SIZE; | |
| break; | |
| } | |
| //Decode type | |
| case Arg_type::ARG_U16: | |
| { | |
| //Accumulate | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| break; | |
| } | |
| //Decode type | |
| case Arg_type::ARG_S16: | |
| { | |
| //Accumulate | |
| arg_cnt += Arg_size::ARG_S16_SIZE; | |
| break; | |
| } | |
| //Decode type | |
| case Arg_type::ARG_U32: | |
| { | |
| //Accumulate | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| break; | |
| } | |
| //Decode type | |
| case Arg_type::ARG_S32: | |
| { | |
| //Accumulate | |
| arg_cnt += Arg_size::ARG_S32_SIZE; | |
| break; | |
| } | |
| default: | |
| { | |
| this -> error_handler( Err_codes::SYNTAX_ARG_TYPE_INVALID ); | |
| DRETURN_ARG("ERR%d in line %d | Invalid argument descriptor %x\n", Err_codes::SYNTAX_ARG_TYPE_INVALID , __LINE__, cmd[t]); | |
| return true; //FAIL | |
| } | |
| } //End Switch: argument type | |
| //Check size | |
| if (arg_cnt > UNIPARSER_ARG_VECTOR_SIZE) | |
| { | |
| this -> error_handler( Err_codes::SYNTAX_ARG_LENGTH ); | |
| DRETURN_ARG("ERR%d in line %d | Invalid argument descriptor %x\n", Err_codes::SYNTAX_ARG_LENGTH , __LINE__, cmd[t]); | |
| return true; //FAIL | |
| } | |
| } //End if: argument descriptor | |
| //Parse next byte | |
| t++; | |
| } //End While: parsing is not done | |
| //If command size has been exceeded | |
| if (t >= UNIPARSER_MAX_CMD_LENGTH) | |
| { | |
| this -> error_handler( Err_codes::SYNTAX_LENGTH ); | |
| DRETURN_ARG("ERR%d in line %d | Given command was too long %d\n", Err_codes::SYNTAX_LENGTH , __LINE__, t); | |
| return true; //FAIL | |
| } | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN(); | |
| return false; //OK | |
| } //end method: chk_cmd | const uint8_t * | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! set_arg<uint8_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector | |
| //! @return bool | false: OK | true: argument exceed the alloted arg vector space | |
| //! @details | |
| //! Template based add_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n | |
| //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n | |
| //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs | |
| /***************************************************************************/ | |
| template <> | |
| inline bool Uniparser::set_arg<uint8_t>( uint8_t arg_index, uint8_t arg ) | |
| { | |
| //Trace Enter | |
| DENTER_ARG( "argument: %d\n", arg ); | |
| ///-------------------------------------------------------------------------- | |
| /// VARS | |
| ///-------------------------------------------------------------------------- | |
| ///-------------------------------------------------------------------------- | |
| /// INIT | |
| ///-------------------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U8_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return true; | |
| } | |
| ///-------------------------------------------------------------------------- | |
| /// BODY | |
| ///-------------------------------------------------------------------------- | |
| //Save the numeric value of the argument | |
| this -> g_arg[ arg_index ] = (uint8_t)arg; | |
| ///-------------------------------------------------------------------------- | |
| /// RETURN | |
| ///-------------------------------------------------------------------------- | |
| //Trace Return | |
| DRETURN_ARG("Index: %d | Binary: %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0] ); | |
| return false; //OK | |
| } //end method: set_arg<uint8_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! set_arg<uint8_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector | |
| //! @return bool | false: OK | true: argument exceed the alloted arg vector space | |
| //! @details | |
| //! Template based set_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n | |
| //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n | |
| //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs | |
| /***************************************************************************/ | |
| template <> | |
| inline bool Uniparser::set_arg<int8_t>( uint8_t arg_index, int8_t arg ) | |
| { | |
| //Trace Enter | |
| DENTER_ARG( "argument: %d\n", arg ); | |
| ///-------------------------------------------------------------------------- | |
| /// VARS | |
| ///-------------------------------------------------------------------------- | |
| ///-------------------------------------------------------------------------- | |
| /// INIT | |
| ///-------------------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S8_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return true; | |
| } | |
| ///-------------------------------------------------------------------------- | |
| /// BODY | |
| ///-------------------------------------------------------------------------- | |
| //Link pointer to the correct data type | |
| int8_t *arg_ptr = ARG_CAST( arg_index, int8_t ); | |
| //Save the numeric value of the argument | |
| *arg_ptr = (int8_t)arg; | |
| ///-------------------------------------------------------------------------- | |
| /// RETURN | |
| ///-------------------------------------------------------------------------- | |
| //Trace Return | |
| DRETURN_ARG("Index: %d | Binary: %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0] ); | |
| return false; //OK | |
| } //end method: set_arg<int8_t> | int8_t | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! set_arg<uint16_t> | uint16_t | |
| /***************************************************************************/ | |
| //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector | |
| //! @return bool | false: OK | true: argument exceed the alloted arg vector space | |
| //! @details | |
| //! Template based add_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n | |
| //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n | |
| //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs | |
| /***************************************************************************/ | |
| template <> | |
| inline bool Uniparser::set_arg<uint16_t>( uint8_t arg_index, uint16_t arg ) | |
| { | |
| //Trace Enter | |
| DENTER_ARG( "argument: %d\n", arg ); | |
| ///-------------------------------------------------------------------------- | |
| /// VARS | |
| ///-------------------------------------------------------------------------- | |
| ///-------------------------------------------------------------------------- | |
| /// INIT | |
| ///-------------------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U16_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return true; | |
| } | |
| ///-------------------------------------------------------------------------- | |
| /// BODY | |
| ///-------------------------------------------------------------------------- | |
| //Link pointer to the correct data type | |
| uint16_t *arg_ptr = ARG_CAST( arg_index, uint16_t ); | |
| //Save the numeric value of the argument | |
| *arg_ptr = (uint16_t)arg; | |
| ///-------------------------------------------------------------------------- | |
| /// RETURN | |
| ///-------------------------------------------------------------------------- | |
| //Trace Return | |
| DRETURN_ARG("Index: %d | Binary: %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1] ); | |
| return false; //OK | |
| } //end method: set_arg<uint16_t> | uint16_t | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! set_arg<int16_t> | int16_t | |
| /***************************************************************************/ | |
| //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector | |
| //! @return bool | false: OK | true: argument exceed the alloted arg vector space | |
| //! @details | |
| //! Template based add_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n | |
| //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n | |
| //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs | |
| /***************************************************************************/ | |
| template <> | |
| inline bool Uniparser::set_arg<int16_t>( uint8_t arg_index, int16_t arg ) | |
| { | |
| //Trace Enter | |
| DENTER_ARG( "argument: %d\n", arg ); | |
| ///-------------------------------------------------------------------------- | |
| /// VARS | |
| ///-------------------------------------------------------------------------- | |
| ///-------------------------------------------------------------------------- | |
| /// INIT | |
| ///-------------------------------------------------------------------------- | |
| //If: set_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S16_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: set_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return true; | |
| } | |
| ///-------------------------------------------------------------------------- | |
| /// BODY | |
| ///-------------------------------------------------------------------------- | |
| //Link pointer to the correct data type | |
| int16_t *arg_ptr = ARG_CAST( arg_index, int16_t ); | |
| //Save the numeric value of the argument | |
| *arg_ptr = (int16_t)arg; | |
| ///-------------------------------------------------------------------------- | |
| /// RETURN | |
| ///-------------------------------------------------------------------------- | |
| //Trace Return | |
| DRETURN_ARG("Index: %d | Binary: %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1] ); | |
| return false; //OK | |
| } //end method: set_arg<int16_t> | int16_t | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! set_arg<uint32_t> | uint32_t | |
| /***************************************************************************/ | |
| //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector | |
| //! @return bool | false: OK | true: argument exceed the alloted arg vector space | |
| //! @details | |
| //! Template based set_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n | |
| //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n | |
| //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs | |
| /***************************************************************************/ | |
| template <> | |
| inline bool Uniparser::set_arg<uint32_t>( uint8_t arg_index, uint32_t arg ) | |
| { | |
| //Trace Enter | |
| DENTER_ARG( "argument: %d\n", arg ); | |
| ///-------------------------------------------------------------------------- | |
| /// VARS | |
| ///-------------------------------------------------------------------------- | |
| ///-------------------------------------------------------------------------- | |
| /// INIT | |
| ///-------------------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U32_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: set_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return true; | |
| } | |
| ///-------------------------------------------------------------------------- | |
| /// BODY | |
| ///-------------------------------------------------------------------------- | |
| //Link pointer to the correct data type | |
| uint32_t *arg_ptr = ARG_CAST( arg_index, uint32_t ); | |
| //Save the numeric value of the argument | |
| *arg_ptr = (uint32_t)arg; | |
| ///-------------------------------------------------------------------------- | |
| /// RETURN | |
| ///-------------------------------------------------------------------------- | |
| //Trace Return | |
| DRETURN_ARG("Index: %d | Binary: %3x %3x %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1], (uint8_t)this -> g_arg[arg_index +2], (uint8_t)this -> g_arg[arg_index +3] ); | |
| return false; //OK | |
| } //end method: set_arg<int32_t> | int32_t | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! set_arg<int32_t> | int32_t | |
| /***************************************************************************/ | |
| //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector | |
| //! @return bool | false: OK | true: argument exceed the alloted arg vector space | |
| //! @details | |
| //! Template based set_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n | |
| //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n | |
| //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs | |
| /***************************************************************************/ | |
| template <> | |
| inline bool Uniparser::set_arg<int32_t>( uint8_t arg_index, int32_t arg ) | |
| { | |
| //Trace Enter | |
| DENTER_ARG( "argument: %d\n", arg ); | |
| ///-------------------------------------------------------------------------- | |
| /// VARS | |
| ///-------------------------------------------------------------------------- | |
| ///-------------------------------------------------------------------------- | |
| /// INIT | |
| ///-------------------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S32_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: set_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return true; | |
| } | |
| ///-------------------------------------------------------------------------- | |
| /// BODY | |
| ///-------------------------------------------------------------------------- | |
| //Link pointer to the correct data type | |
| int32_t *arg_ptr = ARG_CAST( arg_index, int32_t ); | |
| //Save the numeric value of the argument | |
| *arg_ptr = (int32_t)arg; | |
| ///-------------------------------------------------------------------------- | |
| /// RETURN | |
| ///-------------------------------------------------------------------------- | |
| //Trace Return | |
| DRETURN_ARG("Index: %d | Binary: %3x %3x %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1], (uint8_t)this -> g_arg[arg_index +2], (uint8_t)this -> g_arg[arg_index +3] ); | |
| return false; //OK | |
| } //end method: set_arg<int32_t> | int32_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! get_arg<uint8_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg_index | point to an argument inside the argument vector | |
| //! @return decoded content of argument vector at given position | |
| //! @details | |
| //! fetch the numeric value of an argument from the argument vector | |
| /***************************************************************************/ | |
| template <> | |
| inline uint8_t Uniparser::get_arg( uint8_t arg_index ) | |
| { | |
| DENTER_ARG("arg_index: %d\n", arg_index ); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U8_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return (uint8_t)0xff; | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Link the pointer to the actual content | |
| uint8_t *arg_ptr = &this -> g_arg[arg_index]; | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN_ARG("Decoded: %d\n", *arg_ptr); | |
| return *arg_ptr; //OK | |
| } //end method: get_arg<uint8_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! get_arg<int8_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg_index | point to an argument inside the argument vector | |
| //! @return decoded content of argument vector at given position | |
| //! @details | |
| //! fetch the numeric value of an argument from the argument vector | |
| /***************************************************************************/ | |
| template <> | |
| inline int8_t Uniparser::get_arg( uint8_t arg_index ) | |
| { | |
| DENTER_ARG("arg_index: %d\n", arg_index ); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S8_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return (uint8_t)0xff; | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Link the pointer to the actual content | |
| int8_t *arg_ptr = ARG_CAST( arg_index, int8_t); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN_ARG("Decoded: %d\n", *arg_ptr); | |
| return *arg_ptr; //OK | |
| } //end method: get_arg<int8_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! get_arg<uint16_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg_index | point to an argument inside the argument vector | |
| //! @return decoded content of argument vector at given position | |
| //! @details | |
| //! fetch the numeric value of an argument from the argument vector | |
| /***************************************************************************/ | |
| template <> | |
| inline uint16_t Uniparser::get_arg( uint8_t arg_index ) | |
| { | |
| DENTER_ARG("arg_index: %d\n", arg_index ); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U16_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return (uint8_t)0xff; | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Link the pointer to the actual content | |
| uint16_t *arg_ptr = ARG_CAST( arg_index, uint16_t); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN_ARG("Decoded: %d\n", *arg_ptr); | |
| return *arg_ptr; //OK | |
| } //end method: get_arg<uint16_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! get_arg<int16_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg_index | point to an argument inside the argument vector | |
| //! @return decoded content of argument vector at given position | |
| //! @details | |
| //! fetch the numeric value of an argument from the argument vector | |
| /***************************************************************************/ | |
| template <> | |
| inline int16_t Uniparser::get_arg( uint8_t arg_index ) | |
| { | |
| DENTER_ARG("arg_index: %d\n", arg_index ); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S16_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return (uint8_t)0xff; | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Link the pointer to the actual content | |
| int16_t *arg_ptr = ARG_CAST( arg_index, int16_t); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN_ARG("Decoded: %d\n", *arg_ptr); | |
| return *arg_ptr; //OK | |
| } //end method: get_arg<int16_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! get_arg<uint32_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg_index | point to an argument inside the argument vector | |
| //! @return decoded content of argument vector at given position | |
| //! @details | |
| //! fetch the numeric value of an argument from the argument vector | |
| /***************************************************************************/ | |
| template <> | |
| inline uint32_t Uniparser::get_arg( uint8_t arg_index ) | |
| { | |
| DENTER_ARG("arg_index: %d\n", arg_index ); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U32_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return (uint8_t)0xff; | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Link the pointer to the actual content | |
| uint32_t *arg_ptr = ARG_CAST( arg_index, uint32_t); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN_ARG("Decoded: %d\n", *arg_ptr); | |
| return *arg_ptr; //OK | |
| } //end method: get_arg<uint32_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! get_arg<int32_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @param arg_index | point to an argument inside the argument vector | |
| //! @return decoded content of argument vector at given position | |
| //! @details | |
| //! fetch the numeric value of an argument from the argument vector | |
| /***************************************************************************/ | |
| template <> | |
| inline int32_t Uniparser::get_arg( uint8_t arg_index ) | |
| { | |
| DENTER_ARG("arg_index: %d\n", arg_index ); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If: add_arg would exceed the maximum allowed argument vector size | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S32_SIZE)) | |
| { | |
| //Trace Return | |
| DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); | |
| this -> error_handler( Err_codes::ERR_ARG_SIZE ); | |
| return (uint8_t)0xff; | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Link the pointer to the actual content | |
| int32_t *arg_ptr = ARG_CAST( arg_index, int32_t); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| DRETURN_ARG("Decoded: %d\n", *arg_ptr); | |
| return *arg_ptr; //OK | |
| } //end method: get_arg<int32_t> | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! add_arg | uint8_t | |
| /***************************************************************************/ | |
| //! @param cmd_id | index of the command the argument is inferred from | |
| //! @return false: ok | true: fail | |
| //! @details | |
| //! Add an argument to the parser argument storage. | |
| //! It expect the command to be a partial match and the index to be pointing to '%' | |
| //! The command is added to the class argument storage string in the format | |
| //! 'u' data0 ... data 1 | |
| /***************************************************************************/ | |
| bool Uniparser::add_arg( uint8_t cmd_id ) | |
| { | |
| //Trace Enter with arguments | |
| DENTER_ARG("command index: %d\n", cmd_id); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //return | |
| bool f_ret = false; | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //If input index is out of range | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (cmd_id > this -> g_num_cmd) ) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //Fetch index inside the command | |
| uint8_t cmd_index = this -> g_cmd_index[ cmd_id ]; | |
| //if: the command is not an argument | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[cmd_id][ cmd_index ] != '%')) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //Point to the argument type | |
| cmd_index++; | |
| //if: the command is not an argument descriptor. PEDANTIC because dictionary should have been checked before hand | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_ARG_DESCRIPTOR(this -> g_cmd_txt[cmd_id][ cmd_index ])) ) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //! @details algorithm: | |
| //! Compute index to argument vector and number of arguments | |
| //! Compute | |
| //! ARG Index points to first free slot in the argument vector | |
| //! I save argument type and initialize the content | |
| //! Initialize argument identifier | |
| //argument descriptor is held in the dictionary | |
| Arg_type arg_type = (Arg_type)this -> g_cmd_txt[cmd_id][cmd_index]; | |
| //Fetch index to the next free argument slot | |
| uint8_t arg_type_index = this -> g_arg_fsm_status.num_arg; | |
| //Store argument type in the argument type vector | |
| this -> g_arg_type[ arg_type_index ] = arg_type; | |
| //A new argument is being added. Reset the argument sign (@TODO: do this earlier) | |
| this -> g_arg_fsm_status.arg_sign = false; | |
| //fetch argument index | |
| uint8_t arg_index = this -> g_arg_fsm_status.arg_index; | |
| DPRINT("argument of type >%c< added | Num arguments: %d | Arg index: %d | Arg sign %c \n", arg_type, this -> g_arg_fsm_status.num_arg, arg_index, (this -> g_arg_fsm_status.arg_sign)?('-'):('+') ); | |
| //! Initialize argument content | |
| //switch: decode argument desriptor | |
| switch (arg_type) | |
| { | |
| case Arg_type::ARG_U8: | |
| { | |
| //Write zero inside the argument | |
| f_ret = this -> set_arg<uint8_t>( arg_index, (uint8_t)0 ); | |
| break; | |
| } | |
| case Arg_type::ARG_S8: | |
| { | |
| //Write zero inside the argument | |
| f_ret = this -> set_arg<int8_t>( arg_index, (int8_t)0 ); | |
| break; | |
| } | |
| case Arg_type::ARG_U16: | |
| { | |
| //Write zero inside the argument | |
| f_ret = this -> set_arg<uint16_t>( arg_index, (uint16_t)0 ); | |
| break; | |
| } | |
| case Arg_type::ARG_S16: | |
| { | |
| //Write zero inside the argument | |
| f_ret = this -> set_arg<int16_t>( arg_index, (int16_t)0 ); | |
| break; | |
| } | |
| case Arg_type::ARG_U32: | |
| { | |
| //Write zero inside the argument | |
| f_ret = this -> set_arg<uint32_t>( arg_index, (uint32_t)0 ); | |
| break; | |
| } | |
| case Arg_type::ARG_S32: | |
| { | |
| //Write zero inside the argument | |
| f_ret = this -> set_arg<int32_t>( arg_index, (int32_t)0 ); | |
| break; | |
| } | |
| //if: type is not handled | |
| default: | |
| { | |
| this -> error_handler( Err_codes::ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d\n", __LINE__, arg_type_index); | |
| return true; //FAIL | |
| } | |
| } //end switch: decode argument desriptor | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| //Trace Return vith return value | |
| DRETURN_ARG("Success: %x\n", f_ret); | |
| return f_ret; //OK | |
| } //end method: add_arg | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! accumulate_arg | uint8_t | |
| /***************************************************************************/ | |
| //! @param data | input character to be decoded. It should be a number or a sign | |
| //! @return false: ok | true: fail | |
| //! @details | |
| //! decode an input character and accumulate it into the argument vector | |
| /***************************************************************************/ | |
| bool Uniparser::accumulate_arg( uint8_t data ) | |
| { | |
| //Trace Enter with arguments | |
| DENTER_ARG("data >%c<\n", data); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //detect failure state | |
| bool f_ret; | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //Fetch argument index | |
| uint8_t arg_index = this -> g_arg_fsm_status.arg_index; | |
| //Fetch argument type index | |
| uint8_t arg_type_index = this -> g_arg_fsm_status.num_arg; | |
| //If argument descriptor is bad | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_type_index >= UNIPARSER_MAX_ARGS)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Num args: %x\n", this -> g_err, __LINE__, arg_type_index ); | |
| return true; //fail | |
| } | |
| //Fetch argument type | |
| Arg_type arg_type = (Arg_type)this->g_arg_type[arg_type_index]; | |
| //If argument descriptor is bad | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_ARG_DESCRIPTOR(arg_type))) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Arg_type: %x\n", this -> g_err, __LINE__, arg_type ); | |
| return true; //fail | |
| } | |
| //If: input char is bad | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_SIGN(data)) && (!IS_NUMBER(data))) | |
| { | |
| DPRINT("ERR: bad input char. Expecting number or sign and got >0x%x< instead\n", data); | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //!Detect sign | |
| //if sign | |
| if (IS_SIGN(data)) | |
| { | |
| //If sign is minus, argument sign is true which means minus | |
| this -> g_arg_fsm_status.arg_sign = (data == '-'); | |
| DRETURN(); | |
| //I'm done updating argument for now. Next round will come actual numbers. | |
| return false; | |
| } | |
| //!Decode numeric value | |
| //decode the argument descriptor | |
| switch (arg_type) | |
| { | |
| //if: the command expects a uint8_t data | |
| case (Arg_type::ARG_U8): | |
| { | |
| //Fetch old argument | |
| uint8_t old = this -> get_arg<uint8_t>( arg_index ); | |
| //Shift by one digit left | |
| old *= 10; | |
| //If number is positive | |
| if (this -> g_arg_fsm_status.arg_sign == false) | |
| { | |
| //Accumulate new digit | |
| old += data -'0'; | |
| } | |
| //if: number is negative | |
| else | |
| { | |
| //Accumulate new digit | |
| old -= data -'0'; | |
| } | |
| //Write back argument inside argument vector | |
| f_ret = this -> set_arg<uint8_t>( arg_index, old ); | |
| //If set arg failed | |
| if (f_ret == true) | |
| { | |
| return true; | |
| } | |
| DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); | |
| break; | |
| } | |
| //if: the command expects a uint8_t data | |
| case (Arg_type::ARG_S8): | |
| { | |
| //Fetch old argument | |
| int8_t old = this -> get_arg<int8_t>( arg_index ); | |
| //Shift by one digit left | |
| old *= 10; | |
| //If number is positive | |
| if (this -> g_arg_fsm_status.arg_sign == false) | |
| { | |
| //Accumulate new digit | |
| old += data -'0'; | |
| } | |
| //if: number is negative | |
| else | |
| { | |
| //Accumulate new digit | |
| old -= data -'0'; | |
| } | |
| //Write back argument inside argument vector | |
| f_ret = this -> set_arg<int8_t>( arg_index, old ); | |
| //If set arg failed | |
| if (f_ret == true) | |
| { | |
| return true; | |
| } | |
| DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); | |
| break; | |
| } | |
| //if: the command expects a uint8_t data | |
| case (Arg_type::ARG_U16): | |
| { | |
| //Fetch old argument | |
| uint16_t old = this -> get_arg<uint16_t>( arg_index ); | |
| //Shift by one digit left | |
| old *= 10; | |
| //If number is positive | |
| if (this -> g_arg_fsm_status.arg_sign == false) | |
| { | |
| //Accumulate new digit | |
| old += data -'0'; | |
| } | |
| //if: number is negative | |
| else | |
| { | |
| //Accumulate new digit | |
| old -= data -'0'; | |
| } | |
| //Write back argument inside argument vector | |
| f_ret = this -> set_arg<uint16_t>( arg_index, old ); | |
| //If set arg failed | |
| if (f_ret == true) | |
| { | |
| return true; | |
| } | |
| DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); | |
| break; | |
| } | |
| //if: the command expects a uint8_t data | |
| case (Arg_type::ARG_S16): | |
| { | |
| //Fetch old argument | |
| int16_t old = this -> get_arg<int16_t>( arg_index ); | |
| //Shift by one digit left | |
| old *= 10; | |
| //If number is positive | |
| if (this -> g_arg_fsm_status.arg_sign == false) | |
| { | |
| //Accumulate new digit | |
| old += data -'0'; | |
| } | |
| //if: number is negative | |
| else | |
| { | |
| //Accumulate new digit | |
| old -= data -'0'; | |
| } | |
| //Write back argument inside argument vector | |
| f_ret = this -> set_arg<int16_t>( arg_index, old ); | |
| //If set arg failed | |
| if (f_ret == true) | |
| { | |
| return true; | |
| } | |
| DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); | |
| break; | |
| } | |
| //if: the command expects a uint8_t data | |
| case (Arg_type::ARG_U32): | |
| { | |
| //Fetch old argument | |
| uint32_t old = this -> get_arg<uint32_t>( arg_index ); | |
| //Shift by one digit left | |
| old *= 10; | |
| //If number is positive | |
| if (this -> g_arg_fsm_status.arg_sign == false) | |
| { | |
| //Accumulate new digit | |
| old += data -'0'; | |
| } | |
| //if: number is negative | |
| else | |
| { | |
| //Accumulate new digit | |
| old -= data -'0'; | |
| } | |
| //Write back argument inside argument vector | |
| f_ret = this -> set_arg<uint32_t>( arg_index, old ); | |
| //If set arg failed | |
| if (f_ret == true) | |
| { | |
| return true; | |
| } | |
| DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); | |
| break; | |
| } | |
| //if: the command expects a uint8_t data | |
| case (Arg_type::ARG_S32): | |
| { | |
| //Fetch old argument | |
| int32_t old = this -> get_arg<int32_t>( arg_index ); | |
| //Shift by one digit left | |
| old *= 10; | |
| //If number is positive | |
| if (this -> g_arg_fsm_status.arg_sign == false) | |
| { | |
| //Accumulate new digit | |
| old += data -'0'; | |
| } | |
| //if: number is negative | |
| else | |
| { | |
| //Accumulate new digit | |
| old -= data -'0'; | |
| } | |
| //Write back argument inside argument vector | |
| f_ret = this -> set_arg<int32_t>( arg_index, old ); | |
| //If set arg failed | |
| if (f_ret == true) | |
| { | |
| return true; | |
| } | |
| DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); | |
| break; | |
| } | |
| //Unrecognized argument descriptor in the dictionary | |
| default: | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| } | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| //Trace Return vith return value | |
| DRETURN(); | |
| return false; //OK | |
| } //end method: accumulate_arg | uint8_t | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! close_arg | void | |
| /***************************************************************************/ | |
| //! @return false: OK | true: fail | |
| //! @details | |
| //! Argument has been fully decoded into argument string. Update argument descriptor FSM. | |
| /***************************************************************************/ | |
| bool Uniparser::close_arg( void ) | |
| { | |
| //Trace Enter with arguments | |
| DENTER(); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //Fetch argument index | |
| uint8_t arg_index = this -> g_arg_fsm_status.arg_index; | |
| //Fetch argument type index | |
| uint8_t arg_type_index = this -> g_arg_fsm_status.num_arg; | |
| //If argument descriptor is bad | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_type_index >= UNIPARSER_MAX_ARGS)) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Num args: %x\n", this -> g_err, __LINE__, arg_type_index ); | |
| return true; //fail | |
| } | |
| //Fetch argument type | |
| Arg_type arg_type = (Arg_type)this->g_arg_type[arg_type_index]; | |
| //If argument descriptor is bad | |
| if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_ARG_DESCRIPTOR(arg_type))) | |
| { | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Arg_type: %x\n", this -> g_err, __LINE__, arg_type ); | |
| return true; //fail | |
| } | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //! Advance the argument index to the first free byte in the argument vector | |
| //If: one byte argument | |
| if ((arg_type == Arg_type::ARG_U8) || (arg_type == Arg_type::ARG_S8)) | |
| { | |
| //Skip the argument descriptor and the argument itself | |
| arg_index += Arg_size::ARG_S8_SIZE; | |
| } | |
| //If: two bytes argument | |
| else if ((arg_type == Arg_type::ARG_U16) || (arg_type == Arg_type::ARG_S16)) | |
| { | |
| //Skip the argument descriptor and the argument itself | |
| arg_index += Arg_size::ARG_S16_SIZE; | |
| } | |
| //If: four bytes argument | |
| else if ((arg_type == Arg_type::ARG_U32) || (arg_type == Arg_type::ARG_S32)) | |
| { | |
| //Skip the argument descriptor and the argument itself | |
| arg_index += Arg_size::ARG_S32_SIZE; | |
| } | |
| //pedantic because the ditionary should have been checked before hand for bad argument descriptors | |
| else if (UNIPARSER_PENDANTIC_CHECKS) | |
| { | |
| //This error means the argument descriptor was unrecognized | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; | |
| } | |
| else | |
| { | |
| //failure | |
| return true; | |
| } | |
| //! Check that index is valid | |
| //if: index is above bit width or exceed the argument vector size | |
| if ((arg_index > UNIPARSER_MAX_ARG_INDEX) || (arg_index > UNIPARSER_ARG_VECTOR_SIZE)) | |
| { | |
| //Restart the argument decoder | |
| this -> init_arg_decoder(); | |
| // | |
| DPRINT("ERR: Exceeded alloted argument vector size with index: %d\n", arg_index); | |
| this -> g_err = Err_codes::ERR_GENERIC; | |
| DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); | |
| return true; //fail | |
| } | |
| //Write back index | |
| this -> g_arg_fsm_status.arg_index = arg_index; | |
| //Update number of decoded arguments | |
| this -> g_arg_fsm_status.num_arg++; | |
| DPRINT("Argument closed | num arg: %d | arg index: %d\n", this -> g_arg_fsm_status.num_arg, this -> g_arg_fsm_status.arg_index); | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| //Trace Return vith return value | |
| DRETURN(); | |
| return false; //OK | |
| } //end method: close_arg | void | |
| /***************************************************************************/ | |
| //! @brief Public Method | |
| //! execute_callback | void | |
| /***************************************************************************/ | |
| // @param | |
| //! @return no return | |
| //! @details | |
| //! Execute callback by passing a vector of U8 inside which are codified the bytes of the arguments | |
| //! @algorithm | |
| //! It's an execution tree that execute a branch based on the argument types | |
| //! Tree is limited by the maximum number of types and the maximum number of bytes | |
| //! ARG0 ARG0,ARG1 ARG0,ARG1,ARG2 ARG0,ARG1,ARG2,ARG3 | |
| //! void | |
| //! 8 8 8 8 8 8 8 8 8 8 (arg number limit) | |
| //! ... ... | |
| //! 8 16 | |
| //! 8 32 | |
| //! 16 16 8 | |
| //! 16 16 | |
| //! ... | |
| //! 32 32 8 32 8 8 8 (arg number limit) | |
| //! 32 16 8 8 (arg number and size limit) | |
| //! 32 16 16 (arg number limit) | |
| //! 32 32 (arg size limit) | |
| //! (arg type limit) | |
| //! Calls work equally with signed or unsiged arguments | |
| /***************************************************************************/ | |
| bool Uniparser::execute_callback( void *callback_ptr ) | |
| { | |
| //Trace Enter | |
| DENTER(); | |
| ///-------------------------------------------------------------------------- | |
| /// VARS | |
| ///-------------------------------------------------------------------------- | |
| //Argument index counter | |
| uint8_t arg_cnt = 0; | |
| //Number of arguments | |
| uint8_t arg_num_types = this -> g_arg_fsm_status.num_arg; | |
| //Count the index of the current argument type being decoded | |
| uint8_t arg_type_cnt = 0; | |
| //Link argument type vector | |
| Arg_type *arg_type = this -> g_arg_type; | |
| ///-------------------------------------------------------------------------- | |
| /// INIT | |
| ///-------------------------------------------------------------------------- | |
| ///-------------------------------------------------------------------------- | |
| /// BODY | |
| ///-------------------------------------------------------------------------- | |
| //if: no arguments | |
| if (arg_num_types == 0) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// void | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, void ) = FUNCTION_PTR_CAST(void)callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE_VOID( f_ptr ); | |
| DPRINT("Executing void -> void: %p | Args: NONE \n", (void *)f_ptr ); | |
| } | |
| //if: first argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode first argument | |
| uint8_t *arg_a_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 - 1 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t ) = FUNCTION_PTR_CAST( uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr) ); | |
| DPRINT("Executing uint8_t -> void: %p | Args: %d \n", (void *)f_ptr, (*arg_a_ptr) ); | |
| } //End If: it's the only argument | |
| //if: second argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_b_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 - 2 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U8 - 3 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U8 U8 - 4 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U8 U16 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U8 U32 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U16 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U16 U8 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U16 U16 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U16 U32 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint16_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U32 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U32 U8 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint32_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U8 U32 U16 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint32_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint8_t, uint32_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U32 or S32 | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled | |
| } //if: second argument is U8 or S8 | |
| //if: second argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_b_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 - 3 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U8 - 4 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U8 U8 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode fourth argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U8 U16 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode fourth argument | |
| uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U8 U32 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U16 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U16 U8 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U16 U16 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U32 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U16 U32 U8 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint32_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint16_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U32 or S32 | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled | |
| } //if: second argument is U16 or S16 | |
| //if: second argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_b_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U32 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint8_t, uint32_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if: third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U32 U8 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U32 U8 U8 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint32_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U32 U8 U16 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint32_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U32 U16 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint8_t, uint32_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U8 U32 U16 U8 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint8_t, uint32_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 or U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 or U32 or S32 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled } | |
| } //if: second argument is U32 or S32 | |
| //If: second argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: second argument is unhandled | |
| } //end if: first argument is U8 or S8 | |
| //if: first argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode first argument | |
| uint16_t *arg_a_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 - 2 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t ) = FUNCTION_PTR_CAST( uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr) ); | |
| DPRINT("Executing uint16_t -> void: %p | Args: %d \n", (void *)f_ptr, (*arg_a_ptr) ); | |
| } | |
| //if: second argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_b_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 - 3 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U8 - 4 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U8 U8 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode fourth argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U8 U16 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode fourth argument | |
| uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U8 U32 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument | |
| } //end if fourth argument is U32 or S32 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U16 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U16 U8 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode fourth argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U16 U16 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U32 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U8 U32 U8 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint32_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 or U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U32 or S32 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U32 or S32 | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled | |
| } //if: second argument is U8 or S8 | |
| //if: second argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_b_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 - 4 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t -> void: %p | Args: %d %d\n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 U8 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 U8 U8 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode fourth argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 U8 U16 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 U16 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 U16 U8 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode fourth argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 U16 U16 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| //if: fifth argument | |
| else | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fifth argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U16 U32 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if: fourth argument | |
| else | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument | |
| } //if: third argument is U32 or S32 | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled | |
| } //if: second argument is U16 or S16 | |
| //if: second argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_b_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U32 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint16_t, uint32_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U32 U8 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U32 U8 U8 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint16_t, uint32_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 or U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U16 or S16 or U32 or S32 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U16 U32 U16 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint16_t, uint32_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if: fourth argument | |
| else | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //if: third argument is U32 or S32 | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled | |
| } //if: second argument is U32 or S32 | |
| //If: second argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: second argument is unhandled | |
| } //end if: first argument is U16 or S16 | |
| //if: first argument is S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode first argument | |
| uint32_t *arg_a_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_S32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| DPRINT("Decoded argument | arg_type_cnt: %d | arg_cnt: %d | arg: %d\n", arg_type_cnt, arg_cnt, (*arg_a_ptr)); | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 - 4 | |
| ///-------------------------------------------------------------------------- | |
| //Passing an unsigned 32 bit pointer is decoded successfully as signed of same size | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t ) = FUNCTION_PTR_CAST( uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr) ); | |
| DPRINT("Executing int32_t -> void: %p | Args: %d\n", (void *)f_ptr, (*arg_a_ptr) ); | |
| } | |
| //if: second argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_b_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U8 - 5 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint16_t, uint8_t -> void: %p | Args: %d %d\n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U8 U8 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint32_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U8 U8 U8 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint32_t, uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode fourth argument | |
| uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U8 U8 U16 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint32_t, uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument | |
| } //end if fourth argument is U16 or S16 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U32 or S32 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U8 U16 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint32_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U8 U16 U8 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint32_t, uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U32 or S32 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //if: third argument is U32 or S32 | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled | |
| } //if: second argument is U8 or S8 | |
| //if: second argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_b_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U16 - 6 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint16_t, uint16_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //if third argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode second argument | |
| uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U16 U8 - 7 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint32_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument is U8 or S8 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) | |
| { | |
| //Decode fourth argument | |
| uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U8_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U16 U8 U8 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t, uint8_t, uint8_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); | |
| DPRINT("Executing uint32_t, uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); | |
| } //End If: it's the only argument | |
| } //end if fourth argument is U8 or S8 | |
| //if fourth argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument is U32 or S32 | |
| //if: more than four arguments are forbidden! | |
| else | |
| { | |
| this -> error_handler( ERR_TOO_MANY_ARGS ); | |
| DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if: more than four arguments are forbidden! | |
| } //if: third argument is U8 or S8 | |
| //if third argument is U16 or S16 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) | |
| { | |
| //Decode second argument | |
| uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U16_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U16 U16 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t, uint16_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); | |
| DPRINT("Executing uint32_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); | |
| } //End If: it's the only argument | |
| //if fourth argument | |
| else | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //end if fourth argument | |
| } //if: third argument is U16 or S16 | |
| //if third argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //if: third argument is U32 or S32 | |
| //If: third argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: third argument is unhandled | |
| } //if: second argument is U16 or S16 | |
| //if: second argument is U32 or S32 | |
| else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) | |
| { | |
| //Decode second argument | |
| uint32_t *arg_b_ptr = ARG_CAST( arg_cnt, uint32_t ); | |
| //Accumulate argument size | |
| arg_cnt += Arg_size::ARG_U32_SIZE; | |
| //I decoded an argument | |
| arg_type_cnt++; | |
| DPRINT("Decoded argument | arg_type_cnt: %d | arg_cnt: %d | arg: %d\n", arg_type_cnt, arg_cnt, (*arg_b_ptr)); | |
| //If: it's the only argument | |
| if (arg_num_types == arg_type_cnt) | |
| { | |
| ///-------------------------------------------------------------------------- | |
| /// U32 U32 - 8 | |
| ///-------------------------------------------------------------------------- | |
| //Declare specialized function pointer and link it to the general registered function callback address | |
| FUNCTION_PTR_VAR( f_ptr, uint32_t, uint32_t ) = FUNCTION_PTR_CAST( uint32_t, uint32_t )callback_ptr; | |
| //Execute function from its specialized pointer | |
| FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); | |
| DPRINT("Executing uint32_t, uint32_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); | |
| } //End If: it's the only argument | |
| //If: I CANNOT have a third argument after this because it would exceed the argument size limit | |
| else | |
| { | |
| this -> error_handler( ERR_ARG_SIZE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: argument is unhandled | |
| } //if: second argument is U32 or S32 | |
| //If: second argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: second argument is unhandled | |
| } //end if: first argument is S32 | |
| //If: argument is unhandled | |
| else | |
| { | |
| this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); | |
| DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); | |
| return true; //FAIL | |
| } //End If: argument is unhandled | |
| ///-------------------------------------------------------------------------- | |
| /// RETURN | |
| ///-------------------------------------------------------------------------- | |
| //Trace Return | |
| DRETURN(); | |
| return false; //OK | |
| } //end method: execute_callback | |
| /***************************************************************************/ | |
| //! @brief Private Method | |
| //! error_handler | Err_codes | |
| /***************************************************************************/ | |
| //! @param err_code | Err_codes | internal uniparser error code | |
| //! @return void | |
| //! @details | |
| //! Handles an internal parser error | |
| /***************************************************************************/ | |
| void Uniparser::error_handler( Err_codes err_code ) | |
| { | |
| //Trace Enter with arguments | |
| DENTER_ARG( "Error code: %d\n", err_code); | |
| //---------------------------------------------------------------- | |
| // VARS | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // INIT | |
| //---------------------------------------------------------------- | |
| //---------------------------------------------------------------- | |
| // BODY | |
| //---------------------------------------------------------------- | |
| //Save the error code | |
| this -> g_err = err_code; | |
| //---------------------------------------------------------------- | |
| // RETURN | |
| //---------------------------------------------------------------- | |
| //Trace Return vith return value | |
| DRETURN(); | |
| return; | |
| } //end method: error_handler | Err_codes | |
| /**************************************************************************** | |
| ** NAMESPACES | |
| ****************************************************************************/ | |
| } //End Namespace: Orangebot | |