view ffstools/newcomp/compile-fc-chg.c @ 320:7572c35a768a

compile-fc-chg tool written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 17 Dec 2017 02:25:05 +0000
parents
children 0937521ec2f4
line wrap: on
line source

/*
 * This utility compiles a FreeCalypso battery charging configuration file
 * from ASCII source into the binary form suitable for uploading into
 * /etc/charging on a FreeCalypso device.
 */

#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include "../../rvinterf/include/exitcodes.h"

char *infname;
FILE *inf;
char linebuf[256];
int lineno;

struct setting {
	char		*kw;
	int		allow_always;
	int		allow_never;
	int		mandatory;
	unsigned	default_value;
	unsigned	set_value;
	int		is_set;
} settings[] = {
	{"start-delay",       0, 0, 0, 0,      0, 0},
	{"start-threshold",   1, 1, 1, 0,      0, 0},
	{"restart-threshold", 0, 1, 1, 0,      0, 0},
	{"charge-to-voltage", 0, 0, 1, 0,      0, 0},
	{"overvoltage",       0, 0, 0, 0xFFFF, 0, 0},
	{"ci-current",        0, 0, 1, 0,      0, 0},
	{"end-current",       0, 0, 1, 0,      0, 0},
	{"i2v-offset",        0, 0, 0, 0,      0, 0},
	{0,                   0, 0, 0, 0,      0, 0}
};

static void
do_setting(tp, arg)
	struct setting *tp;
	char *arg;
{
	char *endp;

	if (tp->allow_always && !strcmp(arg, "always")) {
		tp->set_value = 0xFFFF;
		return;
	}
	if (tp->allow_never && !strcmp(arg, "never")) {
		tp->set_value = 0;
		return;
	}
	tp->set_value = strtoul(arg, &endp, 0);
	if (*endp || tp->set_value > 0xFFFF) {
		fprintf(stderr, "%s line %d: invalid argument to %s\n",
			infname, lineno, tp->kw);
		exit(ERROR_USAGE);
	}
}

process_line()
{
	char *cp, *kw, *arg;
	struct setting *tp;

	for (cp = linebuf; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#')
		return(0);
	kw = cp;
	while (*cp && !isspace(*cp))
		cp++;
	if (!*cp) {
inv:		fprintf(stderr, "%s line %d: invalid syntax\n", infname,
			lineno);
		exit(ERROR_USAGE);
	}
	*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp == '\0' || *cp == '#')
		goto inv;
	arg = cp;
	while (*cp && !isspace(*cp))
		cp++;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp != '\0' && *cp != '#')
		goto inv;
	for (tp = settings; tp->kw; tp++)
		if (!strcmp(tp->kw, kw))
			break;
	if (!tp->kw) {
		fprintf(stderr, "%s line %d: setting \"%s\" not known\n",
			infname, lineno, kw);
		exit(ERROR_USAGE);
	}
	if (tp->is_set) {
		fprintf(stderr, "%s line %d: %s set more than once\n", infname,
			lineno, kw);
		exit(ERROR_USAGE);
	}
	do_setting(tp, arg);
	tp->is_set = 1;
	return(1);
}

set_defaults()
{
	struct setting *tp;

	for (tp = settings; tp->kw; tp++) {
		if (tp->is_set)
			continue;
		if (tp->mandatory) {
			fprintf(stderr,
				"error: required setting %s is not set\n",
				tp->kw);
			exit(ERROR_USAGE);
		}
		tp->set_value = tp->default_value;
	}
}

write_output(filename)
	char *filename;
{
	FILE *of;
	struct setting *tp;

	of = fopen(filename, "w");
	if (!of) {
		perror(filename);
		exit(ERROR_UNIX);
	}
	for (tp = settings; tp->kw; tp++) {
		putc(tp->set_value, of);
		putc(tp->set_value >> 8, of);
	}
	fclose(of);
}

main(argc, argv)
	char **argv;
{
	if (argc != 3) {
		fprintf(stderr, "usage: %s srcfile output-binfile\n", argv[0]);
		exit(ERROR_USAGE);
	}
	infname = argv[1];
	inf = fopen(infname, "r");
	if (!inf) {
		perror(infname);
		exit(ERROR_UNIX);
	}
	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++)
		process_line();
	fclose(inf);
	set_defaults();
	write_output(argv[2]);
	exit(0);
}