xref: /wlan-dirver/qca-wifi-host-cmn/qdf/src/qdf_parse.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "qdf_file.h"
20 #include "qdf_module.h"
21 #include "qdf_parse.h"
22 #include "qdf_status.h"
23 #include "qdf_str.h"
24 #include "qdf_trace.h"
25 #include "qdf_types.h"
26 
27 QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
28 			 qdf_ini_item_cb item_cb, qdf_ini_section_cb section_cb)
29 {
30 	QDF_STATUS status;
31 	char *fbuf;
32 	char *cursor;
33 	int ini_read_count = 0;
34 
35 	status = qdf_file_read(ini_path, &fbuf);
36 	if (QDF_IS_STATUS_ERROR(status)) {
37 		qdf_err("Failed to read *.ini file @ %s", ini_path);
38 		return status;
39 	}
40 
41 	/* foreach line */
42 	cursor = fbuf;
43 	while (*cursor != '\0') {
44 		char *key = cursor;
45 		char *value = NULL;
46 		bool comment = false;
47 		bool eol = false;
48 
49 		/*
50 		 * Look for the end of the line, while noting any
51 		 * value ('=') or comment ('#') indicators
52 		 */
53 		while (!eol) {
54 			switch (*cursor) {
55 			case '\r':
56 			case '\n':
57 				*cursor = '\0';
58 				cursor++;
59 				/* fall through */
60 			case '\0':
61 				eol = true;
62 				break;
63 
64 			case '=':
65 				/*
66 				 * The first '=' is the value indicator.
67 				 * Subsequent '=' are valid value characters.
68 				 */
69 				if (!value && !comment) {
70 					value = cursor + 1;
71 					*cursor = '\0';
72 				}
73 
74 				cursor++;
75 				break;
76 
77 			case '#':
78 				/*
79 				 * We don't process comments, so we can null-
80 				 * terminate unconditionally here (unlike '=').
81 				 */
82 				comment = true;
83 				*cursor = '\0';
84 				/* fall through */
85 			default:
86 				cursor++;
87 				break;
88 			}
89 		}
90 
91 		key = qdf_str_trim(key);
92 
93 		/*
94 		 * Ignoring comments, a valid ini line contains one of:
95 		 *	1) some 'key=value' config item
96 		 *	2) section header
97 		 *	3) a line containing whitespace
98 		 */
99 		if (value) {
100 			status = item_cb(context, key, value);
101 			if (QDF_IS_STATUS_ERROR(status))
102 				goto free_fbuf;
103 			else
104 				ini_read_count++;
105 		} else if (key[0] == '[') {
106 			qdf_size_t len = qdf_str_len(key);
107 
108 			if (key[len - 1] != ']') {
109 				qdf_err("Invalid *.ini syntax '%s'", key);
110 			} else {
111 				key[len - 1] = '\0';
112 				status = section_cb(context, key + 1);
113 				if (QDF_IS_STATUS_ERROR(status))
114 					goto free_fbuf;
115 			}
116 		} else if (key[0] != '\0') {
117 			qdf_err("Invalid *.ini syntax '%s'", key);
118 		}
119 
120 		/* skip remaining EoL characters */
121 		while (*cursor == '\n' || *cursor == '\r')
122 			cursor++;
123 	}
124 
125 	qdf_debug("INI values read: %d", ini_read_count);
126 	if (ini_read_count != 0)
127 		status = QDF_STATUS_SUCCESS;
128 	else
129 		status = QDF_STATUS_E_FAILURE;
130 
131 free_fbuf:
132 	qdf_file_buf_free(fbuf);
133 
134 	return status;
135 }
136 qdf_export_symbol(qdf_ini_parse);
137 
138