123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #include <common.h>
- #include <command.h>
- #include <environment.h>
- #include <linux/ctype.h>
- #include <linux/string.h>
- #ifdef CONFIG_INI_MAX_LINE
- #define MAX_LINE CONFIG_INI_MAX_LINE
- #else
- #define MAX_LINE 200
- #endif
- #ifdef CONFIG_INI_MAX_SECTION
- #define MAX_SECTION CONFIG_INI_MAX_SECTION
- #else
- #define MAX_SECTION 50
- #endif
- #ifdef CONFIG_INI_MAX_NAME
- #define MAX_NAME CONFIG_INI_MAX_NAME
- #else
- #define MAX_NAME 50
- #endif
- static char *rstrip(char *s)
- {
- char *p = s + strlen(s);
- while (p > s && isspace(*--p))
- *p = '\0';
- return s;
- }
- static char *lskip(const char *s)
- {
- while (*s && isspace(*s))
- s++;
- return (char *)s;
- }
- static char *find_char_or_comment(const char *s, char c)
- {
- int was_whitespace = 0;
- while (*s && *s != c && !(was_whitespace && *s == ';')) {
- was_whitespace = isspace(*s);
- s++;
- }
- return (char *)s;
- }
- static char *strncpy0(char *dest, const char *src, size_t size)
- {
- strncpy(dest, src, size);
- dest[size - 1] = '\0';
- return dest;
- }
- static char *memgets(char *str, int num, char **mem, size_t *memsize)
- {
- char *end;
- int len;
- int newline = 1;
- end = memchr(*mem, '\n', *memsize);
- if (end == NULL) {
- if (*memsize == 0)
- return NULL;
- end = *mem + *memsize;
- newline = 0;
- }
- len = min((end - *mem) + newline, num);
- memcpy(str, *mem, len);
- if (len < num)
- str[len] = '\0';
-
- *memsize -= (end - *mem) + newline;
- *mem += (end - *mem) + newline;
- return str;
- }
- static int ini_parse(char *filestart, size_t filelen,
- int (*handler)(void *, char *, char *, char *), void *user)
- {
-
- char line[MAX_LINE];
- char section[MAX_SECTION] = "";
- char prev_name[MAX_NAME] = "";
- char *curmem = filestart;
- char *start;
- char *end;
- char *name;
- char *value;
- size_t memleft = filelen;
- int lineno = 0;
- int error = 0;
-
- while (memgets(line, sizeof(line), &curmem, &memleft) != NULL) {
- lineno++;
- start = lskip(rstrip(line));
- if (*start == ';' || *start == '#') {
-
- }
- #if CONFIG_INI_ALLOW_MULTILINE
- else if (*prev_name && *start && start > line) {
-
- if (!handler(user, section, prev_name, start) && !error)
- error = lineno;
- }
- #endif
- else if (*start == '[') {
-
- end = find_char_or_comment(start + 1, ']');
- if (*end == ']') {
- *end = '\0';
- strncpy0(section, start + 1, sizeof(section));
- *prev_name = '\0';
- } else if (!error) {
-
- error = lineno;
- }
- } else if (*start && *start != ';') {
-
- end = find_char_or_comment(start, '=');
- if (*end != '=')
- end = find_char_or_comment(start, ':');
- if (*end == '=' || *end == ':') {
- *end = '\0';
- name = rstrip(start);
- value = lskip(end + 1);
- end = find_char_or_comment(value, '\0');
- if (*end == ';')
- *end = '\0';
- rstrip(value);
-
- if (value[0] == '"' &&
- value[strlen(value)-1] == '"') {
- value[strlen(value)-1] = '\0';
- value += 1;
- }
-
- strncpy0(prev_name, name, sizeof(prev_name));
- if (!handler(user, section, name, value) &&
- !error)
- error = lineno;
- } else if (!error)
-
- error = lineno;
- }
- }
- return error;
- }
- static int ini_handler(void *user, char *section, char *name, char *value)
- {
- char *requested_section = (char *)user;
- #ifdef CONFIG_INI_CASE_INSENSITIVE
- int i;
- for (i = 0; i < strlen(requested_section); i++)
- requested_section[i] = tolower(requested_section[i]);
- for (i = 0; i < strlen(section); i++)
- section[i] = tolower(section[i]);
- #endif
- if (!strcmp(section, requested_section)) {
- #ifdef CONFIG_INI_CASE_INSENSITIVE
- for (i = 0; i < strlen(name); i++)
- name[i] = tolower(name[i]);
- for (i = 0; i < strlen(value); i++)
- value[i] = tolower(value[i]);
- #endif
- setenv(name, value);
- printf("ini: Imported %s as %s\n", name, value);
- }
-
- return 1;
- }
- static int do_ini(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
- {
- const char *section;
- char *file_address;
- size_t file_size;
- if (argc == 1)
- return CMD_RET_USAGE;
- section = argv[1];
- file_address = (char *)simple_strtoul(
- argc < 3 ? getenv("loadaddr") : argv[2], NULL, 16);
- file_size = (size_t)simple_strtoul(
- argc < 4 ? getenv("filesize") : argv[3], NULL, 16);
- return ini_parse(file_address, file_size, ini_handler, (void *)section);
- }
- U_BOOT_CMD(
- ini, 4, 0, do_ini,
- "parse an ini file in memory and merge the specified section into the env",
- "section [[file-address] file-size]"
- );
|