/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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; }