#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
+#include <ctype.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
return tc_error;
}
+/* Tracecut identifiers must consist entirely of the characters
+ [_0-9a-zA-Z] with no spaces. */
+static int
+is_id_char(char c)
+{
+ return (c == '_' || ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z'))
+ || ((c >= 'A') && (c <= 'Z')));
+}
+
+/* Does the input string follow the rules for tracecut identifiers? */
+static int
+is_valid_identifier(const char *str)
+{
+ int i;
+
+ for (i = 0; str[i] != '\0'; i++)
+ {
+ if (!is_id_char (*str))
+ return 0;
+ }
+
+ if (i > TC_MAX_ID_SIZE)
+ return 0;
+
+ return 1;
+}
+
/**
* The first operation on a tracecut that fails stores its error code
* in the tracecut. This function returns that error code, or
tc->tc_error = TC_SUCCESS;
}
-enum tc_error
-tc_check_param_type(const struct aop_type *type)
+static enum tc_error
+check_param_type(const struct aop_type *type)
{
if(aop_is_pointer_type (type) ||
aop_is_all_signed_subtype (type) ||
* started;
* - #TC_DUPLICATE, if there already exists a param with the
* specified name;
+ * - #TC_BAD_ID if name is not an acceptable identifier. (Identifiers
+ * must only contain letters, numbers and the underscore character,
+ * with no spaces. Identifiers are case sensitive and should be no
+ * longer than #TC_MAX_ID_SIZE.)
* - #TC_INVAL, if aop_is_pointer_type() is false for the specified
* type;
* - #TC_NOMEM, if memory runs out.
if (tc_in_compilation)
return return_error (tc, TC_BAD_CONTEXT);
- tc_err = tc_check_param_type(type);
+ if (!is_valid_identifier (name))
+ return return_error (tc, TC_BAD_ID);
+
+ tc_err = check_param_type(type);
if(tc_err != TC_SUCCESS)
- return tc_err;
+ return return_error (tc, tc_err);
if (lookup_param (tc, name) != NULL)
return return_error (tc, TC_DUPLICATE);
* started;
* - #TC_DUPLICATE, if there already exists a symbol with the
* specified name;
+ * - #TC_BAD_ID if name is not an acceptable identifier. (Identifiers
+ * must only contain letters, numbers and the underscore character,
+ * with no spaces. Identifiers are case sensitive and should be no
+ * longer than #TC_MAX_ID_SIZE.)
* - #TC_NOMEM, if memory runs out.
*/
enum tc_error
if (tc_in_compilation)
return return_error (tc, TC_BAD_CONTEXT);
+ if (!is_valid_identifier (name))
+ return return_error (tc, TC_BAD_ID);
+
if (lookup_call_symbol (tc, name) != NULL)
return return_error (tc, TC_DUPLICATE);
return add_call_symbol_binding (tc, param_name, symbol_name, -1);
}
+/**
+ * \cond HIDDEN_SYMBOLS
+ */
+#define MAX_FUNC_SIZE 255
+/**
+ * \endcond
+ */
+
/**
* Create a function call symbol along with its bindings in one
* statement. The declaration is a string containing the function
* - #TC_BAD_CONTEXT, when called after compilation has already
* started;
* - #TC_INVAL, when the declaration is invalid because of syntax
- errors;
+ * errors;
* - #TC_DUPLICATE, if there already exists a symbol with the
* specified name;
+ * - #TC_BAD_ID if name is not an acceptable identifier. (Identifiers
+ * must only contain letters, numbers and the underscore character,
+ * with no spaces. Identifiers are case sensitive and should be no
+ * longer than #TC_MAX_ID_SIZE.)
* - #TC_NOENT, if one of the parameters in the declaration does not
- exist;
+ * exist;
* - #TC_NOMEM, if memory runs out.
*/
enum tc_error
const char *declaration,
enum aop_insert_location location)
{
- int i = 0, pos = 0;
- int param_num = 0, space_track = 0;
+ int i = 0, pos;
+ int param_num;
enum tc_error tc_err;
- char func_name[MAX_FUNC_SIZE], return_param[MAX_PARAM_SIZE], param_name[MAX_PARAM_SIZE];
+ char func_name[MAX_FUNC_SIZE];
+ char param_name[TC_MAX_ID_SIZE];
if (tc_in_compilation)
return return_error (tc, TC_BAD_CONTEXT);
-
- strcpy(return_param, "");
- strcpy(func_name, "");
- strcpy(param_name, "");
+
+ strcpy (param_name, "");
/* Eliminate white spaces */
- while (declaration[i] == ' ')
+ while (isspace(declaration[i]))
i++;
/* Check if return parameter is present */
if (declaration[i] == '(')
{
- /* Copy the return param */
+ /* Consume the (. */
i++;
+
/* Remove beginning spaces */
- while (declaration[i] == ' ')
+ while (isspace(declaration[i]))
i++;
- while (declaration[i] != ')')
+
+ if (declaration[i] == '?')
{
- /* If space, copy the name */
- if(declaration[i] == ' ')
- break;
- return_param[pos++] = declaration[i++];
- }
- return_param[pos] = '\0';
- pos = 0;
- if (declaration[i] == ')')
+ /* Consume the ?. */
i++;
+ }
else
{
- while (declaration[i] != ')')
- {
- if(declaration[i] == ' ')
- i++;
- else
- {
- return TC_INVAL;
- }
- }
- i++;
+ /* Copy the return param */
+ pos = 0;
+ while (is_id_char(declaration[i]) && pos + 1 < TC_MAX_ID_SIZE)
+ param_name[pos++] = declaration[i++];
+ param_name[pos] = '\0';
+
+ /* Bad return param. */
+ if (pos == 0)
+ return return_error (tc, TC_INVAL);
}
+
+ while (isspace(declaration[i]))
+ i++;
+
+ /* Unmatched parenthesis. */
+ if (declaration[i] != ')')
+ return return_error (tc, TC_INVAL);
+
+ i++; /* Consume the ). */
}
/* Ignore the white spaces in between */
i++;
/* Copy the function name */
- while(declaration[i] != '(')
- {
- if (declaration[i] == ' ')
- break;
- func_name[pos++] = declaration[i++];
- }
-
- func_name[pos] = '\0';
pos = 0;
+ while(is_id_char(declaration[i]) && pos + 1 < MAX_FUNC_SIZE)
+ func_name[pos++] = declaration[i++];
+ func_name[pos] = '\0';
- if (declaration[i] == '(')
+ while (isspace(declaration[i]))
i++;
- else
- {
- while (declaration[i] != '(')
- {
- if (declaration[i] == ' ')
- i++;
- else
- {
- return TC_INVAL;
- }
- }
- i++;
- }
-
+
+ if (pos == 0 || declaration[i] != '(')
+ return return_error (tc, TC_INVAL);
+
+ /* Consume the (. */
+ i++;
+
/* Add functiona name */
- if (strcmp(func_name, ""))
- {
- tc_err = tc_add_call_symbol (tc,
- name,
- func_name,
- location);
- if (tc_err != TC_SUCCESS)
- {
- return tc_err;
- }
- }
+ tc_err = tc_add_call_symbol (tc, name, func_name, location);
+ if (tc_err != TC_SUCCESS)
+ return tc_err;
/* Bind return parameter */
- if (strcmp(return_param, ""))
+ if (strcmp(param_name, "") != 0)
{
- tc_err = tc_bind_to_return_value (tc,
- return_param,
- name);
-
- if (tc_err != TC_SUCCESS)
- {
- return tc_err;
- }
- }
+ tc_err = tc_bind_to_return_value (tc, param_name, name);
- /* Skip spaces */
- while (declaration[i] == ' ')
- i++;
+ if (tc_err != TC_SUCCESS)
+ return tc_err;
+ }
- /* Parse function parameters and add them */
- while (declaration[i] != '\0')
+ /* Parse function parameters and add them. */
+ for (param_num = 0; ; param_num++)
{
- if (declaration[i] == ' ' && pos == 0)
- {
- /* If it is beginning of the parameter */
+ /* Skip spaces */
+ while (isspace(declaration[i]))
+ i++;
+
+ /* Special case: no paremeters. */
+ if (declaration[i] == ')')
+ {
i++;
- continue;
- }
- else if (declaration[i] == ' ' && pos != 0)
+ break;
+ }
+
+ if (declaration[i] == '?')
{
- /* Space while parsing the param name */
- space_track = 1;
+ /* Consume the ? and ignore this parameter. */
i++;
- continue;
}
- else if ((declaration[i] != ')' && declaration[i] != ',') &&
- (space_track == 1))
+ else
{
- return TC_INVAL;
+ pos = 0;
+ while (is_id_char(declaration[i]) && pos + 1 < TC_MAX_ID_SIZE)
+ param_name[pos++] = declaration[i++];
+ param_name[pos] = '\0';
+
+ if (pos == 0)
+ return return_error (tc, TC_INVAL);
+
+ /* Param found, insert it */
+ tc_err = tc_bind_to_call_param (tc, param_name, name, param_num);
+
+ if (tc_err != TC_SUCCESS)
+ return tc_err;
+ }
+
+ /* Skip spaces */
+ while (isspace(declaration[i]))
+ i++;
+
+ if (declaration[i] == ')')
+ {
+ /* Done with parameters. */
+ i++;
+ break;
+ }
+ else if (declaration[i] == ',')
+ {
+ /* Consume the comma. */
+ i++;
+ }
+ else
+ {
+ return return_error (tc, TC_INVAL);
}
- else if (declaration[i] == ',' || declaration[i] == ')')
- {
- /* Store param */
- space_track = 0;
- param_name[pos] = '\0';
-
- printf("%s\n", param_name);
- if(strcmp(param_name, "?") && pos != 0)
- {
- /* Param found, insert it */
- tc_err = tc_bind_to_call_param (tc,
- param_name,
- name,
- param_num);
-
- if (tc_err != TC_SUCCESS)
- {
- return tc_err;
- }
- }
- param_num++;
- i++;
- pos = 0;
- continue;
- }
-
- param_name[pos++] = declaration[i++];
}
- return return_error (tc, TC_SUCCESS);
+ /* Make sure there's no junk hanging off the end of the
+ declaration. */
+ while (isspace(declaration[i]))
+ i++;
+ if (declaration[i] != '\0')
+ return return_error (tc, TC_INVAL);
+
+ return return_error (tc, TC_SUCCESS);
}
/**
AOP_TERM_ARG);
}
+/**
+ * \cond HIDDEN_SYMBOLS
+ */
struct join_on_call_arg {
struct tc_tracecut *tc;
struct tc_call_symbol *symbol;
};
+/**
+ * \endcond
+ */
static void
join_on_call (struct aop_joinpoint *jp, void *callback_arg)