2 * This file is part of the bayou project.
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
28 #define STATE_NONE 0x00
29 #define STATE_BAYOUCONFIG 0x01
30 #define STATE_GLOBAL 0x02
31 #define STATE_GLOBAL_TIMEOUT 0x03
32 #define STATE_PAYLOADS 0x04
33 #define STATE_PAYLOAD 0x05
34 #define STATE_PAYLOAD_TITLE 0x06
35 #define STATE_PAYLOAD_FILE 0x07
36 #define STATE_PAYLOAD_LARNAME 0x08
37 #define STATE_PAYLOAD_CHAIN 0x09
38 #define STATE_PAYLOAD_CHAIN_FILE 0x0A
39 #define STATE_PAYLOAD_CHAIN_LARNAME 0x0B
41 static struct userdata
{
42 struct config
*config
;
43 struct pentry
*payload
;
48 static char buffer
[8192];
55 {"BayouConfig", STATE_NONE
, STATE_BAYOUCONFIG
},
56 {"global", STATE_BAYOUCONFIG
, STATE_GLOBAL
},
57 {"timeout", STATE_GLOBAL
, STATE_GLOBAL_TIMEOUT
},
58 {"payloads", STATE_BAYOUCONFIG
, STATE_PAYLOADS
},
59 {"payload", STATE_PAYLOADS
, STATE_PAYLOAD
},
60 {"title", STATE_PAYLOAD
, STATE_PAYLOAD_TITLE
},
61 {"lar", STATE_PAYLOAD
, STATE_PAYLOAD_LARNAME
},
62 {"file", STATE_PAYLOAD
, STATE_PAYLOAD_FILE
},
63 {"chain", STATE_PAYLOAD
, STATE_PAYLOAD_CHAIN
},
64 {"file", STATE_PAYLOAD_CHAIN
, STATE_PAYLOAD_CHAIN_FILE
},
65 {"lar", STATE_PAYLOAD_CHAIN
, STATE_PAYLOAD_CHAIN_LARNAME
},
70 static char *strndup (const char *s
, size_t n
)
72 size_t len
= strlen (s
);
74 char *cpy
= malloc (len
+ 1);
83 static struct pentry
*newPayload(struct config
*config
)
85 struct pentry
**tmp
, *ret
;
87 tmp
= realloc(config
->entries
,
88 (config
->n_entries
+ 1) * sizeof(struct pentry
*));
93 config
->entries
= tmp
;
95 ret
= config
->entries
[config
->n_entries
] = calloc(sizeof(*ret
), 1);
100 /* Yes, I want this to be ++config->n_entries (the index is 1 based). */
101 ret
->index
= ++config
->n_entries
;
106 static void parseFlags(struct pentry
*entry
, const char *flags
)
108 char *p
= (char *)flags
;
117 if (!strcmp(p
, "default"))
118 entry
->flags
|= BPT_FLAG_DEFAULT
;
119 else if (!strcmp(p
, "nolist"))
120 entry
->flags
|= BPT_FLAG_NOSHOW
;
122 warn("W: Unknown payload flag %s\n", p
);
127 for (p
= n
; *p
&& isspace(*p
); p
++) ;
131 static struct pentry
*addPayload(struct config
*config
, const char **attr
)
133 struct pentry
*ret
= newPayload(config
);
137 die("E: Could not allocate memory for a new payload\n");
139 while (attr
[i
] != NULL
) {
140 if (!strcmp(attr
[i
], "type")) {
141 if (!strcmp(attr
[i
+ 1], "chain"))
142 ret
->type
= BPT_TYPE_CHAIN
;
143 else if (!strcmp(attr
[i
+ 1], "chooser"))
144 ret
->type
= BPT_TYPE_CHOOSER
;
146 die("E: Invalid payload type %s\n",
148 } else if (!strcmp(attr
[i
], "flags"))
149 parseFlags(ret
, attr
[i
+ 1]);
157 static struct pentry
*addChain(struct config
*config
, struct pentry
*parent
)
159 struct pentry
*ret
= newPayload(config
);
162 die("E: Could not allocate memory for a new payload\n");
164 ret
->parent
= parent
->index
;
165 ret
->type
= BPT_TYPE_SUBCHAIN
;
170 static void start(void *data
, const char *el
, const char **attr
)
173 struct userdata
*d
= (struct userdata
*)data
;
175 for (i
= 0; states
[i
].element
!= NULL
; i
++) {
176 if (d
->state
!= states
[i
].pstate
)
179 if (!strcmp(el
, states
[i
].element
)) {
180 d
->state
= states
[i
].state
;
185 if (states
[i
].element
== NULL
)
186 die("E: Unknown element %s\n", el
);
188 if (d
->state
== STATE_PAYLOAD
)
189 d
->payload
= addPayload(d
->config
, attr
);
191 if (d
->state
== STATE_PAYLOAD_CHAIN
)
192 d
->chain
= addChain(d
->config
, d
->payload
);
195 static void data(void *data
, const char *val
, int len
)
197 struct userdata
*d
= (struct userdata
*)data
;
201 case STATE_GLOBAL_TIMEOUT
:
202 d
->config
->timeout
= atoi(val
);
204 case STATE_PAYLOAD_TITLE
:
205 l
= sizeof(d
->payload
->title
) - 1 > len
?
206 len
: sizeof(d
->payload
->title
) - 1;
208 strncpy((char *)d
->payload
->title
, (char *)val
, l
);
209 d
->payload
->title
[l
] = '\0';
211 case STATE_PAYLOAD_FILE
:
212 d
->payload
->file
= strndup(val
, len
);
214 case STATE_PAYLOAD_LARNAME
:
215 d
->payload
->larname
= strndup(val
, len
);
217 case STATE_PAYLOAD_CHAIN_FILE
:
218 d
->chain
->file
= strndup(val
, len
);
220 case STATE_PAYLOAD_CHAIN_LARNAME
:
221 d
->chain
->larname
= strndup(val
, len
);
228 static void end(void *data
, const char *el
)
230 struct userdata
*d
= (struct userdata
*)data
;
233 if (d
->state
== STATE_PAYLOAD_CHAIN
)
236 if (d
->state
== STATE_PAYLOAD
)
239 for (i
= 0; states
[i
].element
!= NULL
; i
++) {
240 if (d
->state
!= states
[i
].state
)
243 if (!strcmp(el
, states
[i
].element
)) {
244 d
->state
= states
[i
].pstate
;
249 if (states
[i
].element
== NULL
)
250 die("E: Unable to find the reverse state for %s\n", el
);
253 void parseconfig(FILE *stream
, struct config
*config
)
255 XML_Parser p
= XML_ParserCreate(NULL
);
259 die("E: Could not create the parser\n");
261 XML_SetElementHandler(p
, start
, end
);
262 XML_SetCharacterDataHandler(p
, data
);
264 userdata
.config
= config
;
266 XML_SetUserData(p
, &userdata
);
269 int len
= fread(buffer
, 1, 8192, stream
);
274 die("E: Error reading the stream\n");
276 if (!XML_Parse(p
, buffer
, len
, eof
))
277 die("E: Error parsing the XML data\n");