Commit e9a20472 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Before reference counting, no memory leaks

parent 99355b76
......@@ -47,7 +47,4 @@ clean:
build/libmoberg.so: build/lib/moberg_config.o
build/libmoberg.so: build/lib/moberg_device.o
build/libmoberg.so: build/lib/moberg_parser.o
build/lib/moberg_device.o: moberg_device.h
build/parse_config.o: moberg_parser.h
parse_config: build/moberg_driver.o
parse_config: build/parse_config.o
build/lib/%.o: %.h
......@@ -43,7 +43,7 @@ static void parse_config_at(
buf[statbuf.st_size] = 0;
}
printf("Parsing... %s %d %d\n", pathname, dirfd, fd);
struct moberg_config *config = moberg_config_parse(buf);
struct moberg_config *config = moberg_parse(buf);
printf("-> %p\n", config);
if (config) {
if (! moberg->config) {
......@@ -88,39 +88,49 @@ static void parse_config_dir_at(
}
static int install_config(struct moberg *moberg)
{
return 1;
}
struct moberg *moberg_new(
struct moberg_config *config)
{
struct moberg *result = malloc(sizeof(*result));
if (! result) {
fprintf(stderr, "Failed to allocate moberg struct\n");
goto err;
}
if (config) {
result->config = config;
} else {
result->config = NULL;
if (! config) {
/* Parse default configuration(s) */
const char * const *config_paths = xdgSearchableConfigDirectories(NULL);
const char * const *path;
for (path = config_paths ; *path ; path++) {
int dirfd1 = open(*path, O_DIRECTORY);
if (dirfd >= 0) {
parse_config_at(result, dirfd1, "moberg.conf");
int dirfd2 = openat(dirfd1, "moberg.d", O_DIRECTORY);
if (dirfd2 >= 0) {
parse_config_dir_at(result, dirfd2);
parse_config_dir_at(result, dirfd2);
close(dirfd2);
}
close(dirfd1);
/* Parse default configuration(s) */
const char * const *config_paths = xdgSearchableConfigDirectories(NULL);
const char * const *path;
for (path = config_paths ; *path ; path++) {
int dirfd1 = open(*path, O_DIRECTORY);
if (dirfd >= 0) {
parse_config_at(result, dirfd1, "moberg.conf");
int dirfd2 = openat(dirfd1, "moberg.d", O_DIRECTORY);
if (dirfd2 >= 0) {
parse_config_dir_at(result, dirfd2);
parse_config_dir_at(result, dirfd2);
close(dirfd2);
}
free((char*)*path);
close(dirfd1);
}
free((const char **)config_paths);
/* Read environment default */
/* Parse environment overrides */
free((char*)*path);
}
free((const char **)config_paths);
/* Read environment default */
/* Parse environment overrides */
}
install_config(result);
err:
return result;
}
......
......@@ -37,13 +37,53 @@ struct moberg_config
struct moberg_device_analog_in *channel;
} *value;
} analog_in;
struct {
int capacity;
struct analog_out_entry {
struct moberg_device* device;
struct moberg_device_analog_out *channel;
} *value;
} analog_out;
struct {
int capacity;
struct digital_in_entry {
struct moberg_device* device;
struct moberg_device_digital_in *channel;
} *value;
} digital_in;
struct {
int capacity;
struct digital_out_entry {
struct moberg_device* device;
struct moberg_device_digital_out *channel;
} *value;
} digital_out;
struct {
int capacity;
struct encoder_in_entry {
struct moberg_device* device;
struct moberg_device_encoder_in *channel;
} *value;
} encoder_in;
};
struct moberg_config *moberg_config_new()
{
struct moberg_config *result = malloc(sizeof *result);
result->device = NULL;
if (result) {
result->device = NULL;
result->analog_in.capacity = 0;
result->analog_in.value = NULL;
result->analog_out.capacity = 0;
result->analog_out.value = NULL;
result->digital_in.capacity = 0;
result->digital_in.value = NULL;
result->digital_out.capacity = 0;
result->digital_out.value = NULL;
result->encoder_in.capacity = 0;
result->encoder_in.value = NULL;
}
return result;
}
......@@ -57,6 +97,11 @@ void moberg_config_free(struct moberg_config *config)
moberg_device_free(tmp->device);
free(tmp);
}
free(config->analog_in.value);
free(config->analog_out.value);
free(config->digital_in.value);
free(config->digital_out.value);
free(config->encoder_in.value);
free(config);
}
......@@ -97,3 +142,51 @@ err:
return 0;
}
int moberg_config_add_analog_out(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_analog_out *channel)
{
struct analog_out_entry e = { device, channel };
LIST_SET(config->analog_out, index, e, goto err);
return 1;
err:
return 0;
}
int moberg_config_add_digital_in(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_digital_in *channel)
{
struct digital_in_entry e = { device, channel };
LIST_SET(config->digital_in, index, e, goto err);
return 1;
err:
return 0;
}
int moberg_config_add_digital_out(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_digital_out *channel)
{
struct digital_out_entry e = { device, channel };
LIST_SET(config->digital_out, index, e, goto err);
return 1;
err:
return 0;
}
int moberg_config_add_encoder_in(struct moberg_config *config,
int index,
struct moberg_device* device,
struct moberg_device_encoder_in *channel)
{
struct encoder_in_entry e = { device, channel };
LIST_SET(config->encoder_in, index, e, goto err);
return 1;
err:
return 0;
}
......@@ -8,8 +8,25 @@
struct moberg_device {
void *driver_handle;
struct moberg_device_driver driver;
struct moberg_device_config *config;
struct moberg_device_map_range *range;
struct moberg_device_config *device_config;
struct channel_list {
struct channel_list *next;
enum moberg_channel_kind kind;
int index;
union channel {
struct moberg_device_analog_in *analog_in;
struct moberg_device_analog_out *analog_out;
struct moberg_device_digital_in *digital_in;
struct moberg_device_digital_out *digital_out;
struct moberg_device_encoder_in *encoder_in;
} u;
} *channel_head, **channel_tail;
struct map_range {
struct moberg_config *config;
enum moberg_channel_kind kind;
int min;
int max;
} *range;
};
struct moberg_device *moberg_device_new(const char *driver)
......@@ -37,7 +54,11 @@ struct moberg_device *moberg_device_new(const char *driver)
}
result->driver_handle = handle;
result->driver = *device_driver;
result->config = NULL;
result->device_config = NULL;
result->channel_head = NULL;
result->channel_tail = &result->channel_head;
result->range = NULL;
goto free_name;
dlclose_driver:
......@@ -50,8 +71,16 @@ out:
void moberg_device_free(struct moberg_device *device)
{
device->driver.config_free(device->config);
free(device->config);
struct channel_list *channel = device->channel_head;
while (channel) {
struct channel_list *next;
next = channel->next;
free(channel);
channel = next;
}
device->driver.config_free(device->device_config);
free(device->device_config);
dlclose(device->driver_handle);
free(device);
}
......@@ -64,90 +93,125 @@ int moberg_device_parse_config(struct moberg_device *device,
int moberg_device_set_config(struct moberg_device *device,
struct moberg_device_config *config)
{
if (device->config) {
device->driver.config_free(device->config);
free(device->config);
if (device->device_config) {
device->driver.config_free(device->device_config);
free(device->device_config);
}
device->config = config;
device->device_config = config;
return 1;
}
int moberg_device_parse_map(struct moberg_device* device,
struct moberg_config *config,
struct moberg_parser_context *context,
struct moberg_device_map_range range)
enum moberg_channel_kind kind,
int min,
int max)
{
int result;
struct moberg_device_map_range r = range;
struct map_range r = {
.config=config,
.kind=kind,
.min=min,
.max=max
};
device->range = &r;
result = device->driver.parse_map(device, context, range.kind);
result = device->driver.parse_map(device, context, kind);
device->range = NULL;
printf("RRR %d %d\n", r.min, r.max);
return result;
}
static int add_channel(struct moberg_device* device,
enum moberg_channel_kind kind,
int index,
union channel channel)
{
struct channel_list *element = malloc(sizeof(*element));
if (! element) { goto err; }
element->next = NULL;
element->kind = kind;
element->index = index;
element->u = channel;
*device->channel_tail = element;
device->channel_tail = &element->next;
return 1;
err:
return 0;
}
int moberg_device_add_analog_in(struct moberg_device* device,
struct moberg_device_analog_in *channel)
{
if (device->range->kind == map_analog_in &&
int result = 0;
if (device->range->kind == chan_ANALOGIN &&
device->range->min <= device->range->max) {
printf("Mapping %d\n", device->range->min);
// moberg_config_add_analog_in()
result = add_channel(device, device->range->kind, device->range->min,
(union channel) { .analog_in=channel });
device->range->min++;
return 1;
} else {
return 0;
}
return result;
}
int moberg_device_add_analog_out(struct moberg_device* device,
struct moberg_device_analog_out *channel)
{
if (device->range->kind == map_analog_out &&
int result = 0;
if (device->range->kind == chan_ANALOGOUT &&
device->range->min <= device->range->max) {
printf("Mapping %d\n", device->range->min);
result = add_channel(device, device->range->kind, device->range->min,
(union channel) { .analog_out=channel });
device->range->min++;
return 1;
} else {
return 0;
}
return result;
}
int moberg_device_add_digital_in(struct moberg_device* device,
struct moberg_device_digital_in *channel)
struct moberg_device_digital_in *channel)
{
if (device->range->kind == map_digital_in &&
int result = 0;
if (device->range->kind == chan_DIGITALIN &&
device->range->min <= device->range->max) {
printf("Mapping %d\n", device->range->min);
result = add_channel(device, device->range->kind, device->range->min,
(union channel) { .digital_in=channel });
device->range->min++;
return 1;
} else {
return 0;
}
return result;
}
int moberg_device_add_digital_out(struct moberg_device* device,
struct moberg_device_digital_out *channel)
struct moberg_device_digital_out *channel)
{
if (device->range->kind == map_digital_out &&
int result = 0;
if (device->range->kind == chan_DIGITALOUT &&
device->range->min <= device->range->max) {
printf("Mapping %d\n", device->range->min);
result = add_channel(device, device->range->kind, device->range->min,
(union channel) { .digital_out=channel });
device->range->min++;
return 1;
} else {
return 0;
}
return result;
}
int moberg_device_add_encoder_in(struct moberg_device* device,
struct moberg_device_encoder_in *channel)
struct moberg_device_encoder_in *channel)
{
if (device->range->kind == map_encoder_in &&
int result = 0;
if (device->range->kind == chan_ENCODERIN &&
device->range->min <= device->range->max) {
printf("Mapping %d\n", device->range->min);
result = add_channel(device, device->range->kind, device->range->min,
(union channel) { .encoder_in=channel });
device->range->min++;
return 1;
} else {
return 0;
}
return result;
}
......@@ -4,16 +4,12 @@
#include <moberg_config.h>
#include <moberg_parser.h>
struct moberg_device_map_range {
enum moberg_device_map_kind {
map_analog_in,
map_analog_out,
map_digital_in,
map_digital_out,
map_encoder_in
} kind;
int min;
int max;
enum moberg_channel_kind {
chan_ANALOGIN,
chan_ANALOGOUT,
chan_DIGITALIN,
chan_DIGITALOUT,
chan_ENCODERIN
};
struct moberg_device_analog_in {
......@@ -62,7 +58,7 @@ struct moberg_device_driver {
int (*parse_map)(
struct moberg_device* device,
struct moberg_parser_context *context,
enum moberg_device_map_kind kind);
enum moberg_channel_kind kind);
int (*config_free)(
struct moberg_device_config *config);
};
......@@ -80,8 +76,11 @@ int moberg_device_set_config(struct moberg_device* device,
struct moberg_device_config *config);
int moberg_device_parse_map(struct moberg_device* device,
struct moberg_config *config,
struct moberg_parser_context *context,
struct moberg_device_map_range range);
enum moberg_channel_kind kind,
int min,
int max);
int moberg_device_add_analog_in(struct moberg_device* device,
struct moberg_device_analog_in *channel);
......
......@@ -5,6 +5,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <moberg_config.h>
#include <moberg_parser.h>
#include <moberg_module.h>
#include <moberg_device.h>
......@@ -288,23 +289,24 @@ void moberg_parser_failed(
static int parse_map_range(context_t *c,
struct moberg_device_map_range *range)
int *min,
int *max)
{
token_t min, max;
token_t tok_min, tok_max;
if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; }
if (! acceptsym(c, tok_INTEGER, &min)) { goto syntax_err; }
if (! acceptsym(c, tok_INTEGER, &tok_min)) { goto syntax_err; }
if (acceptsym(c, tok_COLON, NULL)) {
if (! acceptsym(c, tok_INTEGER, &max)) { goto syntax_err; }
if (! acceptsym(c, tok_INTEGER, &tok_max)) { goto syntax_err; }
} else {
max = min;
tok_max = tok_min;
}
if (! acceptsym(c, tok_RBRACKET, NULL)) { goto syntax_err; }
if (! range) {
fprintf(stderr, "Range is NULL\n");
if (! min && max) {
fprintf(stderr, "Min or max is NULL\n");
goto err;
}
range->min = min.u.integer.value;
range->max = max.u.integer.value;
*min = tok_min.u.integer.value;
*max = tok_max.u.integer.value;
return 1;
syntax_err:
moberg_parser_failed(c, stderr);
......@@ -315,17 +317,20 @@ err:
static int parse_map(context_t *c,
struct moberg_device *device)
{
struct moberg_device_map_range range;
enum moberg_channel_kind kind;
int min, max;
if (acceptkeyword(c, "analog_in")) { range.kind = map_analog_in; }
else if (acceptkeyword(c, "analog_out")) { range.kind = map_analog_out; }
else if (acceptkeyword(c, "digital_in")) { range.kind = map_digital_in; }
else if (acceptkeyword(c, "digital_out")) { range.kind = map_digital_out; }
else if (acceptkeyword(c, "encoder_in")) { range.kind = map_encoder_in; }
if (acceptkeyword(c, "analog_in")) { kind = chan_ANALOGIN; }
else if (acceptkeyword(c, "analog_out")) { kind = chan_ANALOGOUT; }
else if (acceptkeyword(c, "digital_in")) { kind = chan_DIGITALIN; }
else if (acceptkeyword(c, "digital_out")) { kind = chan_DIGITALOUT; }
else if (acceptkeyword(c, "encoder_in")) { kind = chan_ENCODERIN; }
else { goto syntax_err; }
if (! parse_map_range(c, &range)) { goto syntax_err; }
if (! parse_map_range(c, &min, &max)) { goto syntax_err; }
if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; }
if (! moberg_device_parse_map(device, c, range)) { goto err; }
if (! moberg_device_parse_map(device, c->config, c, kind, min, max)) {
goto err;
}
if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; }
return 1;
syntax_err:
......@@ -341,11 +346,6 @@ static int parse_device(context_t *c,
for (;;) {
if (acceptkeyword(c, "config")) {
moberg_device_parse_config(device, c);
/*
void *config = driver->module.parse_config(c);
result->add_config(config);
free(config);
*/
} else if (acceptkeyword(c, "map")) {
if (! parse_map(c, device)) { goto err; }
} else if (acceptsym(c, tok_RBRACE, NULL)) {
......@@ -403,7 +403,7 @@ err:
return 0;
}
struct moberg_config *moberg_config_parse(const char *buf)
struct moberg_config *moberg_parse(const char *buf)
{
context_t context;
......
......@@ -5,6 +5,6 @@
struct moberg_parser_context;
struct moberg_config *moberg_config_parse(const char *buf);
struct moberg_config *moberg_parse(const char *buf);
#endif
......@@ -90,7 +90,7 @@ err:
static int parse_map(
struct moberg_device *device,
struct moberg_parser_context *c,
enum moberg_device_map_kind kind)
enum moberg_channel_kind kind)
{
token_t min, max;
......@@ -114,19 +114,19 @@ static int parse_map(
}
for (int i = min.u.integer.value ; i <= max.u.integer.value ; i++) {
switch (kind) {
case map_analog_in:
case chan_ANALOGIN:
moberg_device_add_analog_in(device, NULL);
break;
case map_analog_out:
case chan_ANALOGOUT:
moberg_device_add_analog_out(device, NULL);
break;
case map_digital_in:
case chan_DIGITALIN:
moberg_device_add_digital_in(device, NULL);
break;
case map_digital_out:
case chan_DIGITALOUT:
moberg_device_add_digital_out(device, NULL);
break;
case map_encoder_in:
case chan_ENCODERIN:
moberg_device_add_encoder_in(device, NULL);
break;
}
......
......@@ -69,16 +69,16 @@ err:
static int parse_map(
struct moberg_device *device,
struct moberg_parser_context *c,
enum moberg_device_map_kind ignore)
enum moberg_channel_kind ignore)
{
enum moberg_device_map_kind kind;
enum moberg_channel_kind kind;
token_t min, max;
if (acceptkeyword(c, "analog_in")) { kind = map_analog_in; }
else if (acceptkeyword(c, "analog_out")) { kind = map_analog_out; }
else if (acceptkeyword(c, "digital_in")) { kind = map_digital_in; }
else if (acceptkeyword(c, "digital_out")) { kind = map_digital_out; }
else if (acceptkeyword(c, "encoder_in")) { kind = map_encoder_in; }