From c4cb096dd938278cb1d84fbb0f135ad126204336 Mon Sep 17 00:00:00 2001 From: Frodo Looijaard Date: Sat, 19 Dec 1998 00:10:48 +0000 Subject: [PATCH] The first bunch of library files These are the relatively well-tested files. They allow you to parse a configuration file, and to build an internal abstract syntax tree. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@91 7894878c-1315-0410-8ee3-d5d059ff63e0 --- Makefile | 12 +- lib/Module.mk | 23 +++- lib/conf-lex.l | 252 +++++++++++++++++++++++++++++++++++++++ lib/conf-parse.y | 301 +++++++++++++++++++++++++++++++++++++++++++++++ lib/error.c | 62 ++++++++++ lib/error.h | 48 ++++++++ lib/general.c | 75 ++++++++++++ lib/general.h | 36 ++++++ 8 files changed, 798 insertions(+), 11 deletions(-) create mode 100644 lib/conf-lex.l create mode 100644 lib/conf-parse.y create mode 100644 lib/error.c create mode 100644 lib/error.h create mode 100644 lib/general.c create mode 100644 lib/general.h diff --git a/Makefile b/Makefile index 166f664b..0bcf9094 100644 --- a/Makefile +++ b/Makefile @@ -198,7 +198,7 @@ version: %.d: %.c $(CC) -M -MG $(MODCFLAGS) $< | \ - sed -e 's@^\(.*\)\.o:@$*.d $*.o Makefile '`dirname $*.d`/Module.mk':@' > $@ + sed -e 's@^\(.*\)\.o:@$*.d $*.o: Makefile '`dirname $*.d`/Module.mk' @' > $@ @@ -208,7 +208,7 @@ version: %.rd: %.c $(CC) -M -MG $(PROGCFLAGS) $< | \ - sed -e 's@^\(.*\)\.o:@$*.rd $*.ro Makefile '`dirname $*.rd`/Module.mk':@' > $@ + sed -e 's@^\(.*\)\.o:@$*.rd $*.ro: Makefile '`dirname $*.rd`/Module.mk' @' > $@ %: %.ro @@ -221,7 +221,7 @@ version: %.ad: %.c $(CC) -M -MG $(ARCFLAGS) $< | \ - sed -e 's@^\(.*\)\.o:@$*.ad $*.ao Makefile '`dirname $*.ad`/Module.mk':@' > $@ + sed -e 's@^\(.*\)\.o:@$*.ad $*.ao: Makefile '`dirname $*.ad`/Module.mk' @' > $@ # .lo files are used for shared libraries @@ -230,12 +230,12 @@ version: %.ld: %.c $(CC) -M -MG $(LIBCFLAGS) $< | \ - sed -e 's@^\(.*\)\.o:@$*.ld $*.lo Makefile '`dirname $*.ld`/Module.mk':@' > $@ + sed -e 's@^\(.*\)\.o:@$*.ld $*.lo: Makefile '`dirname $*.ld`/Module.mk' @' > $@ # Flex and Bison %c: %y - $(BISON) -d $< -o $@ + $(BISON) -p sensors_yy -d $< -o $@ %.c: %.l - $(FLEX) -t $< > $@ + $(FLEX) -Psensors_yy -t $< > $@ diff --git a/lib/Module.mk b/lib/Module.mk index adefb5bb..5e699b97 100644 --- a/lib/Module.mk +++ b/lib/Module.mk @@ -27,27 +27,37 @@ LIBVER := $(LIBMAINVER).$(LIBMINORVER) # The static lib name, the shared lib name, and the internal ('so') name of # the shared lib. +LIBSHBASENAME := libsensors.so LIBSHLIBNAME := libsensors.so.$(LIBVER) LIBSTLIBNAME := libsensors.a LIBSHSONAME := libsensors.so.$(LIBMAINVER) LIBTARGETS := $(MODULE_DIR)/$(LIBSTLIBNAME) $(MODULE_DIR)/$(LIBSHLIBNAME) -LIBCSOURCES := -LIBSHOBJECTS := $(LIBCSOURCES:.c=.lo) -LIBSTOBJECTS := $(LIBCSOURCES:.c=.ao) +LIBCSOURCES := $(MODULE_DIR)/data.c $(MODULE_DIR)/general.c \ + $(MODULE_DIR)/error.c +LIBOTHEROBJECTS := $(MODULE_DIR)/conf-parse.o $(MODULE_DIR)/conf-lex.o +LIBSHOBJECTS := $(LIBCSOURCES:.c=.lo) $(LIBOTHEROBJECTS:.o=.lo) +LIBSTOBJECTS := $(LIBCSOURCES:.c=.ao) $(LIBOTHEROBJECTS:.o=.ao) -LIBHEADERFILES := +LIBHEADERFILES := $(MODULE_DIR)/error.h # How to create the shared library $(MODULE_DIR)/$(LIBSHLIBNAME): $(LIBSHOBJECTS) - $(CC) -shared -Wl,-soname,$(LIBSONAME) -o $@ $< -lc + $(CC) -shared -Wl,-soname,$(LIBSONAME) -o $@ $^ -lc # And the static library $(MODULE_DIR)/$(LIBSTLIBNAME): $(LIBSTOBJECTS) $(RM) $@ $(AR) rcvs $@ $^ +# Depencies for non-C sources +$(MODULE_DIR)/conf-lex.c: $(MODULE_DIR)/conf-lex.l $(MODULE_DIR)/general.h \ + $(MODULE_DIR)/data.h $(MODULE_DIR)/conf-parse.h +$(MODULE_DIR)/conf-parse.c: $(MODULE_DIR)/conf-parse.y $(MODULE_DIR)/general.h \ + $(MODULE_DIR)/data.h +$(MODULE_DIR)/conf-parse.h: $(MODULE_DIR)/conf-parse.c + # Include all dependency files INCLUDEFILES += $(LIBCSOURCES:.c=.ld) $(LIBCSOURCES:.c=.ad) @@ -57,10 +67,13 @@ all :: all-lib install-lib: $(MKDIR) $(LIBDIR) $(LIBINCLUDEDIR) install -o root -g root -m 644 $(LIBTARGETS) $(LIBDIR) + $(LN) $(LIBSHLIBNAME) $(LIBDIR)/$(LIBSHSONAME) + $(LN) $(LIBSHSONAME) $(LIBDIR)/$(LIBSHBASENAME) install -o root -g root -m 644 $(LIBHEADERFILES) $(LIBINCLUDEDIR) install :: install-lib clean-lib: $(RM) $(LIBTARGETS) $(LIBSHOBJECTS) $(LIBSTOBJECTS) $(RM) $(LIBSHOBJECTS:.lo=.ld) $(LIBSTOBJECTS:.ao=.ad) + $(RM) $(LIBOTHEROBJECTS:.o=.c) $(MODULE_DIR)/conf-parse.h clean :: clean-lib diff --git a/lib/conf-lex.l b/lib/conf-lex.l new file mode 100644 index 00000000..02866d75 --- /dev/null +++ b/lib/conf-lex.l @@ -0,0 +1,252 @@ +%{ +/* + conf-lex.l - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +#include "general.h" +#include "data.h" +#include "conf-parse.h" +#include "error.h" + +static int buffer_count; +static int buffer_max; +static char *buffer; + +char sensors_lex_error[100]; + +#define buffer_malloc() sensors_malloc_array((void **) &buffer,&buffer_count,\ + &buffer_max,1) +#define buffer_free() sensors_free_array((void **) &buffer,&buffer_count,\ + &buffer_max) +#define buffer_add_char(c) sensors_add_array_el(c,(void **) &buffer,\ + &buffer_count,\ + &buffer_max,1) +#define buffer_add_string(s) sensors_add_array_els(s,strlen(s),\ + (void **) &buffer, \ + &buffer_count,&buffer_max,1) + +%} + +/* Scanner for configuration files */ + +%option noyywrap +%option nodefault +%option yylineno +%option nounput + +/* States. 'Normal' states STRING and MIDDLE share some rules; other states + have only their own rules */ +%s MIDDLE +%x STRING +%x ERR + +/* Any whitespace-like character */ +BLANK [[:space:]] + +IDCHAR [[:alnum:]_] + +/* Note: `10', `10.4' and `.4' are valid, `10.' is not */ +FLOAT [[:digit:]]*\.?[[:digit:]]+ + +/* Only positive whole numbers are recognized here */ +NUM 0|([1-9][[:digit:]]*) + +/* Only number between 1 and 255, octally represented. */ +OCTESC (1[0-7]{0,2})|([2-7][0-7]?)|(0[1-7][0-7]?)|(00[1-7]) + + +%% + + + /* End of line: It may be the end of this line. Same for End of file. */ +\n | +<> { + BEGIN(INITIAL); + return EOL; + } + + /* We want to match any blank, except End of line; that is why we have to + match whitespace one by one! */ +{BLANK} /* Eat up a blank */ + + /* Escaped End of line: eat and be happy */ +\\\n /* Eat this! */ + + /* Remove a comment; we do not change the state, this is done when the \n is + eaten */ +#[^\n]* /* Eat this! */ + + /* Some keywords at the beginning of lines */ +"label" { + BEGIN(MIDDLE); + return LABEL; + } + +"set" { + BEGIN(MIDDLE); + return SET; + } + +"compute" { + BEGIN(MIDDLE); + return COMPUTE; + } + +"bus" { + BEGIN(MIDDLE); + return BUS; + } + +"chip" { + BEGIN(MIDDLE); + return CHIP; + } + + /* Anything else at the beginning of a line is an error */ +. { + yymore(); + BEGIN(ERR); + } + +[^\n]*\n { + BEGIN(INITIAL); + strcpy(sensors_lex_error,"Invalid keyword"); + return ERROR; + } + + /* A number */ +{FLOAT} { + sensors_yylval.value = atof(sensors_yytext); + return FLOAT; + } + + /* Some operators */ +"+" { + return '+'; + } + +"-" { + return '-'; + } + +"*" { + return '*'; + } + +"/" { + return '/'; + } + +"(" { + return '('; + } + +")" { + return ')'; + } +"," { + return ','; + } + + /* Quoted string */ +\" { + buffer_malloc(); + BEGIN(STRING); + } + + /* Oops, newline while in a string is not good */ +\n | +\\\n { + buffer_add_char("\0"); + strcpy(sensors_lex_error,"No matching double quote"); + buffer_free(); + BEGIN(INITIAL); + return ERROR; + } + + /* At the end */ +\" { + buffer_add_char("\0"); + sensors_yylval.name = strdup(buffer); + if (! sensors_yylval.name) + sensors_fatal_error("conf-lex.l", + "Allocating a new string"); + buffer_free(); + BEGIN(MIDDLE); + return NAME; + } + +\\a { + buffer_add_char("\a"); + } + +\\b { + buffer_add_char("\b"); + } + +\\f { + buffer_add_char("\f"); + } + +\\n { + buffer_add_char("\n"); + } + +\\r { + buffer_add_char("\r"); + } + +\\t { + buffer_add_char("\t"); + } + +\\v { + buffer_add_char("\v"); + } + + /* We can't support \0, this would cause havoc! */ +\\{OCTESC} { + int res; + sscanf(sensors_yytext+1,"%o",&res); + buffer_add_char(&res); + } + + /* Other escapes: just copy the character behind the slash */ +\\. { + buffer_add_char(&sensors_yytext[1]); + } + + /* Anything else */ +[^\\\n\"]+ { + buffer_add_string(sensors_yytext); + } + + /* A normal, unquoted identifier */ +{IDCHAR}+ { + sensors_yylval.name = strdup(sensors_yytext); + if (! sensors_yylval.name) + sensors_fatal_error("conf-lex.l", + "Allocating a new string"); + + return NAME; + } + +%% diff --git a/lib/conf-parse.y b/lib/conf-parse.y new file mode 100644 index 00000000..2ee5f935 --- /dev/null +++ b/lib/conf-parse.y @@ -0,0 +1,301 @@ +%{ +/* + conf-parse.y - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define YYERROR_VERBOSE + +#include +#include +#include + +#include "data.h" +#include "general.h" +#include "error.h" + +/* These two functions are defined in conf-lex.l */ +extern int sensors_yylex(void); +extern char sensors_lex_error[]; +extern int sensors_yylineno; + +static void sensors_yyerror(const char *err); +static sensors_expr *malloc_expr(void); + +static sensors_chip *current_chip = NULL; + +#define bus_add_el(el) sensors_add_array_el(el,\ + (void **) &sensors_config_busses,\ + &sensors_config_busses_count,\ + &sensors_config_busses_max,\ + sizeof(sensors_bus)) +#define label_add_el(el) sensors_add_array_el(el,\ + (void **) ¤t_chip->labels,\ + ¤t_chip->labels_count,\ + ¤t_chip->labels_max,\ + sizeof(sensors_label)); +#define set_add_el(el) sensors_add_array_el(el,\ + (void **) ¤t_chip->sets,\ + ¤t_chip->sets_count,\ + ¤t_chip->sets_max,\ + sizeof(sensors_set)); +#define compute_add_el(el) sensors_add_array_el(el,\ + (void **) ¤t_chip->computes,\ + ¤t_chip->computes_count,\ + ¤t_chip->computes_max,\ + sizeof(sensors_compute)); +#define chip_add_el(el) sensors_add_array_el(el,\ + (void **) &sensors_config_chips,\ + &sensors_config_chips_count,\ + &sensors_config_chips_max,\ + sizeof(sensors_chip)); + +#define fits_add_el(el,list) sensors_add_array_el(el,\ + (void **) &(list).fits,\ + &(list).fits_count,\ + &(list).fits_max, \ + sizeof(sensors_chip_name)); + +/* YYERROR can only be called in rules, not in other functions, so this must + be a macro */ +#define check_current_chip()\ + do { if (! current_chip) {\ + sensors_yyerror("Label, Set or Compute statement before first chip statement");\ + YYERROR;\ + }\ + } while (0) + +%} + +%union { + double value; + char *name; + void *nothing; + sensors_chip_name_list chips; + sensors_expr *expr; + int bus; + sensors_chip_name chip; +} + +%left '-' '+' +%left '*' '/' +%left NEG + +%token ',' +%token EOL +%token BUS +%token LABEL +%token SET +%token CHIP +%token COMPUTE +%token FLOAT +%token NAME +%token ERROR + +%type chip_name_list +%type expression +%type i2cbus_name +%type adapter_name +%type algorithm_name +%type function_name +%type string +%type chip_name + +%start input + +%% + +input: /* empty */ + | input line +; + +line: bus_statement EOL + | label_statement EOL + | set_statement EOL + | chip_statement EOL + | compute_statement EOL + | error EOL +; + +bus_statement: BUS i2cbus_name adapter_name algorithm_name + { sensors_bus new_el; + new_el.number = $2; + new_el.adapter = $3; + new_el.algorithm = $4; + bus_add_el(&new_el); + } +; + +label_statement: LABEL function_name string + { sensors_label new_el; + check_current_chip(); + new_el.name = $2; + new_el.value = $3; + label_add_el(&new_el); + } +; + +set_statement: SET function_name expression + { sensors_set new_el; + check_current_chip(); + new_el.name = $2; + new_el.value = $3; + set_add_el(&new_el); + } +; + +compute_statement: COMPUTE function_name expression ',' expression + { sensors_compute new_el; + check_current_chip(); + new_el.name = $2; + new_el.from_proc = $3; + new_el.to_proc = $5; + compute_add_el(&new_el); + } +; + +chip_statement: CHIP chip_name_list + { sensors_chip new_el; + new_el.labels = NULL; + new_el.sets = NULL; + new_el.computes = NULL; + new_el.labels_count = new_el.labels_max = 0; + new_el.sets_count = new_el.sets_max = 0; + new_el.computes_count = new_el.computes_max = 0; + new_el.chips = $2; + chip_add_el(&new_el); + current_chip = sensors_config_chips + + sensors_config_chips_count - 1; + } +; + +chip_name_list: chip_name + { + $$.fits = NULL; + $$.fits_count = $$.fits_max = 0; + fits_add_el(&$1,$$); + } + | chip_name_list chip_name + { $$ = $1; + fits_add_el(&$2,$$); + } +; + +expression: FLOAT + { $$ = malloc_expr(); + $$->data.val = $1; + $$->kind = sensors_kind_val; + } + | NAME + { $$ = malloc_expr(); + $$->data.var = $1; + $$->kind = sensors_kind_var; + } + | expression '+' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_add; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | expression '-' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_sub; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | expression '*' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_multiply; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | expression '/' expression + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_divide; + $$->data.subexpr.sub1 = $1; + $$->data.subexpr.sub2 = $3; + } + | '-' expression %prec NEG + { $$ = malloc_expr(); + $$->kind = sensors_kind_sub; + $$->data.subexpr.op = sensors_negate; + $$->data.subexpr.sub1 = $2; + $$->data.subexpr.sub2 = NULL; + } + | '(' expression ')' + { $$ = $2; } +; + +i2cbus_name: NAME + { int res = sensors_parse_i2cbus_name($1,&$$); + free($1); + if (res) { + sensors_yyerror("Parse error in i2c bus name"); + YYERROR; + } + } +; + +adapter_name: NAME + { $$ = $1; } +; + +algorithm_name: NAME + { $$ = $1; } +; + +function_name: NAME + { $$ = $1; } +; + +string: NAME + { $$ = $1; } +; + +chip_name: NAME + { int res = sensors_parse_chip_name($1,&$$); + free($1); + if (res) { + sensors_yyerror("Parse error in chip name"); + YYERROR; + } + } +; + +%% + +void sensors_yyerror(const char *err) +{ + if (sensors_lex_error[0]) { + sensors_parse_error(sensors_lex_error,sensors_yylineno); + sensors_lex_error[0] = '\0'; + } else + sensors_parse_error(err,sensors_yylineno); +} + +sensors_expr *malloc_expr(void) +{ + sensors_expr *res = malloc(sizeof(sensors_expr)); + if (! res) + sensors_fatal_error("malloc_expr","Allocating a new expression"); + return res; +} + diff --git a/lib/error.c b/lib/error.c new file mode 100644 index 00000000..32f0bcf4 --- /dev/null +++ b/lib/error.c @@ -0,0 +1,62 @@ +/* + error.c - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include "error.h" + +static void sensors_default_parse_error(const char *err, int lineno); +static void sensors_default_fatal_error(const char *proc,const char *err); + +void (*sensors_parse_error) (const char *err, int lineno) = + sensors_default_parse_error; +void (*sensors_fatal_error) (const char *proc, const char *err) = + sensors_default_fatal_error; + +static const char *errorlist[] = + { /* Unknown error */ "sensors_strerror: Unknown error!", + /* SENSORS_ERR_WILDCARDS */ "Wildcard found in chip name", + /* SENSORS_ERR_NO_ENTRY */ "No such feature known", + /* SENSORS_ERR_ACCESS */ "Can't read or write", + /* SENSORS_ERR_PROC */ "Can't access /proc file", + /* SENSORS_ERR_DIV_ZERO */ "Divide by zero", + /* SENSORS_ERR_CHIP_NAME */ "Can't parse chip name", + /* SENSORS_ERR_BUS_NAME */ "Can't parse bus name" + }; + +#define ERROR_LIST_LEN (sizeof(errorlist) / sizeof(char *)) + +char *sensors_strerror(int errnum) +{ + if (errnum < 0) + errnum = -errnum; + if (errnum >= ERROR_LIST_LEN) + errnum = 0; + return errorlist[errnum]; +} + +void sensors_default_parse_error(const char *err, int lineno) +{ + fprintf(stderr,"Line %d: %s\n",lineno,err); +} + +void sensors_default_fatal_error(const char *proc, const char *err) +{ + fprintf(stderr,"Fatal error in `%s': %s\n",proc,err); + exit(1); +} diff --git a/lib/error.h b/lib/error.h new file mode 100644 index 00000000..13ab56db --- /dev/null +++ b/lib/error.h @@ -0,0 +1,48 @@ +/* + error.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef LIB_SENSORS_ERROR_H +#define LIB_SENSORS_ERROR_H + +#define SENSORS_ERR_WILDCARDS 1 /* Wildcard found in chip name */ +#define SENSORS_ERR_NO_ENTRY 2 /* No such feature known */ +#define SENSORS_ERR_ACCESS 3 /* Can't read or write */ +#define SENSORS_ERR_PROC 4 /* Can't access /proc file */ +#define SENSORS_ERR_DIV_ZERO 5 /* Divide by zero */ +#define SENSORS_ERR_CHIP_NAME 6 /* Can't parse chip name */ +#define SENSORS_ERR_BUS_NAME 7 /* Can't parse bus name */ + +/* This function returns a pointer to a string which describes the error. + errnum may be negative (the corresponding positive error is returned). + You may not modify the result! */ +extern char *sensors_strerror(int errnum); + +/* This function is called when a parse error is detected. Give it a new + value, and your own function is called instead of the default (which + prints to stderr). */ +extern void (*sensors_parse_error) (const char *err, int lineno); + +/* This function is called when an immediately fatal error (like no + memory left) is detected. Give it a new value, and your own function + is called instead of the default (which prints to stderr and ends + the program). */ +extern void (*sensors_fatal_error) (const char *proc, const char *err); + + +#endif /* def LIB_SENSORS_ERROR_H */ diff --git a/lib/general.c b/lib/general.c new file mode 100644 index 00000000..2f8700cf --- /dev/null +++ b/lib/general.c @@ -0,0 +1,75 @@ +/* + general.c - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "general.h" +#include +#include +#include +#include + + +#define A_BUNCH 16 + +void sensors_malloc_array(void **list, int *num_el, int *max_el, int el_size) +{ + *list = malloc(el_size*A_BUNCH); + if (! *list) + sensors_fatal_error("sensors_malloc_array","Allocating new elements"); + *max_el = A_BUNCH; + *num_el = 0; +} + +void sensors_free_array(void **list, int *num_el, int *max_el) +{ + free(*list); + *list = NULL; + *num_el = 0; + *max_el = 0; +} + +void sensors_add_array_el(const void *el, void **list, int *num_el, + int *max_el, int el_size) +{ + int new_max_el; + if (*num_el + 1 > *max_el) { + new_max_el = *max_el + A_BUNCH; + *list = realloc(*list,new_max_el * el_size); + if (! *list) + sensors_fatal_error("sensors_add_array_el","Allocating new elements"); + *max_el = new_max_el; + } + memcpy(((char *) *list) + *num_el * el_size, el, el_size); + (*num_el) ++; +} + +void sensors_add_array_els(const void *els, int nr_els, void **list, + int *num_el, int *max_el, int el_size) +{ + int new_max_el; + if (*num_el + nr_els > *max_el) { + new_max_el = (*max_el + nr_els + A_BUNCH); + new_max_el -= new_max_el % A_BUNCH; + *list = realloc(*list,new_max_el * el_size); + if (! *list) + sensors_fatal_error("sensors_add_array_els","Allocating new elements"); + *max_el = new_max_el; + } + memcpy(((char *)*list) + *num_el * el_size, els, el_size * nr_els); + *num_el += nr_els; +} diff --git a/lib/general.h b/lib/general.h new file mode 100644 index 00000000..4c85e350 --- /dev/null +++ b/lib/general.h @@ -0,0 +1,36 @@ +/* + general.h - Part of libsensors, a Linux library for reading sensor data. + Copyright (c) 1998 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef LIB_SENSORS_GENERAL +#define LIB_SENSORS_GENERAL + +/* These are general purpose functions. They allow you to use variable- + length arrays, which are extended automatically. A distinction is + made between the current number of elements and the maximum number. + You can only add elements at the end. Primitive, but very useful + for internal use. */ +extern void sensors_malloc_array(void **list, int *num_el, int *max_el, + int el_size); +extern void sensors_free_array(void **list, int *num_el, int *max_el); +extern void sensors_add_array_el(const void *el, void **list, int *num_el, + int *max_el, int el_size); +extern void sensors_add_array_els(const void *els, int nr_els, void **list, + int *num_el, int *max_el, int el_size); + +#endif /* LIB_SENSORS_GENERAL */