cfgparser.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /****************************************************************************
  2. * tools/cfgparser.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include "cfgparser.h"
  27. /****************************************************************************
  28. * Pre-processor Definitions
  29. ****************************************************************************/
  30. /****************************************************************************
  31. * Public Data
  32. ****************************************************************************/
  33. char line[LINESIZE + 1];
  34. /****************************************************************************
  35. * Private Data
  36. ****************************************************************************/
  37. /****************************************************************************
  38. * Private Functions
  39. ****************************************************************************/
  40. /* Skip over any spaces */
  41. static char *skip_space(char *ptr)
  42. {
  43. while (*ptr && isspace((int)*ptr)) ptr++;
  44. return ptr;
  45. }
  46. /* Find the end of a variable string */
  47. static char *find_name_end(char *ptr)
  48. {
  49. while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++;
  50. return ptr;
  51. }
  52. /* Find the end of a value string */
  53. static char *find_value_end(char *ptr)
  54. {
  55. while (*ptr && !isspace((int)*ptr))
  56. {
  57. if (*ptr == '"')
  58. {
  59. do ptr++; while (*ptr && *ptr != '"');
  60. if (*ptr) ptr++;
  61. }
  62. else
  63. {
  64. do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"');
  65. }
  66. }
  67. return ptr;
  68. }
  69. /* Read the next line from the configuration file */
  70. static char *read_line(FILE *stream)
  71. {
  72. char *ptr;
  73. for (; ; )
  74. {
  75. line[LINESIZE] = '\0';
  76. if (!fgets(line, LINESIZE, stream))
  77. {
  78. return NULL;
  79. }
  80. else
  81. {
  82. ptr = skip_space(line);
  83. if (*ptr && *ptr != '#' && *ptr != '\n')
  84. {
  85. return ptr;
  86. }
  87. }
  88. }
  89. }
  90. /* Parse the line from the configuration file into a variable name
  91. * string and a value string.
  92. */
  93. static void parse_line(char *ptr, char **varname, char **varval)
  94. {
  95. /* Skip over any leading spaces */
  96. ptr = skip_space(ptr);
  97. /* The first no-space is the beginning of the variable name */
  98. *varname = skip_space(ptr);
  99. *varval = NULL;
  100. /* Parse to the end of the variable name */
  101. ptr = find_name_end(ptr);
  102. /* An equal sign is expected next, perhaps after some white space */
  103. if (*ptr && *ptr != '=')
  104. {
  105. /* Some else follows the variable name. Terminate the variable
  106. * name and skip over any spaces.
  107. */
  108. *ptr = '\0';
  109. ptr = skip_space(ptr + 1);
  110. }
  111. /* Verify that the equal sign is present */
  112. if (*ptr == '=')
  113. {
  114. /* Make sure that the variable name is terminated (this was already
  115. * done if the name was followed by white space.
  116. */
  117. *ptr = '\0';
  118. /* The variable value should follow =, perhaps separated by some
  119. * white space.
  120. */
  121. ptr = skip_space(ptr + 1);
  122. if (*ptr)
  123. {
  124. /* Yes.. a variable follows. Save the pointer to the start
  125. * of the variable string.
  126. */
  127. *varval = ptr;
  128. /* Find the end of the variable string and make sure that it
  129. * is terminated.
  130. */
  131. ptr = find_value_end(ptr);
  132. *ptr = '\0';
  133. }
  134. }
  135. }
  136. /****************************************************************************
  137. * Public Functions
  138. ****************************************************************************/
  139. void parse_file(FILE *stream, struct variable_s **list)
  140. {
  141. struct variable_s *curr;
  142. struct variable_s *prev;
  143. struct variable_s *next;
  144. char *varname;
  145. char *varval;
  146. char *ptr;
  147. /* Loop until the entire file has been parsed. */
  148. do
  149. {
  150. /* Read the next line from the file */
  151. ptr = read_line(stream);
  152. if (ptr)
  153. {
  154. /* Parse the line into a variable and a value field */
  155. parse_line(ptr, &varname, &varval);
  156. /* If the variable has no value (or the special value 'n'), then
  157. * ignore it.
  158. */
  159. if (!varval || strcmp(varval, "n") == 0)
  160. {
  161. continue;
  162. }
  163. /* Make sure that a variable name was found. */
  164. if (varname)
  165. {
  166. int varlen = strlen(varname) + 1;
  167. int vallen = 0;
  168. /* Get the size of the value, including the NUL terminating
  169. * character.
  170. */
  171. if (varval)
  172. {
  173. vallen = strlen(varval) + 1;
  174. }
  175. /* Allocate memory to hold the struct variable_s with the
  176. * variable name and the value.
  177. */
  178. curr = (struct variable_s *)malloc(sizeof(struct variable_s) +
  179. varlen + vallen - 1);
  180. if (curr)
  181. {
  182. /* Add the variable to the list */
  183. curr->var = &curr->storage[0];
  184. strcpy(curr->var, varname);
  185. curr->val = NULL;
  186. if (varval)
  187. {
  188. curr->val = &curr->storage[varlen];
  189. strcpy(curr->val, varval);
  190. }
  191. prev = 0;
  192. next = *list;
  193. while (next && strcmp(next->var, curr->var) <= 0)
  194. {
  195. prev = next;
  196. next = next->flink;
  197. }
  198. if (prev)
  199. {
  200. prev->flink = curr;
  201. }
  202. else
  203. {
  204. *list = curr;
  205. }
  206. curr->flink = next;
  207. }
  208. }
  209. }
  210. }
  211. while (ptr);
  212. }
  213. struct variable_s *find_variable(const char *varname,
  214. struct variable_s *list)
  215. {
  216. while (list)
  217. {
  218. if (strcmp(varname, list->var) == 0)
  219. {
  220. return list;
  221. }
  222. list = list->flink;
  223. }
  224. return NULL;
  225. }