From patchwork Wed Jun 17 14:48:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maciej Gajdzica X-Patchwork-Id: 5476 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 6DD6EC4C0; Wed, 17 Jun 2015 17:08:09 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id E2F37C4BE for ; Wed, 17 Jun 2015 17:08:07 +0200 (CEST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP; 17 Jun 2015 08:07:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,633,1427785200"; d="scan'208";a="748396320" Received: from unknown (HELO stargo) ([10.217.248.233]) by orsmga002.jf.intel.com with SMTP; 17 Jun 2015 08:07:46 -0700 Received: by stargo (sSMTP sendmail emulation); Wed, 17 Jun 2015 17:08:30 +0200 From: Maciej Gajdzica To: dev@dpdk.org Date: Wed, 17 Jun 2015 16:48:46 +0200 Message-Id: <1434552528-3576-5-git-send-email-maciejx.t.gajdzica@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1434552528-3576-1-git-send-email-maciejx.t.gajdzica@intel.com> References: <1434552528-3576-1-git-send-email-maciejx.t.gajdzica@intel.com> Subject: [dpdk-dev] [PATCH v2 4/6] cfgfile: added line continue character '\' to make multiline values possible X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Pawel Wodkowski Signed-off-by: Pawel Wodkowski --- lib/librte_cfgfile/rte_cfgfile.c | 147 ++++++++++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 14 deletions(-) diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index 2e78583..4e77ef5 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -116,6 +116,122 @@ strip_comment(char *buffer, size_t len) return len; } +/* Get line from file. It concatanate lines with line continue. + * If *line is not NULL it must point to malloced data buffer and *len must + * be the length of *line. + */ +static int +rte_cfgfile_getline(char **line, size_t *len, FILE *f, size_t *lineno) +{ + char *str = NULL; + size_t str_len = 0; + + void *buf; + char *line_str = NULL; + size_t line_size = 0; /* Whole buffer size */ + ssize_t line_len = 0; /* Length of line_str */ + + size_t line_cnt = 0; + int status = 0; + + if (!line) { + status = EINVAL; + goto error_exit; + } + + while (1) { + line_len = getline(&line_str, &line_size, f); + if (line_len <= 0) { + if (!feof(f)) { + status = -EIO; + goto error_exit; + } + + break; + } + + line_cnt++; + /* Replace last CR with LF */ + if (line_len > 0 && line_str[line_len - 1] == '\r') + line_str[line_len - 1] = '\n'; + + /* Replace last CRLF with LF */ + if (line_len > 1 && line_str[line_len - 2] == '\r' && + line_str[line_len - 1] == '\n') { + line_str[line_len - 1] = '\0'; + line_str[line_len - 2] = '\n'; + line_len -= 1; + } + + line_len = strip_comment(line_str, line_len); + + /* Special case for first line. */ + if (str == NULL) { + if (line_len == 0) + continue; + + str = line_str; + str_len = line_len; + + line_str = NULL; + line_len = 0; + } else { + if (line_len == 0) + break; + + buf = realloc(str, str_len + line_len + 1); + if (buf == NULL) { + status = -ENOMEM; + goto error_exit; + } + + str = buf; + memcpy(&str[str_len], line_str, line_len + 1); + + str_len += line_len; + } + + /* Check for line continue */ + if (str_len < 2 || str[str_len - 1] != '\n' || str[str_len - 2] != '\\') + break; + + /* Remove line continue character. */ + str[str_len - 1] = '\0'; + /* Change new line into space */ + str[str_len - 2] = ' '; + str_len -= 1; + } + + if (str_len) { + /* Squeeze str */ + buf = realloc(str, str_len + 1); + if (buf == NULL) { + status = -ENOMEM; + goto error_exit; + } + + free(*line); + *line = buf; + } + + if (len) + *len = str_len; + + if (lineno) + *lineno += line_cnt; + + free(line_str); + return 0; + +error_exit: + printf("Error: %s\n", strerror(status)); + if (lineno) + *lineno += line_cnt; + free(str); + free(line_str); + return status; +} + /** * Create new apty config file object. * @@ -153,9 +269,11 @@ rte_cfgfile_read(FILE *f, int flags) int allocated_entries = 0; int curr_section = -1; int curr_entry = -1; - char buffer[256]; - int lineno = 0; + char *buffer = NULL; + size_t len; + size_t lineno = 0; struct rte_cfgfile *cfg = NULL; + int status; if (f == NULL) return NULL; @@ -164,15 +282,12 @@ rte_cfgfile_read(FILE *f, int flags) if (cfg == NULL) goto error2; - while (fgets(buffer, sizeof(buffer), f) != NULL) { - size_t len = strnlen(buffer, sizeof(buffer)); - lineno++; - if ((len >= sizeof(buffer) - 1) && (buffer[len-1] != '\n')) { - printf("Error line %d - no \\n found on string. " - "Check if line too long\n", lineno); - goto error1; - } - len = strip_comment(buffer, len); + while (!feof(f)) { + status = rte_cfgfile_getline(&buffer, &len, f, &lineno); + if (status) + break; + else if (!len) + continue; len = _strip(buffer, len); if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL) @@ -182,7 +297,7 @@ rte_cfgfile_read(FILE *f, int flags) /* section heading line */ char *end = memchr(buffer, ']', len); if (end == NULL) { - printf("Error line %d - no terminating '['" + printf("Error line %zu - no terminating '['" "character found\n", lineno); goto error1; } @@ -227,7 +342,7 @@ rte_cfgfile_read(FILE *f, int flags) } else { /* value line */ if (curr_section < 0) { - printf("Error line %d - value outside of" + printf("Error line %zu - value outside of" "section\n", lineno); goto error1; } @@ -237,7 +352,7 @@ rte_cfgfile_read(FILE *f, int flags) char *split[2]; if (rte_strsplit(buffer, sizeof(buffer), split, 2, '=') != 2) { - printf("Error at line %d - cannot split " + printf("Error at line %zu - cannot split " "string\n", lineno); goto error1; } @@ -275,6 +390,10 @@ rte_cfgfile_read(FILE *f, int flags) sizeof(entry->value))); } } + + if (status) + goto error1; + fclose(f); cfg->flags = flags; cfg->num_sections = curr_section + 1;