xref: /wlan-dirver/qca-wifi-host-cmn/qdf/src/qdf_parse.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
1 /*
2  * Copyright (c) 2018 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 
34 	status = qdf_file_read(ini_path, &fbuf);
35 	if (QDF_IS_STATUS_ERROR(status)) {
36 		qdf_err("Failed to read *.ini file @ %s", ini_path);
37 		return status;
38 	}
39 
40 	/* foreach line */
41 	cursor = fbuf;
42 	while (*cursor != '\0') {
43 		char *key = cursor;
44 		char *value = NULL;
45 		bool comment = false;
46 		bool eol = false;
47 
48 		/*
49 		 * Look for the end of the line, while noting any
50 		 * value ('=') or comment ('#') indicators
51 		 */
52 		while (!eol) {
53 			switch (*cursor) {
54 			case '\r':
55 			case '\n':
56 				*cursor = '\0';
57 				cursor++;
58 				/* fall through */
59 			case '\0':
60 				eol = true;
61 				break;
62 
63 			case '=':
64 				/*
65 				 * The first '=' is the value indicator.
66 				 * Subsequent '=' are valid value characters.
67 				 */
68 				if (!value && !comment) {
69 					value = cursor + 1;
70 					*cursor = '\0';
71 				}
72 
73 				cursor++;
74 				break;
75 
76 			case '#':
77 				/*
78 				 * We don't process comments, so we can null-
79 				 * terminate unconditionally here (unlike '=').
80 				 */
81 				comment = true;
82 				*cursor = '\0';
83 				/* fall through */
84 			default:
85 				cursor++;
86 				break;
87 			}
88 		}
89 
90 		key = qdf_str_trim(key);
91 
92 		/*
93 		 * Ignoring comments, a valid ini line contains one of:
94 		 *	1) some 'key=value' config item
95 		 *	2) section header
96 		 *	3) a line containing whitespace
97 		 */
98 		if (value) {
99 			status = item_cb(context, key, value);
100 			if (QDF_IS_STATUS_ERROR(status))
101 				goto free_fbuf;
102 		} else if (key[0] == '[') {
103 			qdf_size_t len = qdf_str_len(key);
104 
105 			if (key[len - 1] != ']') {
106 				qdf_err("Invalid *.ini syntax '%s'", key);
107 			} else {
108 				key[len - 1] = '\0';
109 				status = section_cb(context, key + 1);
110 				if (QDF_IS_STATUS_ERROR(status))
111 					goto free_fbuf;
112 			}
113 		} else if (key[0] != '\0') {
114 			qdf_err("Invalid *.ini syntax '%s'", key);
115 		}
116 
117 		/* skip remaining EoL characters */
118 		while (*cursor == '\n' || *cursor == '\r')
119 			cursor++;
120 	}
121 
122 	status = QDF_STATUS_SUCCESS;
123 
124 free_fbuf:
125 	qdf_file_buf_free(fbuf);
126 
127 	return status;
128 }
129 qdf_export_symbol(qdf_ini_parse);
130 
131