a73b93157f
It encourages users from writing to the FSF without giving an address. Linux also prefers to drop that and their checkpatch.pl (that we imported) looks out for that. This is the result of util/scripts/no-fsf-addresses.sh with no further editing. Change-Id: Ie96faea295fe001911d77dbc51e9a6789558fbd6 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Reviewed-on: http://review.coreboot.org/11888 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
275 lines
6.2 KiB
C
275 lines
6.2 KiB
C
/*
|
|
* This file is part of the bayou project.
|
|
*
|
|
* Copyright (C) 2008 Advanced Micro Devices, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <expat.h>
|
|
#include <ctype.h>
|
|
#include "pbuilder.h"
|
|
|
|
#define STATE_NONE 0x00
|
|
#define STATE_BAYOUCONFIG 0x01
|
|
#define STATE_GLOBAL 0x02
|
|
#define STATE_GLOBAL_TIMEOUT 0x03
|
|
#define STATE_PAYLOADS 0x04
|
|
#define STATE_PAYLOAD 0x05
|
|
#define STATE_PAYLOAD_TITLE 0x06
|
|
#define STATE_PAYLOAD_FILE 0x07
|
|
#define STATE_PAYLOAD_LARNAME 0x08
|
|
#define STATE_PAYLOAD_CHAIN 0x09
|
|
#define STATE_PAYLOAD_CHAIN_FILE 0x0A
|
|
#define STATE_PAYLOAD_CHAIN_LARNAME 0x0B
|
|
|
|
static struct userdata {
|
|
struct config *config;
|
|
struct pentry *payload;
|
|
struct pentry *chain;
|
|
int state;
|
|
} userdata;
|
|
|
|
static char buffer[8192];
|
|
|
|
static struct {
|
|
char *element;
|
|
int pstate;
|
|
int state;
|
|
} states[] = {
|
|
{"BayouConfig", STATE_NONE, STATE_BAYOUCONFIG},
|
|
{"global", STATE_BAYOUCONFIG, STATE_GLOBAL},
|
|
{"timeout", STATE_GLOBAL, STATE_GLOBAL_TIMEOUT},
|
|
{"payloads", STATE_BAYOUCONFIG, STATE_PAYLOADS},
|
|
{"payload", STATE_PAYLOADS, STATE_PAYLOAD},
|
|
{"title", STATE_PAYLOAD, STATE_PAYLOAD_TITLE},
|
|
{"lar", STATE_PAYLOAD, STATE_PAYLOAD_LARNAME},
|
|
{"file", STATE_PAYLOAD, STATE_PAYLOAD_FILE},
|
|
{"chain", STATE_PAYLOAD, STATE_PAYLOAD_CHAIN},
|
|
{"file", STATE_PAYLOAD_CHAIN, STATE_PAYLOAD_CHAIN_FILE},
|
|
{"lar", STATE_PAYLOAD_CHAIN, STATE_PAYLOAD_CHAIN_LARNAME},
|
|
{NULL},
|
|
};
|
|
|
|
#ifndef __LINUX__
|
|
static char *strndup (const char *s, size_t n)
|
|
{
|
|
size_t len = strlen (s);
|
|
len = (len<n)?len:n;
|
|
char *cpy = malloc (len + 1);
|
|
if (cpy == NULL)
|
|
return NULL;
|
|
cpy[len] = '\0';
|
|
memcpy (cpy, s, len);
|
|
return cpy;
|
|
}
|
|
#endif
|
|
|
|
static struct pentry *newPayload(struct config *config)
|
|
{
|
|
struct pentry **tmp, *ret;
|
|
|
|
tmp = realloc(config->entries,
|
|
(config->n_entries + 1) * sizeof(struct pentry *));
|
|
|
|
if (tmp == NULL)
|
|
return NULL;
|
|
|
|
config->entries = tmp;
|
|
|
|
ret = config->entries[config->n_entries] = calloc(sizeof(*ret), 1);
|
|
|
|
if (ret == NULL)
|
|
return NULL;
|
|
|
|
/* Yes, I want this to be ++config->n_entries (the index is 1 based). */
|
|
ret->index = ++config->n_entries;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void parseFlags(struct pentry *entry, const char *flags)
|
|
{
|
|
char *p = (char *)flags;
|
|
char *n;
|
|
|
|
while (*p) {
|
|
n = strchr(p, ',');
|
|
|
|
if (n)
|
|
*(n++) = 0;
|
|
|
|
if (!strcmp(p, "default"))
|
|
entry->flags |= BPT_FLAG_DEFAULT;
|
|
else if (!strcmp(p, "nolist"))
|
|
entry->flags |= BPT_FLAG_NOSHOW;
|
|
else
|
|
warn("W: Unknown payload flag %s\n", p);
|
|
|
|
if (!n)
|
|
break;
|
|
|
|
for (p = n; *p && isspace(*p); p++) ;
|
|
}
|
|
}
|
|
|
|
static struct pentry *addPayload(struct config *config, const char **attr)
|
|
{
|
|
struct pentry *ret = newPayload(config);
|
|
int i = 0;
|
|
|
|
if (ret == NULL)
|
|
die("E: Could not allocate memory for a new payload\n");
|
|
|
|
while (attr[i] != NULL) {
|
|
if (!strcmp(attr[i], "type")) {
|
|
if (!strcmp(attr[i + 1], "chain"))
|
|
ret->type = BPT_TYPE_CHAIN;
|
|
else if (!strcmp(attr[i + 1], "chooser"))
|
|
ret->type = BPT_TYPE_CHOOSER;
|
|
else
|
|
die("E: Invalid payload type %s\n",
|
|
attr[i + 1]);
|
|
} else if (!strcmp(attr[i], "flags"))
|
|
parseFlags(ret, attr[i + 1]);
|
|
|
|
i += 2;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct pentry *addChain(struct config *config, struct pentry *parent)
|
|
{
|
|
struct pentry *ret = newPayload(config);
|
|
|
|
if (ret == NULL)
|
|
die("E: Could not allocate memory for a new payload\n");
|
|
|
|
ret->parent = parent->index;
|
|
ret->type = BPT_TYPE_SUBCHAIN;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void start(void *data, const char *el, const char **attr)
|
|
{
|
|
int i;
|
|
struct userdata *d = (struct userdata *)data;
|
|
|
|
for (i = 0; states[i].element != NULL; i++) {
|
|
if (d->state != states[i].pstate)
|
|
continue;
|
|
|
|
if (!strcmp(el, states[i].element)) {
|
|
d->state = states[i].state;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (states[i].element == NULL)
|
|
die("E: Unknown element %s\n", el);
|
|
|
|
if (d->state == STATE_PAYLOAD)
|
|
d->payload = addPayload(d->config, attr);
|
|
|
|
if (d->state == STATE_PAYLOAD_CHAIN)
|
|
d->chain = addChain(d->config, d->payload);
|
|
}
|
|
|
|
static void data(void *data, const char *val, int len)
|
|
{
|
|
struct userdata *d = (struct userdata *)data;
|
|
int l;
|
|
|
|
switch (d->state) {
|
|
case STATE_GLOBAL_TIMEOUT:
|
|
d->config->timeout = atoi(val);
|
|
break;
|
|
case STATE_PAYLOAD_TITLE:
|
|
l = sizeof(d->payload->title) - 1 > len ?
|
|
len : sizeof(d->payload->title) - 1;
|
|
|
|
strncpy((char *)d->payload->title, (char *)val, l);
|
|
d->payload->title[l] = '\0';
|
|
break;
|
|
case STATE_PAYLOAD_FILE:
|
|
d->payload->file = strndup(val, len);
|
|
break;
|
|
case STATE_PAYLOAD_LARNAME:
|
|
d->payload->larname = strndup(val, len);
|
|
break;
|
|
case STATE_PAYLOAD_CHAIN_FILE:
|
|
d->chain->file = strndup(val, len);
|
|
break;
|
|
case STATE_PAYLOAD_CHAIN_LARNAME:
|
|
d->chain->larname = strndup(val, len);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void end(void *data, const char *el)
|
|
{
|
|
struct userdata *d = (struct userdata *)data;
|
|
int i;
|
|
|
|
if (d->state == STATE_PAYLOAD_CHAIN)
|
|
d->chain = NULL;
|
|
|
|
if (d->state == STATE_PAYLOAD)
|
|
d->payload = NULL;
|
|
|
|
for (i = 0; states[i].element != NULL; i++) {
|
|
if (d->state != states[i].state)
|
|
continue;
|
|
|
|
if (!strcmp(el, states[i].element)) {
|
|
d->state = states[i].pstate;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (states[i].element == NULL)
|
|
die("E: Unable to find the reverse state for %s\n", el);
|
|
}
|
|
|
|
void parseconfig(FILE *stream, struct config *config)
|
|
{
|
|
XML_Parser p = XML_ParserCreate(NULL);
|
|
int eof = 0;
|
|
|
|
if (p == NULL)
|
|
die("E: Could not create the parser\n");
|
|
|
|
XML_SetElementHandler(p, start, end);
|
|
XML_SetCharacterDataHandler(p, data);
|
|
|
|
userdata.config = config;
|
|
|
|
XML_SetUserData(p, &userdata);
|
|
|
|
while (!eof) {
|
|
int len = fread(buffer, 1, 8192, stream);
|
|
|
|
eof = feof(stream);
|
|
|
|
if (ferror(stream))
|
|
die("E: Error reading the stream\n");
|
|
|
|
if (!XML_Parse(p, buffer, len, eof))
|
|
die("E: Error parsing the XML data\n");
|
|
}
|
|
}
|