/** * osl_util_read_line function: * reads a line on the input 'file' or the input string 'str' depending on * which one is not NULL (exactly one of them must not be NULL). A line * is defined as the array of characters before the comment tag or the end of * line (it may include spaces). * \param[in] file The file where to read a line (if not NULL). * \param[in,out] str The string where to read a line (if not NULL). This * pointer is updated to reflect the read and points * after the line in the input string. * \return The line that has been read. */ char * osl_util_read_line(FILE * file, char ** str) { char s[OSL_MAX_STRING], * start; char * res; int i = 0; if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) OSL_error("one and only one of the two parameters can be non-NULL"); OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char)); if (file != NULL) { // Parse from a file. start = osl_util_skip_blank_and_comments(file, s); while (*start && *start != '\n' && *start != '#' && i < OSL_MAX_STRING) res[i++] = *start++; } else { // Parse from a string. osl_util_sskip_blank_and_comments(str); while (**str && **str != '\n' && **str != '#' && i < OSL_MAX_STRING) res[i++] = *((*str)++); } res[i] = '\0'; OSL_realloc(res, char *, strlen(res) + 1); return res; }
/** * osl_util_read_string function: * reads a string on the input 'file' or the input string 'str' depending on * which one is not NULL (exactly one of them must not be NULL). * \param[in] file The file where to read a string (if not NULL). * \param[in,out] str The string where to read a string (if not NULL). This * pointer is updated to reflect the read and points * after the string in the input string. * \return The string that has been read. */ char * osl_util_read_string(FILE * file, char ** str) { char s[OSL_MAX_STRING], * start; char * res; int i = 0; if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) OSL_error("one and only one of the two parameters can be non-NULL"); OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char)); if (file != NULL) { // Parse from a file. start = osl_util_skip_blank_and_comments(file, s); if (sscanf(start, " %s", res) != 1) OSL_error("a string was expected"); } else { // Parse from a string. // Skip blank/commented lines. osl_util_sskip_blank_and_comments(str); // Build the chain to analyze. while (**str && !isspace(**str) && **str != '\n' && **str != '#') s[i++] = *((*str)++); s[i] = '\0'; if (sscanf(s, "%s", res) != 1) OSL_error("a string was expected"); } OSL_realloc(res, char *, strlen(res) + 1); return res; }
/** * osl_util_read_int internal function: * reads a tag (the form of a tag with name "name" is \<name\>) on the input * 'file' or the input string 'str' depending on which one is not NULL (exactly * one of them must not be NULL). It returns the name of the tag (thus without * the < and > as a string. Note that in the case of an ending tag, e.g., * \</foo\>, the slash is returned as a part of the name, e.g., /foo. If no * tag is found the function returns NULL. * \param[in] file The file where to read a tag (if not NULL). * \param[in,out] str The string where to read a tag (if not NULL). This * pointer is updated to reflect the read and points * after the tag in the input string. * \return The tag name that has been read. */ char * osl_util_read_tag(FILE * file, char ** str) { char s[OSL_MAX_STRING], * start; char * res; int i = 0; if ((file != NULL && str != NULL) || (file == NULL && str == NULL)) OSL_error("one and only one of the two parameters can be non-NULL"); // Skip blank/commented lines. if (file != NULL) { start = osl_util_skip_blank_and_comments(file, s); str = &start; } else { osl_util_sskip_blank_and_comments(str); } // If the end of the input has been reached, return NULL. if (((file != NULL) && (feof(file))) || ((str != NULL) && (**str == '\0'))) return NULL; // Pass the starting '<'. if (**str != '<') OSL_error("a \"<\" to start a tag was expected"); (*str)++; // Read the tag. OSL_malloc(res, char *, (OSL_MAX_STRING + 1) * sizeof(char)); res[OSL_MAX_STRING] = '\0'; while (**str && **str != '>') { if (((**str >= 'A') && (**str <= 'Z')) || ((**str >= 'a') && (**str <= 'z')) || ((**str == '/') && (i == 0)) || (**str == '_')) { res[i++] = *((*str)++); res[i] = '\0'; } else { OSL_error("illegal character in the tag name"); } } // Check we actually end up with a '>' and pass it. if (**str != '>') OSL_error("a \">\" to end a tag was expected"); (*str)++; return res; }
/** * osl_strings_sread function: * this function reads a strings structure from a string complying to the * OpenScop textual format and returns a pointer to this strings structure. * The input string should only contain the list of strings this function * has to read (comments at the end of the line are accepted). The input * parameter is updated to the position in the input string this function * reach right after reading the strings structure. * \param[in,out] input The input string where to find a strings structure. * Updated to the position after what has been read. * \return A pointer to the strings structure that has been read. */ osl_strings_p osl_strings_sread(char ** input) { char tmp[OSL_MAX_STRING]; char * s; char ** string = NULL; int nb_strings; int i, count; osl_strings_p strings = NULL; // Skip blank/commented lines and spaces before the strings. osl_util_sskip_blank_and_comments(input); // Count the actual number of strings. nb_strings = 0; s = *input; while (1) { for (count = 0; *s && !isspace(*s) && *s != '#'; count++) s++; if (count != 0) nb_strings++; if ((!*s) || (*s == '#') || (*s == '\n')) break; else s++; } if (nb_strings > 0) { // Allocate the array of strings. Make it NULL-terminated. OSL_malloc(string, char **, sizeof(char *) * (nb_strings + 1)); string[nb_strings] = NULL; // Read the desired number of strings. s = *input; for (i = 0; i < nb_strings; i++) { for (count = 0; *s && !isspace(*s) && *s != '#'; count++) tmp[count] = *(s++); tmp[count] = '\0'; OSL_strdup(string[i], tmp); if (*s != '#') s++; } // Update the input pointer to the end of the strings structure. *input = s; // Build the strings structure strings = osl_strings_malloc(); free(strings->string); strings->string = string; }
/** * osl_body_read function: * this function reads a body structure from a string complying to the * OpenScop textual format and returns a pointer to this body structure. * The input string should only contain the body this function * has to read (comments at the end of the line are accepted). The input * parameter is updated to the position in the input string this function * reach right after reading the strings structure. * \param[in,out] input The input string where to find a body structure. * Updated to the position after what has been read. * \return A pointer to the body structure that has been read. */ osl_body_p osl_body_sread(char ** input) { osl_body_p body = NULL; char * expression; int nb_iterators; if (input) { body = osl_body_malloc(); // Read the number of iterators. nb_iterators = osl_util_read_int(NULL, input); // Read the iterator strings if any. if (nb_iterators > 0) body->iterators = osl_strings_sread(input); // Read the body: // - Skip blank/commented lines and spaces before the body. osl_util_sskip_blank_and_comments(input); // - Remove the comments after the body. expression = *input; while (*input && **input != '#' && **input != '\n') (*input)++; if (*input && **input == '#') { **input = '\0'; while (**input != '\n') (*input)++; } else { if (*input && **input == '\n') { **input = '\0'; (*input)++; } } // - Copy the body. body->expression = osl_strings_encapsulate(strdup(expression)); } return body; }