]> rtime.felk.cvut.cz Git - linux-lin.git/blob - lin_config/src/linc_parse_xml.c
lin_config: Use strtol() instead of atoi() + errorhandling
[linux-lin.git] / lin_config / src / linc_parse_xml.c
1 #include <libxml/parser.h>
2 #include <assert.h>
3 #include <string.h>
4 #include <errno.h>
5 #include "lin_config.h"
6
7 /**
8 * @val -- ptr to int where the int value will be saved
9 * @cur -- xmlNodePtr
10 * @str -- Property name (string)
11 */
12 static inline int linc_xml_get_prop_int(int *val, xmlNodePtr cur, const xmlChar* str)
13 {
14         xmlChar *attr;
15         char *endptr;
16
17         attr = xmlGetProp(cur, str);
18         if (!attr)
19                 assert(0);
20
21         errno = 0;
22         *val = strtol((const char *)attr, &endptr, 10);
23         if ((char *)attr == endptr)
24                 return -1;
25         if (errno != 0) {
26                 perror("strtol()");
27                 return -1;
28         }
29
30         xmlFree(attr);
31         return 0;
32 }
33
34 /**
35 * @val -- ptr to int where the int value will be saved
36 * @doc -- xmlDocPtr
37 * @cur -- xmlNodePtr
38 */
39 static inline int linc_xml_get_element_int(int *val, xmlDocPtr doc, xmlNodePtr cur)
40 {
41         xmlChar *key;
42         char *endptr;
43
44         key = xmlNodeListGetString(doc, cur->children, 1);
45         if (!key)
46                 assert(0);
47
48         errno = 0;
49         *val = strtol((const char *)key, &endptr, 10);
50         if ((char *)key == endptr)
51                 return -1;
52         if (errno != 0) {
53                 perror("strtol()");
54                 return -1;
55         }
56         xmlFree(key);
57
58         return 0;
59 }
60
61 int linc_parse_scheduler_entries(struct linc_lin_state *linc_lin_state, xmlDocPtr doc, xmlNodePtr cur)
62 {
63         cur = cur->children;
64         while (cur) {
65                 if (!xmlStrcmp(cur->name, (const xmlChar *)"Entry")) {
66                         int ret;
67                         int linid;
68                         int interval;
69
70                         ret = linc_xml_get_element_int(&linid, doc, cur);
71                         if (ret < 0)
72                                 return ret;
73
74                         ret = linc_xml_get_prop_int(&interval, cur, (const xmlChar *)"Time");
75                         if (ret < 0)
76                                 return ret;
77
78                         linc_lin_state->scheduler_entry[linc_lin_state->scheduler_entries_cnt].lin_id = linid;
79                         linc_lin_state->scheduler_entry[linc_lin_state->scheduler_entries_cnt].interval_ms = interval;
80                         linc_lin_state->scheduler_entries_cnt++;
81
82                         //printf("Time = %d Lin ID = %d Entry no. = %d\n",
83                         //      interval, linid, linc_lin_state->scheduler_entries_cnt-1);
84                 }
85                 cur = cur->next;
86         }
87         return 0;
88 }
89
90 int linc_parse_frame_configuration(struct linc_lin_state *linc_lin_state, xmlDocPtr doc, xmlNodePtr cur)
91 {
92         xmlNodePtr tmp_node;
93         int val;
94
95         cur = cur->children;
96         while (cur) {
97                 if (!xmlStrcmp(cur->name, (const xmlChar *)"Frame")) {
98                         tmp_node = cur->children;
99                         /* We are able to write into the main Configuration array after
100                         parsing of all necessary elements (especially LIN ID) -- store
101                         parsed elements in this temporary entry -- copy the entry afterwards */
102                         struct linc_frame_entry tmp_fr_entry;
103                         int linid = -1;
104                         int ret;
105
106                         while (tmp_node) {
107                                 if (!xmlStrcmp(tmp_node->name, (const xmlChar *)"ID")) {
108                                         ret = linc_xml_get_element_int(&linid, doc, tmp_node);
109                                         //printf("ID = %d\n", linid);
110                                         if (ret < 0)
111                                                 return ret;
112                                 }
113                                 if (!xmlStrcmp(tmp_node->name, (const xmlChar *)"Length")) {
114                                         ret = linc_xml_get_element_int(&val, doc, tmp_node);
115                                         if (ret < 0)
116                                                 return ret;
117
118                                         tmp_fr_entry.data_len = val;
119                                         //printf("Length = %d\n", val);
120                                 }
121                                 if (!xmlStrcmp(tmp_node->name, (const xmlChar *)"Active")) {
122                                         ret = linc_xml_get_element_int(&val, doc, tmp_node);
123                                         if (ret < 0)
124                                                 return ret;
125
126                                         tmp_fr_entry.status = val;
127                                         //printf("Active = %d\n", val);
128                                 }
129                                 if (!xmlStrcmp(tmp_node->name, (const xmlChar *)"Data")) {
130                                         int indx = 0;
131                                         xmlNodePtr tmp_node2;
132                                         tmp_node2 = tmp_node->children;
133                                         while (tmp_node2) {
134                                                 if (!xmlStrcmp(tmp_node2->name, (const xmlChar *)"Byte")) {
135                                                         // Byte indexing in XML file is wrong
136                                                         //ret = linc_xml_get_prop_int(&index, tmp_node2,
137                                                         //      (const xmlChar *)"Index");
138                                                         ret = linc_xml_get_element_int(&val, doc, tmp_node2);
139                                                         if (ret < 0)
140                                                                 return ret;
141
142                                                         //printf("Data = %d\n", val);
143                                                         snprintf((char *)&tmp_fr_entry.data[indx], 1, "%i", val);
144                                                         indx++;
145                                                 }
146                                                 tmp_node2 = tmp_node2->next;
147                                         }
148                                 }
149                                 tmp_node = tmp_node->next;
150                         }
151
152                         if (linid >= 0 && linid <= MAX_LIN_ID) {
153                                 memcpy(&linc_lin_state->frame_entry[linid], &tmp_fr_entry,
154                                         sizeof(struct linc_frame_entry));
155                         }
156                 }
157                 cur = cur->next;
158         }
159
160         return 0;
161 }
162
163 int linc_parse_configuration(char *filename, struct linc_lin_state *linc_lin_state)
164 {
165         int val;
166         int ret;
167         xmlDocPtr doc;
168         xmlNodePtr cur_node;
169
170         if (!filename)
171                 filename = PCL_DEFAULT_CONFIG;
172
173         xmlKeepBlanksDefault(1);
174         doc = xmlParseFile(filename);
175         if (doc == NULL)
176                 return -1;
177
178         cur_node = xmlDocGetRootElement(doc);
179         if (cur_node == NULL) {
180                 fprintf(stderr, "Configuration file %s is empty\n", filename);
181                 xmlFreeDoc(doc);
182                 return -1;
183         }
184
185         /* Check for Root element */
186         if (xmlStrcmp(cur_node->name, (const xmlChar *)"PCLIN_PROFILE"))
187                 goto exit_failure;
188
189         /* Check for LIN element */
190         cur_node = cur_node->children;
191         while (cur_node) {
192                 if (!xmlStrcmp(cur_node->name, (const xmlChar *)"LIN"))
193                         break;
194
195                 cur_node = cur_node->next;
196         }
197
198         if (!cur_node)
199                 goto exit_failure;
200
201         /* Process LIN configuration */
202         cur_node = cur_node->children;
203         while (cur_node) {
204                 if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Active")) {
205                         ret = linc_xml_get_element_int(&val, doc, cur_node);
206                         if (ret < 0)
207                                 goto exit_failure;
208
209                         linc_lin_state->is_active = val;
210                 }
211                 if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Baudrate")) {
212                         ret = linc_xml_get_element_int(&val, doc, cur_node);
213                         if (ret < 0)
214                                 goto exit_failure;
215
216                         linc_lin_state->baudrate = val;
217                 }
218                 if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Master_Status")) {
219                         ret = linc_xml_get_element_int(&val, doc, cur_node);
220                         if (ret < 0)
221                                 goto exit_failure;
222
223                         linc_lin_state->master_status = val;
224                 }
225                 if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Bus_Termination")) {
226                         ret = linc_xml_get_element_int(&val, doc, cur_node);
227                         if (ret < 0)
228                                 goto exit_failure;
229
230                         linc_lin_state->bus_termination = val;
231                 }
232                 if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Scheduler_Entries")) {
233                         ret = linc_parse_scheduler_entries(linc_lin_state, doc, cur_node);
234                         if (ret < 0)
235                                 goto exit_failure;
236                 }
237                 if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Frame_Configuration")) {
238                         ret = linc_parse_frame_configuration(linc_lin_state, doc, cur_node);
239                         if (ret < 0)
240                                 goto exit_failure;
241                 }
242
243                 cur_node = cur_node->next;
244         }
245
246         xmlFreeDoc(doc);
247         return 0;
248
249 exit_failure:
250         fprintf(stderr, "Invalid configuration file\n");
251         xmlFreeDoc(doc);
252         return -1;
253 }
254