mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-30 08:30:53 +00:00
Add Function Name, Constants, Globals and Local Variables to RAnnotatedCode (#17429)
* Annotation for function name (#17204) * Annotations for Constant Variables and Global Variables for the decompiler (#17281) * Annotation For Function Variables (#17375) * function variable annotation added (includes local variable and function parameter) * API for checking if an annotation is a reference or function variable. (#17386) * Update docs in annotate code API (#17397) * Unit tests for annotated code API (#17403)
This commit is contained in:
parent
18c052c266
commit
b4677b4dfe
@ -28,6 +28,27 @@ R_API void r_core_annotated_code_print_json(RAnnotatedCode *code) {
|
||||
pj_ks (pj, "type", "offset");
|
||||
pj_kn (pj, "offset", annotation->offset.offset);
|
||||
break;
|
||||
case R_CODE_ANNOTATION_TYPE_FUNCTION_NAME:
|
||||
pj_ks (pj, "type", "function_name");
|
||||
pj_ks (pj, "name", annotation->reference.name);
|
||||
pj_kn (pj, "offset", annotation->reference.offset);
|
||||
break;
|
||||
case R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE:
|
||||
pj_ks (pj, "type", "global_variable");
|
||||
pj_kn (pj, "offset", annotation->reference.offset);
|
||||
break;
|
||||
case R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE:
|
||||
pj_ks (pj, "type", "constant_variable");
|
||||
pj_kn (pj, "offset", annotation->reference.offset);
|
||||
break;
|
||||
case R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE:
|
||||
pj_ks (pj, "type", "local_variable");
|
||||
pj_ks (pj, "name", annotation->variable.name);
|
||||
break;
|
||||
case R_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER:
|
||||
pj_ks (pj, "type", "function_parameter");
|
||||
pj_ks (pj, "name", annotation->variable.name);
|
||||
break;
|
||||
case R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT:
|
||||
pj_ks (pj, "type", "syntax_highlight");
|
||||
switch (annotation->syntax_highlight.type) {
|
||||
|
@ -930,39 +930,34 @@ extern RCorePlugin r_core_plugin_a2f;
|
||||
|
||||
/* DECOMPILER PRINTING FUNCTIONS */
|
||||
/**
|
||||
* r_core_annotated_code_print_json() - Prints the data contained in RAnnotatedCode *code in JSON format.
|
||||
* @code: Pointer to a RAnnotatedCode
|
||||
*
|
||||
* Prints the data contained in RAnnotatedCode represented by the pointer 'code' in JSON format.
|
||||
* The function will print the output in console using the function r_cons_printf();
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
* @brief Prints the data contained in the specified RAnnotatedCode in JSON format.
|
||||
*
|
||||
* The function will print the output in console using the function r_cons_printf();
|
||||
*
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
*/
|
||||
R_API void r_core_annotated_code_print_json(RAnnotatedCode *code);
|
||||
/**
|
||||
* r_core_annotated_code_print() - Prints the decompiled code in the passed argument 'code'.
|
||||
* @code: Pointer to a RAnnotatedCode
|
||||
* @line_offsets: Pointer to a RVector that containes offsets for the decompiled code
|
||||
*
|
||||
* This function is used for printing the output of commands pdg and pdgo.
|
||||
* It can print the decompiled code with or without offsets. If line_offsets is a null pointer,
|
||||
* the output will be printed without offsets (pdg), otherwise, the output will be
|
||||
* printed with offsets.
|
||||
* This function will print the output in console using the function r_cons_printf();
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
* @brief Prints the decompiled code from the specified RAnnotatedCode.
|
||||
*
|
||||
* This function is used for printing the output of commands pdg and pdgo.
|
||||
* It can print the decompiled code with or without offsets. If line_offsets is a null pointer,
|
||||
* the output will be printed without offsets (pdg), otherwise, the output will be
|
||||
* printed with offsets.
|
||||
* This function will print the output in console using the function r_cons_printf();
|
||||
*
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
* @param line_offsets Pointer to a @ref RVector that contains offsets for the decompiled code.
|
||||
*/
|
||||
R_API void r_core_annotated_code_print(RAnnotatedCode *code, RVector *line_offsets);
|
||||
/**
|
||||
* r_core_annotated_code_print_comment_cmds() - Prints the decompiled code as comments
|
||||
* @code: Pointer to a RAnnotatedCode
|
||||
*
|
||||
* This functions prints the decompiled code as comment.
|
||||
* This function is used for the output of command pdg*
|
||||
* Output will be printed in console using the function r_cons_printf();
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
* @brief Prints the decompiled code as comments
|
||||
*
|
||||
* This function is used for the output of command pdg*
|
||||
* Output will be printed in console using the function r_cons_printf();
|
||||
*
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
*/
|
||||
R_API void r_core_annotated_code_print_comment_cmds(RAnnotatedCode *code);
|
||||
|
||||
#endif
|
||||
|
@ -21,108 +21,155 @@ typedef enum r_syntax_highlight_type_t {
|
||||
R_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE,
|
||||
} RSyntaxHighlightType;
|
||||
|
||||
/**
|
||||
* enum r_code_annotation_type_t - typedefed as RCodeAnnotationType and this gives types of annotation
|
||||
*
|
||||
* There are two kinds of RCodeAnnotation. One for offset, which of the type
|
||||
* R_CODE_ANNOTATION_TYPE_OFFSET and other one is for syntax highlight, which is
|
||||
* of the type R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT.
|
||||
* R_CODE_ANNOTATION_TYPE_OFFSET is for representing annotations that gives an offset for
|
||||
* a range while R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT is for representing the
|
||||
* kind of data the range represents. Here, range refers to the range of annotation.
|
||||
*/
|
||||
|
||||
/** Represents the type of annnotation. */
|
||||
typedef enum r_code_annotation_type_t {
|
||||
R_CODE_ANNOTATION_TYPE_OFFSET,
|
||||
R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT,
|
||||
R_CODE_ANNOTATION_TYPE_OFFSET, /*!< Gives the offset of the specified range in annotation. */
|
||||
R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT, /*!< Represents the kind of data the specified range represents for highlighting purposes. */
|
||||
R_CODE_ANNOTATION_TYPE_FUNCTION_NAME, /*!< Specified range in annotation represents a function name. */
|
||||
R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE, /*!< Specified range in annotation represents a global variable. */
|
||||
R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE, /*!< Specified range in annotation represents a constant variable with an address. */
|
||||
R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE, /*!< Specified range in annotation represents a local variable. */
|
||||
R_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER, /*!< Specified range in annotation represents a function parameter. */
|
||||
// ...
|
||||
} RCodeAnnotationType;
|
||||
|
||||
/**
|
||||
* \brief Annotations for the decompiled code are represented using this structure.
|
||||
*/
|
||||
typedef struct r_code_annotation_t {
|
||||
size_t start;
|
||||
size_t end;
|
||||
size_t start; /**< Start of the range in the annotation(inclusive). */
|
||||
size_t end; /**< End of the range in the annotation(exclusive). */
|
||||
RCodeAnnotationType type;
|
||||
union {
|
||||
/** If the annotation is of type R_CODE_ANNOTATION_TYPE_OFFSET,
|
||||
* offset should be stored in the struct named offset in this union.
|
||||
*/
|
||||
struct {
|
||||
ut64 offset;
|
||||
} offset;
|
||||
|
||||
/** If the annotation is of type R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT,
|
||||
* type of the syntax highlight will be stored in the struct named syntax_highlight
|
||||
* in this union.
|
||||
*/
|
||||
struct {
|
||||
RSyntaxHighlightType type;
|
||||
} syntax_highlight;
|
||||
|
||||
/** Information in annotations of type R_CODE_ANNOTATION_TYPE_FUNCTION_NAME,
|
||||
* R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE, and R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE
|
||||
* will be stored in the struct named reference in this union.
|
||||
*/
|
||||
struct {
|
||||
char *name;
|
||||
ut64 offset;
|
||||
} reference;
|
||||
|
||||
/** Information in annotations of type R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE
|
||||
* and R_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER will be stored in the
|
||||
* struct named variable in this union.
|
||||
*/
|
||||
struct {
|
||||
char *name;
|
||||
} variable;
|
||||
};
|
||||
} RCodeAnnotation;
|
||||
|
||||
/**
|
||||
* \brief This structure contains the decompiled code and all the annotations for the decompiled code.
|
||||
*/
|
||||
typedef struct r_annotated_code_t {
|
||||
char *code; // owned
|
||||
RVector /*<RCodeAnnotation>*/ annotations;
|
||||
char *code; /**< Decompiled code. RAnnotatedCode owns this string and it must free it. */
|
||||
RVector annotations; /**< @ref RVector <RCodeAnnotation> contains the list of annotations for the decompiled code. */
|
||||
} RAnnotatedCode;
|
||||
|
||||
/**
|
||||
* r_annotated_code_new() - Creates a new RAnnotatedCode structure and returns its pointer.
|
||||
* @code: Literal code for which the RAnnotatedCode structure will be created .
|
||||
*
|
||||
* This functions creates a new RAnnotatedCode structure.
|
||||
* RAnnotatedCode.code will be initialized as the character array passed.
|
||||
* Here, code must be a string that can deallocated.
|
||||
* This will initialize RVector<RCodeAnnotation> annotations as well.
|
||||
* @brief Create and initialize a RAnnotatedCode structure and returns its pointer.
|
||||
*
|
||||
* Return: Pointer to the new RAnnotatedCode structure created.
|
||||
* This function creates and initializes a new RAnnotatedCode
|
||||
* structure with the specified decompiled code that's passed
|
||||
* as an argument. Here, the argument code must be a string that can be deallocated.
|
||||
* This will initialize @ref RVector <RCodeAnnotation> annotations as well.
|
||||
*
|
||||
* @param code A deallocatable character array.
|
||||
* @return Pointer to the new RAnnotatedCode structure created.
|
||||
*/
|
||||
R_API RAnnotatedCode *r_annotated_code_new(char *code);
|
||||
/**
|
||||
* r_annotated_code_free() - Deallocates *code.
|
||||
* @code: Pointer to a RAnnotatedCode.
|
||||
*
|
||||
* This functions deallocates memory allocated for *code.
|
||||
* @brief Deallocates the dynamically allocated memory for the specified RAnnotatedCode.
|
||||
*
|
||||
* Return: Nothing.
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
*/
|
||||
R_API void r_annotated_code_free(RAnnotatedCode *code);
|
||||
/**
|
||||
* r_annotated_code_add_annotation() - Inserts *annotation in *code.
|
||||
* @code: Pointer to a RAnnotatedCode.
|
||||
* @annotation: Pointer to a annotation.
|
||||
*
|
||||
* This functions inserts the annotation represented by the pointer 'annotation' to the vector
|
||||
* of annotations in the RAnnotatedCode represented by 'code'. To be more precise,
|
||||
* annotation will be added to code->annotations, which is a RVector<RCodeAnnotation> annotations.
|
||||
* @brief Deallocates dynamically allocated memory for the specified annotation.
|
||||
*
|
||||
* Return: Nothing.
|
||||
* This function recognizes the type of the specified annotation and
|
||||
* frees memory that is dynamically allocated for it.
|
||||
*
|
||||
* @param e Pointer to the annotation.
|
||||
* @param user Always NULL for this function. Present here for this function to be of the type @ref RVectorFree.
|
||||
*/
|
||||
R_API void r_annotation_free(void *e, void *user);
|
||||
/**
|
||||
* @brief Checks if the specified annotation is a reference.
|
||||
*
|
||||
* This function recognizes the type of the specified annotation and returns true if its
|
||||
* type is any of the following three: R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE,
|
||||
* R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE, R_CODE_ANNOTATION_TYPE_FUNCTION_NAME
|
||||
*
|
||||
* @param annotation Pointer to an annotation.
|
||||
* @return Returns true if the specified annotation is a reference.
|
||||
*/
|
||||
R_API bool r_annotation_is_reference(RCodeAnnotation *annotation);
|
||||
/**
|
||||
* @brief Checks if the specified annotation is a function variable.
|
||||
*
|
||||
* This function recognizes the type of the specified annotation and returns true if its
|
||||
* type is any of the following two: R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE,
|
||||
* R_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER
|
||||
*
|
||||
* @param annotation Pointer to an annotation.
|
||||
* @return Returns true if the specified annotation is a function variable.
|
||||
*/
|
||||
R_API bool r_annotation_is_variable(RCodeAnnotation *annotation);
|
||||
/**
|
||||
* @brief Inserts the specified annotation into the list of annotations in the specified RAnnotatedCode.
|
||||
*
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
* @param annotation Pointer to an annotation.
|
||||
*/
|
||||
R_API void r_annotated_code_add_annotation(RAnnotatedCode *code, RCodeAnnotation *annotation);
|
||||
/**
|
||||
* r_annotated_code_annotations_in() - Returns all annotations with range that contains the given offset.
|
||||
* @code: Pointer to a RAnnotatedCode.
|
||||
* @offset: Offset.
|
||||
*
|
||||
* Creates an RPVector and inserts the pointers to all annotations in which
|
||||
* @brief Returns all annotations with range that contains the given offset.
|
||||
*
|
||||
* Creates a @ref RPVector <RCodeAnnotation> and inserts the pointers to all annotations in which
|
||||
* annotation->start <= offset < annotation->end.
|
||||
*
|
||||
* Return: Pointer to the RPVecrtor created.
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
* @param offset Offset.
|
||||
* @return Pointer to the @ref RPVector created.
|
||||
*/
|
||||
R_API RPVector *r_annotated_code_annotations_in(RAnnotatedCode *code, size_t offset);
|
||||
/**
|
||||
* r_annotated_code_annotations_range() - Returns all annotations with range that overlap with the given range.
|
||||
* @code: Pointer to a RAnnotatedCode.
|
||||
* @start: Start of the range(inclusive).
|
||||
* @end: End of the range(exclusive).
|
||||
*
|
||||
* Creates an RPVector and inserts the pointers to all annotations whose
|
||||
* range overlap with range [start, end-1] (both inclusive).
|
||||
* @brief Returns all annotations with range that overlap with the specified range.
|
||||
*
|
||||
* Return: Pointer to the RPVecrtor created.
|
||||
* Creates an @ref RPVector <RCodeAnnotation> and inserts the pointers to all annotations whose
|
||||
* range overlap with range specified.
|
||||
*
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
* @param start Start of the range(inclusive).
|
||||
* @param end End of the range(exclusive).
|
||||
* @return Pointer to the @ref RPVector created.
|
||||
*/
|
||||
R_API RPVector *r_annotated_code_annotations_range(RAnnotatedCode *code, size_t start, size_t end);
|
||||
/**
|
||||
* r_annotated_code_line_offsets() - Returns the offset for every line of decompiled code in RAnnotatedCode *code.
|
||||
* @code: Pointer to a RAnnotatedCode.
|
||||
*
|
||||
* Creates an RVector and inserts the offsets for every seperate line of decompiled code in
|
||||
* code->code (code->code is a character array).
|
||||
* @brief Returns the offset for every line of decompiled code in the specified RAnnotatedCode.
|
||||
*
|
||||
* Creates an @ref RVector <ut64> and inserts the offsets for every seperate line of decompiled code in
|
||||
* the specified RAnnotatedCode.
|
||||
* If a line of decompiled code doesn't have a unique offset, UT64_MAX is inserted as its offset.
|
||||
*
|
||||
* Return: Pointer to the RVector created.
|
||||
*
|
||||
* @param code Pointer to a RAnnotatedCode.
|
||||
* @return Pointer to the @ref RVector created.
|
||||
*/
|
||||
R_API RVector *r_annotated_code_line_offsets(RAnnotatedCode *code);
|
||||
|
||||
|
@ -9,10 +9,28 @@ R_API RAnnotatedCode *r_annotated_code_new(char *code) {
|
||||
return NULL;
|
||||
}
|
||||
r->code = code;
|
||||
r_vector_init (&r->annotations, sizeof (RCodeAnnotation), NULL, NULL);
|
||||
r_vector_init (&r->annotations, sizeof (RCodeAnnotation), r_annotation_free, NULL);
|
||||
return r;
|
||||
}
|
||||
|
||||
R_API void r_annotation_free(void *e, void *user) {
|
||||
(void)user;
|
||||
RCodeAnnotation *annotation = e;
|
||||
if (annotation->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||
free (annotation->reference.name);
|
||||
} else if (annotation->type == R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE || annotation->type == R_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER) {
|
||||
free (annotation->variable.name);
|
||||
}
|
||||
}
|
||||
|
||||
R_API bool r_annotation_is_reference(RCodeAnnotation *annotation) {
|
||||
return (annotation->type == R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE || annotation->type == R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE || annotation->type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME);
|
||||
}
|
||||
|
||||
R_API bool r_annotation_is_variable(RCodeAnnotation *annotation) {
|
||||
return (annotation->type == R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE || annotation->type == R_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER);
|
||||
}
|
||||
|
||||
R_API void r_annotated_code_free(RAnnotatedCode *code) {
|
||||
if (!code) {
|
||||
return;
|
||||
|
@ -21,6 +21,31 @@ static RCodeAnnotation make_code_annotation(int st, int en, RCodeAnnotationType
|
||||
return annotation;
|
||||
}
|
||||
|
||||
static RCodeAnnotation make_variable_annotation(int st, int en, RCodeAnnotationType typec,
|
||||
const char *name) {
|
||||
RCodeAnnotation annotation = { 0 };
|
||||
annotation.start = st;
|
||||
annotation.end = en;
|
||||
annotation.type = typec;
|
||||
annotation.variable.name = strdup (name);
|
||||
return annotation;
|
||||
}
|
||||
|
||||
static RCodeAnnotation make_reference_annotation(int st, int en, RCodeAnnotationType typec,
|
||||
ut64 offset, const char *name) {
|
||||
RCodeAnnotation annotation = { 0 };
|
||||
annotation.start = st;
|
||||
annotation.end = en;
|
||||
annotation.type = typec;
|
||||
annotation.reference.offset = offset;
|
||||
if (annotation.type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||
annotation.reference.name = strdup (name);
|
||||
} else {
|
||||
annotation.reference.name = NULL;
|
||||
}
|
||||
return annotation;
|
||||
}
|
||||
|
||||
static RVector *get_some_code_annotation_for_add(void) {
|
||||
RVector *test_annotations = r_vector_new (sizeof (RCodeAnnotation), NULL, NULL);
|
||||
RCodeAnnotation annotation;
|
||||
@ -97,6 +122,22 @@ static RAnnotatedCode *get_hello_world(void) {
|
||||
return code;
|
||||
}
|
||||
|
||||
static RAnnotatedCode *get_all_context_annotated_code(void) {
|
||||
char *test_string = strdup ("\nfunc-name\nconst-var\n global-var(\"Hello, local-var\");\n function-param\n}\n");
|
||||
RAnnotatedCode *code = r_annotated_code_new (test_string);
|
||||
RCodeAnnotation function_name = make_reference_annotation (1, 10, R_CODE_ANNOTATION_TYPE_FUNCTION_NAME, 1234, "func-name");
|
||||
RCodeAnnotation constant_variable = make_reference_annotation (10, 19, R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE, 12345, NULL);
|
||||
RCodeAnnotation global_variable = make_reference_annotation (23, 33, R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE, 123456, NULL);
|
||||
RCodeAnnotation local_variable = make_variable_annotation (42, 51, R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE, "local-var");
|
||||
RCodeAnnotation function_parameter = make_variable_annotation (59, 73, R_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER, "function-param");
|
||||
r_annotated_code_add_annotation (code, &function_name);
|
||||
r_annotated_code_add_annotation (code, &constant_variable);
|
||||
r_annotated_code_add_annotation (code, &global_variable);
|
||||
r_annotated_code_add_annotation (code, &local_variable);
|
||||
r_annotated_code_add_annotation (code, &function_parameter);
|
||||
return code;
|
||||
}
|
||||
|
||||
static bool test_r_annotated_code_new(void) {
|
||||
//Testing RAnnoatedCode->code
|
||||
char *test_string = strdup ("How are you?");
|
||||
@ -267,6 +308,23 @@ static bool test_r_core_annotated_code_print_json(void) {
|
||||
mu_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tests JSON output for all context related annotations
|
||||
*/
|
||||
static bool test_r_core_annotated_code_print_json_context_annotations(void) {
|
||||
RAnnotatedCode *code = get_all_context_annotated_code ();
|
||||
char *expected = "{\"code\":\"\\nfunc-name\\nconst-var\\n global-var(\\\"Hello, local-var\\\");\\n function-param\\n}\\n\",\"annotations\":[{\"start\":1,\"end\":10,\"type\":\"function_name\",\"name\":\"func-name\",\"offset\":1234},{\"start\":10,\"end\":19,\"type\":\"constant_variable\",\"offset\":12345},{\"start\":23,\"end\":33,\"type\":\"global_variable\",\"offset\":123456},{\"start\":42,\"end\":51,\"type\":\"local_variable\",\"name\":\"local-var\"},{\"start\":59,\"end\":73,\"type\":\"function_parameter\",\"name\":\"function-param\"}]}\n";
|
||||
r_cons_new ();
|
||||
r_cons_push ();
|
||||
r_core_annotated_code_print_json (code);
|
||||
char *actual = strdup (r_cons_get_buffer ());
|
||||
r_cons_pop ();
|
||||
mu_assert_streq (actual, expected, "r_core_annotated_code_print_json() output doesn't match with the expected output");
|
||||
free (actual);
|
||||
r_annotated_code_free (code);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_r_core_annotated_code_print(void) {
|
||||
RAnnotatedCode *code = get_hello_world ();
|
||||
char *actual;
|
||||
@ -325,6 +383,46 @@ static bool test_r_core_annotated_code_print_comment_cmds(void) {
|
||||
mu_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tests functions r_annotation_is_variable(), r_annotation_is_reference(), and r_annotation_free()
|
||||
*/
|
||||
static bool test_r_annotation_free_and_is_annotation_type_functions(void) {
|
||||
// Making all types of annotations
|
||||
RCodeAnnotation offset = make_code_annotation (58, 64, R_CODE_ANNOTATION_TYPE_OFFSET, 4447, R_SYNTAX_HIGHLIGHT_TYPE_KEYWORD);
|
||||
RCodeAnnotation syntax_highlight = make_code_annotation (1, 5, R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT, 123, R_SYNTAX_HIGHLIGHT_TYPE_DATATYPE);
|
||||
RCodeAnnotation local_variable = make_variable_annotation (1, 2, R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE, "RADARE2");
|
||||
RCodeAnnotation function_parameter = make_variable_annotation (4, 10, R_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE, "Cutter");
|
||||
RCodeAnnotation function_name = make_reference_annotation (10, 12, R_CODE_ANNOTATION_TYPE_FUNCTION_NAME, 123513, "test_function");
|
||||
RCodeAnnotation global_variable = make_reference_annotation (10, 12, R_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE, 1234234, NULL);
|
||||
RCodeAnnotation constant_variable = make_reference_annotation (21, 200, R_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE, 12342314, NULL);
|
||||
// Test r_annotation_is_variable()
|
||||
char *error_message = "r_annotation_is_variable() result doesn't match with the expected output";
|
||||
mu_assert_true (r_annotation_is_variable (&local_variable), error_message);
|
||||
mu_assert_true (r_annotation_is_variable (&function_parameter), error_message);
|
||||
mu_assert_false (r_annotation_is_variable (&function_name), error_message);
|
||||
mu_assert_false (r_annotation_is_variable (&global_variable), error_message);
|
||||
mu_assert_false (r_annotation_is_variable (&constant_variable), error_message);
|
||||
mu_assert_false (r_annotation_is_variable (&offset), error_message);
|
||||
mu_assert_false (r_annotation_is_variable (&syntax_highlight), error_message);
|
||||
// Test r_annotation_is_reference()
|
||||
error_message = "r_annotation_is_reference() result doesn't match with the expected output";
|
||||
mu_assert_true (r_annotation_is_reference (&function_name), error_message);
|
||||
mu_assert_true (r_annotation_is_reference (&global_variable), error_message);
|
||||
mu_assert_true (r_annotation_is_reference (&constant_variable), error_message);
|
||||
mu_assert_false (r_annotation_is_reference (&local_variable), error_message);
|
||||
mu_assert_false (r_annotation_is_reference (&function_parameter), error_message);
|
||||
mu_assert_false (r_annotation_is_reference (&offset), error_message);
|
||||
mu_assert_false (r_annotation_is_reference (&syntax_highlight), error_message);
|
||||
// Free dynamically allocated memory for annotations.
|
||||
// This is also supposed to be a test of r_annotation_free() for run errors.
|
||||
r_annotation_free (&local_variable, NULL);
|
||||
r_annotation_free (&function_parameter, NULL);
|
||||
r_annotation_free (&function_name, NULL);
|
||||
r_annotation_free (&global_variable, NULL);
|
||||
r_annotation_free (&constant_variable, NULL);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static int all_tests(void) {
|
||||
mu_run_test (test_r_annotated_code_new);
|
||||
mu_run_test (test_r_annotated_code_free);
|
||||
@ -333,8 +431,10 @@ static int all_tests(void) {
|
||||
mu_run_test (test_r_annotated_code_annotations_range);
|
||||
mu_run_test (test_r_annotated_code_line_offsets);
|
||||
mu_run_test (test_r_core_annotated_code_print_json);
|
||||
mu_run_test (test_r_core_annotated_code_print_json_context_annotations);
|
||||
mu_run_test (test_r_core_annotated_code_print);
|
||||
mu_run_test (test_r_core_annotated_code_print_comment_cmds);
|
||||
mu_run_test (test_r_annotation_free_and_is_annotation_type_functions);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user