/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* COPYING NOTES
*
* parser.c -- Function to parserize a text file structure like MS'.ini
*
* Copyright (C) 2003 Roberto A. Foglietta <robang@libero.it>
* Copyright (C) 2003 GEA-Automotive <fogliettar@gea-automotive.com>
*
* 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.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* REVISION NOTES:
*
* released 22-05-2003 by Roberto A. Foglietta
* bugfixed 10-06-2003 by Roberto A. Foglietta
* bugfixed 26-06-2003 by Roberto A. Foglietta
* static 27-06-2003 by Roberto A. Foglietta
* english 03-07-2003 by Roberto A. Foglietta
*
*/
#include <stdio.h>
#ifndef __USE_GNU
# define __USE_GNU
#endif
#include <string.h>
#include <stdlib.h>
#include "parser.h"
#include "debug.h"
#define PRINT_RET(i) if(debug && cast[i] != NULL) { \
PRINTF("ret[%d] = '", i); \
printf(cast[i], ret[i]); \
PRINTF("'\n"); \
}union alltypes *
get_mult_param_value_from_text (const char *pt, const char *pname, const char **cast)
{
DEBUG(OFF);
if(pt == NULL || pname == NULL || cast == NULL)
return NULL;
//computing how many are the parameters
int n_par; {
int i = 0; while(cast[i]) i++;
if(!(n_par = i)) return NULL;
}
PRINTF("n_par = %d\n",n_par);
#ifdef MAX_NUM_PARSER_PARAM
/* RAF 2003-06-27:
* ATTENTION ATTENTION ATTENTION ATTENTION
* Static definition in not multi-thread safe!
*/
static union alltypes ret[MAX_NUM_PARSER_PARAM]; {
int i;
//Initialization of parameters' vector
for(i = 0; i < MAX_NUM_PARSER_PARAM; i++)
ret[i].s = NULL;
}
#else
//Dynamic allocation of parameters' vector
union alltypes *ret; {
long size = (n_par+1)*sizeof(union alltypes);
ret = (union alltypes *)malloc( size );
if(ret == NULL) {
return NULL;
} else {
//Initialization of parameters' vector
int i;
for(i = 0; i <= n_par; i++)
ret[i].s = NULL;
}
PRINTF("unions allocated in %u bytes\n", size);
}
#endif
//I will find the line of text containing the name
//of the selected parameter and isolate the value
const char *str = pt; {
const char *p;
str--; do {
//RAF 2003-05-20: find the parameter name
str = strstr (++str, pname);
if (str == NULL) {
#ifndef MAX_NUM_PARSER_PARAM
free(ret);
#endif
return NULL;
}
PRINTF("str = '%s'\n", str);
//RAF 2003-05-20: ignore the #comments
p = str;
while(*p != '\n' && *p != '#' && p > pt)
p--;
PRINTF("p = '%s'\n", p);
} while(*p == '#');
//RAF 2003-05-21: move on the value
str = strstr (str, "=");
if (str == NULL) {
#ifndef MAX_NUM_PARSER_PARAM
free(ret);
#endif
return NULL;
} else str++;
//RAF 2003-05-21: ignore the spaces around the '='
while (*str == ' ') str++; //ATTENTION: prefix ha un comportamento differente
}
PRINTF("str = '%s'\n", str);
//I will do a copy of the parameter value
char *sprm; {
const char *p = str; {
while(*p != '\n' && *p) p++; //ATTENTION: il file deve finire con una linea vuota
while(str < p && *p != ';') p--; //ATTENTION: il valore deve terminare con un ';'
}
sprm = (char *)strndup(str, (size_t)(p-str));
}
PRINTF("sprm = '%s'\n", sprm);
//I will do an index of all parameters
#ifdef MAX_NUM_PARSER_PARAM
char *p[MAX_NUM_PARSER_PARAM]; {
#else
char **p; {
p = (char **)malloc( (n_par+1)*sizeof(char *) );
if(p == NULL) {
free(ret);
free(sprm);
return NULL;
}
#endif
int i; p[(i=0)] = strtok(sprm, ",");
while(i < n_par && p[i]) {
PRINTF("p[%d] = '%s'\n", i, p[i]);
p[++i] = strtok(NULL, ",");
}
}
//I will fill the return vector
int i = 0;
while(i < n_par && cast[i]) {
PRINTF("%d/%d -- p = '%s', cast = '%s'\n", i+1,n_par,p[i],cast[i]);
if(p[i]) { //RAF 2003-06-26: bugfix
ret[i] = back_cast_param_from_test(p[i], cast[i]);
} else
ret[i].s = NULL;
PRINT_RET(i);
i++;
}
PRINTF("ret[%d] = '%s'\n", i, ret[i].s);
#ifndef MAX_NUM_PARSER_PARAM
free(p); //RAF-2003-05-10: fix a memory leak!
#endif
free(sprm);
/* ATTENTION:
* User who called this function has to free
* the ret vector and every ret[i].s strings
*/
return ret;
}
/* RAF 2003-05-22: allowed type of parameter value
* %u, %d, %x, %f, %s, %lu, %ld, %lx, %lf
*/
union alltypes
back_cast_param_from_test(char *str, const char *cast)
{
DEBUG(OFF);
union alltypes var;
if(str == NULL || cast == NULL) {
var.s = NULL;
return var;
}
PRINTF("str = '%s'\ncast = '%s'\n", str, cast);
switch (cast[1]) {
case 'u':
sscanf (str, "%d", &(var.u));
break;
case 'x':
if (!strncasecmp (str, "0x", 2))
str += 2;
sscanf (str, "%x", &(var.u));
break;
case 'l':
switch (cast[2]) {
case 'f':
sscanf (str, "0x%lf", &(var.lf));
break;
case 'x':
if (!strncasecmp (str, "0x", 2))
str += 2;
sscanf (str, "%lx", &(var.lu));
break;
case 'u':
sscanf (str, "%lu", &(var.lu));
break;
case 'd':
sscanf (str, "%ld", &(var.ld));
break;
default:
var.s = NULL;
break;
}
break;
case 's':
//RAF 2003-05-22: eventually I remove the quotes
var.s = strchr(str, '"');
PRINTF("var.s = '%s'\n", var.s);
if(var.s == NULL) {
var.s = strdup(str);
} else {
char *p = var.s;
var.s = strdup(++p);
PRINTF("var.s = '%s'\n", var.s);
p = strchr(var.s, '"');
if(p) *p = 0;
}
PRINTF("var.s = '%s'\n", var.s);
break;
case 'f':
sscanf (str, "%f", &(var.f));
PRINTF ("value = %f\n", var.lf);
break;
case 'd':
sscanf (str, "%d", &(var.d));
break;
default:
var.s = NULL;
break;
}
return var;
}
char *
grab_section_from_text (const char *pt, const char *name)
{
int debug = 0;
const char *p = pt;
if (name == NULL) {
p = strstr (p, "]");
if (p == NULL)
return NULL;
else {
p++;
/* RAF 2003-01-08:
* take care of doing a distinction
* between [section] and text which
* contains '[' and ']' characters.
*/
while (*p != '\n' && *p != '"')
p++;
if (*p == '"')
p = grab_section_from_text (p, NULL);
PRINTF ("<(%s)>\n", p);
}
} else
do {
p = strstr (p, "[");
if (p == NULL)
return NULL;
else {
p++;
while (*p == ' ')
p++;
}
PRINTF ("p:<<%s>>\n", p);
if (!strncasecmp (p, name, strlen (name))) {
/* RAF 2003-01-08:
* take care of doing a distinction
* between [section] and text which
* contains '[' and ']' characters.
*/
while (*p != '\n' && *p != '"' && *p != ']')
p++;
if (*p != '"' && *p != '\n')
break;
}
} while (p != NULL);
return (char *)p;
}
char *
dup_n_separate_section (const char *p)
{
int debug = 0;
char *pe, *pc, *pi;
if (p != NULL) {
pe = strstr (p, "[");
if (pe == NULL)
pc = strdup (p);
else {
/* RAF 2003-01-08:
* take care of doing a distinction
* between [section] and text which
* contains '[' and ']' characters.
*/
pi = pe;
while (*pi != '\n' && *pi != '"')
pi++;
if (*pi == '\n')
pc = (char *) strndup (p, (size_t) (pe - p - 1));
else {
pe = strstr (pi, "[");
pc = (char *) strndup (p, (size_t) (pe - p - 1));
}
PRINTF ("<{%s}>\n", pc);
}
} else
pc = NULL;
return pc;
}