TORCS  1.3.9
The Open Racing Car Simulator
params.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  params.cpp -- configuration parameters management
3  -------------------
4  created : Fri Aug 13 22:27:57 CEST 1999
5  copyright : (C) 1999-2014 by Eric Espie, Bernhard Wymann
6  email : torcs@free.fr
7  version : $Id$
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <sys/stat.h>
28 #ifndef _WIN32
29 #include <unistd.h>
30 #endif
31 #include <math.h>
32 
33 #include <xmlparse.h>
34 #ifdef WIN32
35 #include <windows.h>
36 #endif
37 #include <tgf.h>
38 #include <assert.h>
39 #include <portability.h>
40 
41 
42 #define LINE_SZ 1024
43 #define PARAM_CREATE 0x01
44 
45 #define P_NUM 0
46 #define P_STR 1
47 
49 struct within
50 {
51  char *val;
52  GF_TAILQ_ENTRY (struct within) linkWithin;
53 };
54 
55 GF_TAILQ_HEAD (withinHead, struct within);
56 
57 
58 
63 struct param
64 {
65  char *name;
66  char *fullName;
67  char *value;
69  int type;
70  char *unit;
73  struct withinHead withinList;
74  GF_TAILQ_ENTRY (struct param) linkParam;
75 };
76 
77 GF_TAILQ_HEAD (paramHead, struct param);
78 struct section;
79 GF_TAILQ_HEAD (sectionHead, struct section);
80 
81 
83 struct section
84 {
85  char *fullName;
86  struct paramHead paramList;
87  GF_TAILQ_ENTRY (struct section) linkSection;
88  struct sectionHead subSectionList;
90  struct section *parent;
91 };
92 
93 
94 #define PARM_MAGIC 0x20030815
95 
97 struct parmHeader
98 {
99  char *filename;
100  char *name;
101  char *dtd;
102  char *header;
103  int refcount;
105  void *paramHash;
106  void *sectionHash;
107 };
108 
109 #define PARM_HANDLE_FLAG_PRIVATE 0x01
110 #define PARM_HANDLE_FLAG_PARSE_ERROR 0x02
111 
112 
115 {
116  int state;
117  struct section *curSection;
118  struct param *curParam;
119  char *filename;
120  int indent;
121 };
122 
123 
126 {
127  int magic;
128  struct parmHeader *conf;
129  int flag;
131  struct section *curSection;
133  GF_TAILQ_ENTRY (struct parmHandle) linkHandle;
134 };
135 
136 
137 GF_TAILQ_HEAD (parmHead, struct parmHandle);
138 
139 static struct parmHead parmHandleList;
140 
141 static char *getFullName(const char *sectionName, const char *paramName);
142 static struct param *getParamByName (struct parmHeader *conf, const char *sectionName, const char *paramName, int flag);
143 static void removeParamByName (struct parmHeader *conf, const char *sectionName, const char *paramName);
144 static void removeParam (struct parmHeader *conf, struct section *section, struct param *param);
145 static struct param *addParam (struct parmHeader *conf, struct section *section, const char *paramName, const char *value);
146 static void removeSection (struct parmHeader *conf, struct section *section);
147 static struct section *addSection (struct parmHeader *conf, const char *sectionName);
148 static void parmClean (struct parmHeader *conf);
149 static void parmReleaseHandle (struct parmHandle *parmHandle);
150 static void parmReleaseHeader (struct parmHeader *conf);
151 static struct section *getParent (struct parmHeader *conf, const char *sectionName);
152 static void cleanUnusedSection (struct parmHeader *conf, struct section *section);
153 
154 
158 void GfParmInit (void)
159 {
161 }
162 
163 
167 void GfParmShutdown (void)
168 {
169  struct parmHandle *parmHandle;
170 
173  }
174 }
175 
176 
187 static char *getFullName (const char *sectionName, const char *paramName)
188 {
189  char *fullName;
190  unsigned long len = strlen (sectionName) + strlen (paramName) + 2;
191 
192  fullName = (char *) malloc(strlen (sectionName) + strlen (paramName) + 2);
193  if (!fullName) {
194  GfError ("getFullName: malloc (%lu) failed", len);
195  return NULL;
196  }
197  snprintf(fullName, len, "%s/%s", sectionName, paramName);
198 
199  return fullName;
200 }
201 
202 
213 static struct param* getParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName, int flag)
214 {
215  char *fullName;
216  struct param *param;
217  struct section *section;
218 
219  fullName = getFullName (sectionName, paramName);
220  if (!fullName) {
221  GfError ("getParamByName: getFullName failed\n");
222  return NULL;
223  }
224 
225  param = (struct param *)GfHashGetStr (conf->paramHash, fullName);
226  free (fullName);
227  if (param || ((flag & PARAM_CREATE) == 0)) {
228  return param;
229  }
230 
231  /* Parameter not found CREATE it */
232  section = (struct section *)GfHashGetStr (conf->sectionHash, sectionName);
233  if (!section) {
234  section = addSection (conf, sectionName);
235  if (!section) {
236  GfError ("getParamByName: addSection failed\n");
237  return NULL;
238  }
239  }
240  param = addParam (conf, section, paramName, "");
241 
242  return param;
243 }
244 
245 
254 static void removeParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName)
255 {
256  char *fullName;
257  struct param *param;
258  struct section *section;
259 
260  section = (struct section *)GfHashGetStr (conf->sectionHash, sectionName);
261  if (!section) {
262  return;
263  }
264 
265  fullName = getFullName (sectionName, paramName);
266  if (!fullName) {
267  GfError("removeParamByName: getFullName failed\n");
268  return;
269  }
270 
271  param = (struct param *)GfHashGetStr (conf->paramHash, fullName);
272  freez (fullName);
273  if (param) {
274  removeParam(conf, section, param);
275  }
276 
278 }
279 
280 
291 static void cleanUnusedSection(struct parmHeader *conf, struct section *section)
292 {
293  struct section *parent;
294 
295  if (
296  !section->fullName ||
298  ) {
299  parent = section->parent;
300  removeSection (conf, section);
301  if (parent) {
302  /* check if the parent is unused */
303  cleanUnusedSection (conf, parent);
304  }
305  }
306 }
307 
308 
316 static void removeParam(struct parmHeader *conf, struct section *section, struct param *param)
317 {
319  GF_TAILQ_REMOVE (&(section->paramList), param, linkParam);
320 
321  struct within *within;
323  GF_TAILQ_REMOVE (&param->withinList, within, linkWithin);
324  freez(within->val);
325  free(within);
326  }
327 
328  freez (param->name);
329  freez (param->fullName);
330  freez (param->value);
331  freez (param->unit);
332  freez (param);
333 }
334 
335 
346 static struct param *addParam(struct parmHeader *conf, struct section *section, const char *paramName, const char *value)
347 {
348  char *fullName;
349  struct param *param = NULL;
350  char *tmpVal = NULL;
351  const unsigned long len = sizeof (struct param);
352 
353  tmpVal = strdup (value);
354  if (!tmpVal) {
355  GfError ("addParam: strdup (%s) failed\n", value);
356  goto bailout;
357  }
358 
359  param = (struct param *) calloc (1, len);
360  if (!param) {
361  GfError ("addParam: calloc (1, %lu) failed\n", len);
362  goto bailout;
363  }
364 
365  param->name = strdup (paramName);
366  if (!param->name) {
367  GfError ("addParam: strdup (%s) failed\n", paramName);
368  goto bailout;
369  }
370 
371  fullName = getFullName (section->fullName, paramName);
372  if (!fullName) {
373  GfError ("addParam: getFullName failed\n");
374  goto bailout;
375  }
376 
378  if (GfHashAddStr (conf->paramHash, param->fullName, param)) {
379  goto bailout;
380  }
381 
383 
384  /* Attach to section */
385  GF_TAILQ_INSERT_TAIL (&(section->paramList), param, linkParam);
386 
387  freez (param->value);
388  param->value = tmpVal;
389 
390  return param;
391 
392  bailout:
393  if (param) {
394  freez (param->name);
395  freez (param->fullName);
396  freez (param->value);
397  free (param);
398  }
399  freez (tmpVal);
400 
401  return NULL;
402 }
403 
404 
411 static void removeSection(struct parmHeader *conf, struct section *section)
412 {
413  struct param *param;
414  struct section *subSection;
415 
416  while ((subSection = GF_TAILQ_FIRST (&(section->subSectionList))) != NULL) {
417  removeSection (conf, subSection);
418  }
419 
420  if (section->fullName) {
421  /* not the root section */
423  GF_TAILQ_REMOVE (&(section->parent->subSectionList), section, linkSection);
424  while ((param = GF_TAILQ_FIRST (&(section->paramList))) != GF_TAILQ_END (&(section->paramList))) {
425  removeParam (conf, section, param);
426  }
428  }
429  freez (section);
430 }
431 
432 
441 static struct section *getParent(struct parmHeader *conf, const char *sectionName)
442 {
443  struct section *section;
444  char *tmpName;
445  char *s;
446 
447  tmpName = strdup (sectionName);
448  if (!tmpName) {
449  GfError ("getParent: strdup (\"%s\") failed\n", sectionName);
450  return NULL;
451  }
452 
453  s = strrchr (tmpName, '/');
454  if (s) {
455  *s = '\0';
456  section = (struct section *)GfHashGetStr (conf->sectionHash, tmpName);
457  if (section) {
458  goto end;
459  }
460  section = addSection (conf, tmpName);
461  goto end;
462  } else {
463  section = conf->rootSection;
464  goto end;
465  }
466 
467 end:
468  free (tmpName);
469  return section;
470 }
471 
472 
481 static struct section *addSection(struct parmHeader *conf, const char *sectionName)
482 {
483  struct section *section;
484  struct section *parent;
485  const unsigned long len = sizeof (struct section);
486 
487  if (GfHashGetStr (conf->sectionHash, sectionName)) {
488  GfError ("addSection: duplicate section [%s]\n", sectionName);
489  return NULL;
490  }
491 
492  parent = getParent(conf, sectionName);
493  if (!parent) {
494  GfError ("addSection: Problem with getParent for section [%s]\n", sectionName);
495  return NULL;
496  }
497 
498  section = (struct section *) calloc (1, len);
499  if (!section) {
500  GfError ("addSection: calloc (1, %lu) failed\n", len);
501  return NULL;
502  }
503 
504  section->fullName = strdup(sectionName);
505  if (!section->fullName) {
506  GfError ("addSection: strdup (%s) failed\n", sectionName);
507  goto bailout;
508  }
509 
510  if (GfHashAddStr (conf->sectionHash, sectionName, section)) {
511  GfError ("addSection: GfHashAddStr failed\n");
512  goto bailout;
513  }
514 
515  /* no more bailout call */
516  section->parent = parent;
520 
521  return section;
522 
523 bailout:
525  freez (section);
526  return NULL;
527 }
528 
529 
546  static struct parmHeader *getSharedHeader(const char *file, int mode)
547 {
548  struct parmHeader *conf = NULL;
549  struct parmHandle *parmHandle;
550 
551  /* Search for existing conf */
552  if ((mode & GFPARM_RMODE_PRIVATE) == 0) {
553  for (
556  parmHandle = GF_TAILQ_NEXT (parmHandle, linkHandle)
557  ) {
558  if ((parmHandle->flag & PARM_HANDLE_FLAG_PRIVATE) == 0) {
559  conf = parmHandle->conf;
560  if (!strcmp(conf->filename, file)) {
561  if (mode & GFPARM_RMODE_REREAD) {
562  parmClean (conf);
563  }
564  conf->refcount++;
565  return conf;
566  }
567  }
568  }
569  }
570 
571  return NULL;
572 }
573 
574 
582 static struct parmHeader* createParmHeader (const char *file)
583 {
584  struct parmHeader *conf = NULL;
585  const unsigned long parmheadersize = sizeof (struct parmHeader);
586  const unsigned long sectionsize = sizeof (struct section);
587 
588  conf = (struct parmHeader *) calloc (1, parmheadersize);
589  if (!conf) {
590  GfError ("gfParmReadFile: calloc (1, %lu) failed\n", parmheadersize);
591  return NULL;
592  }
593 
594  conf->refcount = 1;
595 
596  conf->rootSection = (struct section *) calloc (1, sectionsize);
597  if (!conf->rootSection) {
598  GfError ("gfParmReadFile: calloc (1, %lu) failed\n", sectionsize);
599  goto bailout;
600  }
601 
602  GF_TAILQ_INIT (&(conf->rootSection->paramList));
604 
606  if (!conf->paramHash) {
607  GfError ("gfParmReadFile: GfHashCreate (paramHash) failed\n");
608  goto bailout;
609  }
610 
612  if (!conf->sectionHash) {
613  GfError ("gfParmReadFile: GfHashCreate (sectionHash) failed\n");
614  goto bailout;
615  }
616 
617  conf->filename = strdup (file);
618  if (!conf->filename) {
619  GfError ("gfParmReadFile: strdup (%s) failed\n", file);
620  goto bailout;
621  }
622 
623  return conf;
624 
625  bailout:
626  freez (conf->rootSection);
627  if (conf->paramHash) {
628  GfHashRelease (conf->paramHash, NULL);
629  }
630 
631  if (conf->sectionHash) {
632  GfHashRelease (conf->sectionHash, NULL);
633  }
634 
635  freez (conf->filename);
636  freez (conf);
637 
638  return NULL;
639 }
640 
641 
648 static void addWithin (struct param *curParam, char *s1)
649 {
650  struct within *curWithin;
651 
652  if (!s1 || ! strlen (s1)) {
653  return;
654  }
655 
656  curWithin = (struct within *) calloc (1, sizeof (struct within));
657  curWithin->val = strdup (s1);
658  GF_TAILQ_INSERT_TAIL (&(curParam->withinList), curWithin, linkWithin);
659 }
660 
661 
662 static int myStrcmp(const void *s1, const void * s2)
663 {
664  return strcmp((const char *)s1, (const char *)s2);
665 }
666 
667 
674 static tdble getValNumFromStr (const char *str)
675 {
676  tdble val;
677 
678  if (!str || !strlen (str)) {
679  return 0.0;
680  }
681 
682  if (strncmp (str, "0x", 2) == 0) {
683  return (tdble)strtol(str, NULL, 0);
684  }
685 
686  sscanf (str, "%g", &val);
687  return val;
688 }
689 
690 
698 static void xmlStartElement (void *userData , const char *name, const char **atts)
699 {
700  struct parmHandle *parmHandle = (struct parmHandle *)userData;
701  struct parmHeader *conf = parmHandle->conf;
702  struct param *curParam;
703 
704  int nAtts;
705  int len;
706  const char **p;
707  const char *s1, *s2;
708  char *fullName;
709  const char *shortName;
710  const char *val;
711  const char *min;
712  const char *max;
713  const char *unit;
714  char *within;
715  char *sa, *sb;
716 
718  // parse error occured, ignore.
719  return;
720  }
721 
722  p = atts;
723  while (*p) {
724  ++p;
725  }
726 
727  nAtts = (p - atts) >> 1;
728  if (nAtts > 1) {
729  qsort ((void *)atts, nAtts, sizeof(char *) * 2, myStrcmp);
730  }
731 
732  if (!strcmp(name, "params")) {
733 
735  parmHandle->curSection->fullName = strdup ("");
736 
737  if (!parmHandle->curSection->fullName) {
738  GfError ("xmlStartElement: strdup (\"\") failed\n");
739  goto bailout;
740  }
741 
742  while (*atts) {
743  s1 = *atts++;
744  s2 = *atts++;
745  if (!strcmp(s1, "name")) {
746  FREEZ (conf->name);
747  conf->name = strdup(s2);
748  if (!conf->name) {
749  GfError ("xmlStartElement: strdup (\"%s\") failed\n", s2);
750  goto bailout;
751  }
752  break;
753  }
754  }
755 
756  if (!conf->name) {
757  GfOut ("xmlStartElement: Syntax error, missing \"name\" field in params definition\n");
758  goto bailout;
759  }
760 
761  } else if (!strcmp(name, "section")) {
762 
763  if (!parmHandle->curSection) {
764  GfError ("xmlStartElement: Syntax error, missing \"params\" tag\n");
765  goto bailout;
766  }
767 
768  shortName = NULL;
769 
770  while (*atts) {
771  s1 = *atts++;
772  s2 = *atts++;
773  if (!strcmp(s1, "name")) {
774  shortName = s2;
775  break;
776  }
777  }
778 
779  if (!shortName) {
780  GfError ("xmlStartElement: Syntax error, missing \"name\" field in section definition\n");
781  goto bailout;
782  }
783 
784  if (strlen(parmHandle->curSection->fullName)) {
785  len = strlen (shortName) + strlen (parmHandle->curSection->fullName) + 2;
786  fullName = (char *) malloc (len);
787  if (!fullName) {
788  GfError ("xmlStartElement: malloc (%d) failed\n", len);
789  goto bailout;
790  }
791  snprintf (fullName, len, "%s/%s", parmHandle->curSection->fullName, shortName);
792  } else {
793  fullName = strdup (shortName);
794  }
795 
797  free(fullName);
798 
799  if (!parmHandle->curSection) {
800  GfError ("xmlStartElement: addSection failed\n");
801  goto bailout;
802  }
803 
804  } else if (!strcmp(name, "attnum")) {
805 
806  if ((!parmHandle->curSection) || (!strlen (parmHandle->curSection->fullName))) {
807  GfError ("xmlStartElement: Syntax error, missing \"section\" tag\n");
808  goto bailout;
809  }
810 
811  shortName = NULL;
812  val = NULL;
813  min = max = unit = NULL;
814 
815  while (*atts) {
816  s1 = *atts++;
817  s2 = *atts++;
818  if (!strcmp(s1, "name")) {
819  shortName = s2;
820  } else if (!strcmp(s1, "val")) {
821  val = s2;
822  } else if (!strcmp(s1, "min")) {
823  min = s2;
824  } else if (!strcmp(s1, "max")) {
825  max = s2;
826  } else if (!strcmp(s1, "unit")) {
827  unit = s2;
828  }
829  }
830 
831  if (!shortName) {
832  GfError ("xmlStartElement: Syntax error, missing \"name\" field in %s definition\n", name);
833  goto bailout;
834  }
835 
836  if (!val) {
837  GfError ("xmlStartElement: Syntax error, missing \"val\" field in %s definition\n", name);
838  goto bailout;
839  }
840 
841  if (!min) {
842  min = val;
843  }
844 
845  if (!max) {
846  max = val;
847  }
848 
849  curParam = addParam (conf, parmHandle->curSection, shortName, val);
850  if (!curParam) {
851  GfError ("xmlStartElement: addParam failed\n");
852  goto bailout;
853  }
854 
855  curParam->type = P_NUM;
856  curParam->valnum = getValNumFromStr (val);
857  curParam->min = getValNumFromStr (min);
858  curParam->max = getValNumFromStr (max);
859 
860  if (curParam->min > curParam->valnum) {
861  curParam->min = curParam->valnum;
862  }
863 
864  if (curParam->max < curParam->valnum) {
865  curParam->max = curParam->valnum;
866  }
867 
868  if (unit) {
869  curParam->unit = strdup (unit);
870  curParam->valnum = GfParmUnit2SI ((char*)unit, curParam->valnum);
871  curParam->min = GfParmUnit2SI ((char*)unit, curParam->min);
872  curParam->max = GfParmUnit2SI ((char*)unit, curParam->max);
873  }
874 
875  } else if (!strcmp(name, "attstr")) {
876 
877  if ((!parmHandle->curSection) || (!strlen (parmHandle->curSection->fullName))) {
878  GfError ("xmlStartElement: Syntax error, missing \"section\" tag\n");
879  goto bailout;
880  }
881 
882  shortName = NULL;
883  val = NULL;
884  within = NULL;
885 
886  while (*atts) {
887  s1 = *atts++;
888  s2 = *atts++;
889  if (!strcmp(s1, "name")) {
890  shortName = s2;
891  } else if (!strcmp(s1, "val")) {
892  val = s2;
893  } else if (!strcmp(s1, "in")) {
894  within = (char *)s2;
895  }
896  }
897 
898  if (!shortName) {
899  GfError ("xmlStartElement: Syntax error, missing \"name\" field in %s definition\n", name);
900  goto bailout;
901  }
902 
903  if (!val) {
904  GfError ("xmlStartElement: Syntax error, missing \"val\" field in %s definition\n", name);
905  goto bailout;
906  }
907 
908  curParam = addParam (conf, parmHandle->curSection, shortName, val);
909  if (!curParam) {
910  GfError ("xmlStartElement: addParam failed\n");
911  goto bailout;
912  }
913 
914  curParam->type = P_STR;
915  if (within) {
916  sa = within;
917  sb = strchr (sa, ',');
918  while (sb) {
919  *sb = 0;
920  addWithin (curParam, sa);
921  sa = sb + 1;
922  sb = strchr (sa, ',');
923  }
924  addWithin (curParam, sa);
925  }
926 
927  }
928 
929  return;
930 
931  bailout:
933  return;
934 }
935 
936 
943 static void xmlEndElement (void *userData, const XML_Char *name)
944 {
945  struct parmHandle *parmHandle = (struct parmHandle *)userData;
946 
948  /* parse error occured, ignore */
949  return;
950  }
951 
952  if (!strcmp(name, "section")) {
954  GfError ("xmlEndElement: Syntax error in \"%s\"\n", name);
955  return;
956  }
958  }
959 }
960 
961 
974  XML_Parser mainparser,
975  const XML_Char *openEntityNames,
976  const XML_Char *base,
977  const XML_Char *systemId,
978  const XML_Char *publicId)
979 {
980  FILE *in;
981  char buf[BUFSIZ];
983  int done;
984  char fin[LINE_SZ];
985  char *s;
986  struct parmHandle *parmHandle;
987  struct parmHeader *conf;
988 
989  parmHandle = (struct parmHandle *)XML_GetUserData (mainparser);
990  conf = parmHandle->conf;
991 
992  parser = XML_ExternalEntityParserCreate (mainparser, openEntityNames, (const XML_Char *)NULL);
993 
994  if (systemId[0] == '/') {
995  strncpy (fin, systemId, sizeof (fin));
996  fin[LINE_SZ - 1] = 0;
997  } else {
998  /* relative path */
999  strncpy (fin, conf->filename, sizeof (fin));
1000  fin[LINE_SZ - 1] = 0;
1001  s = strrchr (fin, '/');
1002  if (s) {
1003  s++;
1004  } else {
1005  s = fin;
1006  }
1007  strncpy (s, systemId, sizeof (fin) - (s - fin));
1008  fin[LINE_SZ - 1] = 0;
1009  }
1010 
1011  in = fopen (fin, "r");
1012  if (in == NULL) {
1013  perror (fin);
1014  GfError ("GfReadParmFile: file %s has pb\n", systemId);
1015  return 0;
1016  }
1017 
1019  do {
1020  size_t len = fread (buf, 1, sizeof(buf), in);
1021  done = len < sizeof (buf);
1022  if (!XML_Parse (parser, buf, len, done)) {
1023  GfError ("file: %s -> %s at line %d\n",
1024  systemId,
1027  fclose (in);
1028  return 0;
1029  }
1030  } while (!done);
1031 
1033  fclose(in);
1034 
1035  return 1; /* ok (0 for failure) */
1036 }
1037 
1038 
1049 static int parseXml(struct parmHandle *parmHandle, char *buf, int len, int done)
1050 {
1051  if (!XML_Parse(parmHandle->parser, buf, len, done)) {
1052  GfError ("parseXml: %s at line %d\n",
1055  return 1;
1056  }
1057 
1058  if (done) {
1060  parmHandle->parser = 0;
1061  }
1062 
1063  return 0;
1064 }
1065 
1066 
1073 {
1078 
1079  return 0;
1080 }
1081 
1082 
1091 void* GfParmReadBuf (char *buffer)
1092 {
1093  struct parmHeader *conf;
1094  struct parmHandle *parmHandle = NULL;
1095  const unsigned long parmhandlesize = sizeof (struct parmHandle);
1096 
1097  /* Conf Header creation */
1098  conf = createParmHeader ("");
1099  if (!conf) {
1100  GfError ("gfParmReadBuf: conf header creation failed\n");
1101  goto bailout;
1102  }
1103 
1104  /* Handle creation */
1105  parmHandle = (struct parmHandle *) calloc (1, parmhandlesize);
1106  if (!parmHandle) {
1107  GfError ("gfParmReadBuf: calloc (1, %lu) failed\n", parmhandlesize);
1108  goto bailout;
1109  }
1110 
1112  parmHandle->conf = conf;
1114 
1115  /* Parsers Initialization */
1116  if (parserXmlInit (parmHandle)) {
1117  GfError ("gfParmReadBuf: parserInit failed\n");
1118  goto bailout;
1119  }
1120 
1121  /* Parameters reading in buffer */
1122  if (parseXml (parmHandle, buffer, strlen (buffer), 1)) {
1123  GfError ("gfParmReadBuf: Parse failed for buffer\n");
1124  goto bailout;
1125  }
1126 
1128 
1129  return parmHandle;
1130 
1131  bailout:
1132  freez (parmHandle);
1133  if (conf) {
1135  }
1136 
1137  return NULL;
1138 }
1139 
1140 
1157 void* GfParmReadFile(const char *file, int mode)
1158 {
1159  FILE *in = NULL;
1160  struct parmHeader *conf;
1161  struct parmHandle *parmHandle = NULL;
1162  char buf[LINE_SZ];
1163  int len;
1164  int done;
1165  const unsigned long parmHandleSize = sizeof (struct parmHandle);
1166 
1167  /* search for an already openned header & clean the conf if necessary */
1168  conf = getSharedHeader (file, mode);
1169 
1170  /* Conf Header creation */
1171  if (conf == NULL) {
1172  conf = createParmHeader (file);
1173  if (!conf) {
1174  GfError ("gfParmReadFile: conf header creation failed\n");
1175  goto bailout;
1176  }
1177  mode |= GFPARM_RMODE_REREAD;
1178  }
1179 
1180  /* Handle creation */
1181  parmHandle = (struct parmHandle *) calloc (1, parmHandleSize);
1182  if (!parmHandle) {
1183  GfError ("gfParmReadFile: calloc (1, %lu) failed\n", parmHandleSize);
1184  goto bailout;
1185  }
1186 
1188  parmHandle->conf = conf;
1189  if (mode & GFPARM_RMODE_PRIVATE) {
1191  }
1192 
1193  /* File opening */
1194  if (mode & GFPARM_RMODE_REREAD) {
1195  in = fopen (file, "r");
1196  if (!in && ((mode & GFPARM_RMODE_CREAT) == 0)) {
1197  GfOut ("gfParmReadFile: fopen \"%s\" failed\n", file);
1198  goto bailout;
1199  }
1200 
1201  if (in) {
1202  /* Parsers Initialization */
1203  if (parserXmlInit (parmHandle)) {
1204  GfError ("gfParmReadBuf: parserInit failed for file \"%s\"\n", file);
1205  goto bailout;
1206  }
1207  /* Parameters reading */
1208  do {
1209  len = fread (buf, 1, sizeof(buf), in);
1210  done = len < (int)sizeof(buf);
1211  if (parseXml (parmHandle, buf, len, done)) {
1212  GfError ("gfParmReadFile: Parse failed in file \"%s\"\n", file);
1213  goto bailout;
1214  }
1216  /* parse error occured, ignore */
1217  GfError ("gfParmReadFile: Parse failed in file \"%s\"\n", file);
1218  goto bailout;
1219  }
1220  } while (!done);
1221 
1222  fclose (in);
1223  in = NULL;
1224  }
1225  }
1226 
1228 
1229  GfOut ("GfParmReadFile: Opening \"%s\" (%p)\n", file, parmHandle);
1230 
1231  return parmHandle;
1232 
1233  bailout:
1234  if (in) {
1235  fclose (in);
1236  }
1237  freez (parmHandle);
1238  if (conf) {
1240  }
1241 
1242  return NULL;
1243 }
1244 
1245 
1254 static char* handleEntities(char *buf, const int BUFSIZE, const char* val)
1255 {
1256  int i = 0;
1257  int len = strlen(val);
1258  const char *replacement;
1259  char *pos = buf;
1260  int rlen;
1261 
1262  for (i = 0; i < len; i++) {
1263  switch (val[i]) {
1264  case '<':
1265  replacement = "&lt;"; break;
1266  case '>':
1267  replacement = "&gt;"; break;
1268  case '&':
1269  replacement = "&amp;"; break;
1270  case '\'':
1271  replacement = "&apos;"; break;
1272  case '"':
1273  replacement = "&quot;"; break;
1274  default:
1275  replacement = 0;
1276  }
1277 
1278  if (replacement == 0) {
1279  replacement = &val[i];
1280  rlen = 1;
1281  } else {
1282  rlen = strlen(replacement);
1283  }
1284 
1285  if (pos-buf < BUFSIZE - rlen) {
1286  memcpy(pos, replacement, rlen*sizeof(char));
1287  pos += rlen;
1288  } else {
1289  GfError("handleEntities: buffer too small to convert %s", val);
1290  break;
1291  }
1292  }
1293 
1294  *pos = '\0';
1295 
1296  return buf;
1297 }
1298 
1299 
1307 static void createIndent(char *buf, const int BUFSIZE, const int blanks)
1308 {
1309  int pos = 0;
1310  while ((pos < BUFSIZE - 1) && (pos < blanks)) {
1311  *buf++ = ' ';
1312  pos++;
1313  }
1314  *buf = '\0';
1315 }
1316 
1317 
1325 static void createIn(char *buf, const int BUFSIZE, withinHead* head)
1326 {
1327  const char* s = " in=\"";
1328  struct within* curWithin = GF_TAILQ_FIRST(head);
1329  int pos = 0;
1330  bool separator = false;
1331  *buf = '\0'; // Terminate for empty content
1332 
1333  while (curWithin != 0) {
1334  int len = strlen(s);
1335  if (pos < BUFSIZE - len - 1) {
1336  memcpy(buf, s, len*sizeof(char));
1337  buf += len;
1338  pos += len;
1339  } else {
1340  break;
1341  }
1342 
1343  if (separator) {
1344  curWithin = GF_TAILQ_NEXT(curWithin, linkWithin);
1345  if (curWithin != 0) {
1346  s = ",";
1347  separator = false;
1348  }
1349  } else {
1350  s = curWithin->val;
1351  separator = true;
1352  }
1353  }
1354 
1355  // Just terminate if we have written something
1356  if (pos > 0) {
1357  memcpy(buf, "\"", 2*sizeof(char));
1358  }
1359 }
1360 
1361 
1373 static int xmlGetOuputLine(struct parmHandle *parmHandle, char *buffer, int size)
1374 {
1375  struct parmOutput *outCtrl = &(parmHandle->outCtrl);
1376  struct parmHeader *conf = parmHandle->conf;
1377  struct section *curSection;
1378  struct param *curParam;
1379  char *s;
1380  const int BUFSIZE = 1024;
1381  char buf[BUFSIZE];
1382  const int INDENTSIZE = 1024;
1383  char indent[INDENTSIZE];
1384  const int INSIZE = 1024;
1385  char in[INSIZE];
1386  const int NUMVALUE = 1024;
1387  char numvalue[NUMVALUE];
1388 
1389  while (1) {
1390  switch (outCtrl->state) {
1391  case 0:
1392  snprintf (buffer, size, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1393  outCtrl->indent = 0;
1394  outCtrl->state = 1;
1395  return 1;
1396 
1397  case 1:
1398  if (conf->dtd == NULL) {
1399  conf->dtd = strdup("params.dtd");
1400  }
1401  if (conf->header == NULL) {
1402  conf->header = strdup("");
1403  }
1404  snprintf (buffer, size, "<!DOCTYPE params SYSTEM \"%s\">\n%s\n", conf->dtd, conf->header);
1405  outCtrl->indent = 0;
1406  outCtrl->state = 2;
1407  return 1;
1408 
1409  case 2: /* Start Params */
1410  outCtrl->curSection = parmHandle->conf->rootSection;
1411  snprintf (buffer, size, "\n<params name=\"%s\">\n", parmHandle->conf->name);
1412  curSection = GF_TAILQ_FIRST (&(outCtrl->curSection->subSectionList));
1413  if (curSection) {
1414  outCtrl->curSection = curSection;
1415  outCtrl->indent += 2;
1416  outCtrl->state = 4;
1417  } else {
1418  outCtrl->state = 3;
1419  }
1420  return 1;
1421 
1422  case 3: /* End Params */
1423  snprintf (buffer, size, "</params>\n");
1424  outCtrl->state = 9;
1425  return 1;
1426 
1427  case 4: /* Parse section attributes list */
1428  outCtrl->curParam = GF_TAILQ_FIRST (&(outCtrl->curSection->paramList));
1429  s = strrchr (outCtrl->curSection->fullName, '/');
1430  if (!s) {
1431  s = outCtrl->curSection->fullName;
1432  } else {
1433  s++;
1434  }
1435 
1436  createIndent(indent, INDENTSIZE, outCtrl->indent);
1437  handleEntities(buf, BUFSIZE, s);
1438  snprintf(buffer, size, "%s<section name=\"%s\">\n", indent, buf);
1439 
1440  outCtrl->indent += 2;
1441  outCtrl->state = 5;
1442  return 1;
1443 
1444  case 5: /* Parse one attribute */
1445  if (!outCtrl->curParam) {
1446  outCtrl->state = 6;
1447  break;
1448  }
1449 
1450  curParam = outCtrl->curParam;
1451  if (curParam->type == P_STR) {
1452  createIndent(indent, INDENTSIZE, outCtrl->indent);
1453  createIn(in, INSIZE, &(curParam->withinList));
1454  handleEntities(buf, BUFSIZE, curParam->value);
1455  snprintf(buffer, size, "%s<attstr name=\"%s\"%s val=\"%s\"/>\n", indent, curParam->name, in, buf);
1456 
1457  outCtrl->curParam = GF_TAILQ_NEXT (curParam, linkParam);
1458  return 1;
1459  } else {
1460  if (curParam->unit) {
1461  if ((curParam->min != curParam->valnum) || (curParam->max != curParam->valnum)) {
1462  snprintf(numvalue, NUMVALUE, " min=\"%g\" max=\"%g\" unit=\"%s\" val=\"%g\"/>\n",
1463  GfParmSI2Unit (curParam->unit, curParam->min),
1464  GfParmSI2Unit (curParam->unit, curParam->max),
1465  curParam->unit,
1466  GfParmSI2Unit (curParam->unit, curParam->valnum)
1467  );
1468  } else {
1469  snprintf(numvalue, NUMVALUE, " unit=\"%s\" val=\"%g\"/>\n",
1470  curParam->unit,
1471  GfParmSI2Unit (curParam->unit, curParam->valnum)
1472  );
1473  }
1474  } else {
1475  if ((curParam->min != curParam->valnum) || (curParam->max != curParam->valnum)) {
1476  snprintf (numvalue, NUMVALUE, " min=\"%g\" max=\"%g\" val=\"%g\"/>\n",
1477  curParam->min,
1478  curParam->max,
1479  curParam->valnum
1480  );
1481  } else {
1482  snprintf (numvalue, NUMVALUE, " val=\"%g\"/>\n", curParam->valnum);
1483  }
1484  }
1485 
1486  createIndent(indent, INDENTSIZE, outCtrl->indent);
1487  snprintf (buffer, size, "%s<attnum name=\"%s\"%s", indent, curParam->name, numvalue);
1488 
1489  outCtrl->curParam = GF_TAILQ_NEXT (curParam, linkParam);
1490  return 1;
1491  }
1492 
1493  case 6: /* Parse sub-section list */
1494  curSection = GF_TAILQ_FIRST (&(outCtrl->curSection->subSectionList));
1495  if (curSection) {
1496  outCtrl->curSection = curSection;
1497  outCtrl->state = 4;
1498  break;
1499  }
1500  outCtrl->state = 7;
1501  break;
1502 
1503  case 7: /* End Section */
1504  outCtrl->indent -= 2;
1505  createIndent(indent, INDENTSIZE, outCtrl->indent);
1506  snprintf (buffer, size, "%s</section>\n\n", indent);
1507  outCtrl->state = 8;
1508  return 1;
1509 
1510  case 8: /* Parse next section at the same level */
1511  curSection = GF_TAILQ_NEXT (outCtrl->curSection, linkSection);
1512  if (curSection) {
1513  outCtrl->curSection = curSection;
1514  outCtrl->state = 4;
1515  break;
1516  }
1517  curSection = outCtrl->curSection->parent;
1518  outCtrl->indent -= 2;
1519  if (curSection->parent) {
1520  outCtrl->curSection = curSection;
1521  createIndent(indent, INDENTSIZE, outCtrl->indent);
1522  snprintf (buffer, size, "%s</section>\n\n", indent);
1523  return 1;
1524  }
1525  outCtrl->state = 3;
1526  break;
1527  case 9:
1528  return 0;
1529  }
1530  }
1531 }
1532 
1533 
1543 int GfParmWriteBuf(void *handle, char *buf, int size)
1544 {
1545  struct parmHandle *parmHandle = (struct parmHandle *)handle;
1546  char line[LINE_SZ];
1547  int len;
1548  int curSize;
1549  char *s;
1550 
1551  if (parmHandle->magic != PARM_MAGIC) {
1552  GfFatal ("gfParmWriteBuf: bad handle (%p)\n", parmHandle);
1553  return 1;
1554  }
1555 
1556  parmHandle->outCtrl.state = 0;
1557  parmHandle->outCtrl.curSection = NULL;
1558  parmHandle->outCtrl.curParam = NULL;
1559  curSize = size;
1560  s = buf;
1561 
1562  while (curSize && xmlGetOuputLine (parmHandle, line, sizeof (line))) {
1563  len = strlen (line);
1564  if (len > curSize) {
1565  len = curSize;
1566  }
1567  memcpy (s, line, len);
1568  s += len;
1569  curSize -= len;
1570  }
1571  buf [size - 1] = 0;
1572 
1573  return 0;
1574 }
1575 
1576 
1584 void GfParmSetDTD(void *parmHandle, char *dtd, char*header)
1585 {
1586  struct parmHandle *handle = (struct parmHandle *)parmHandle;
1587  struct parmHeader *conf = handle->conf;
1588 
1589  if (dtd) {
1590  FREEZ(conf->dtd);
1591  conf->dtd = strdup(dtd);
1592  }
1593 
1594  if (header) {
1595  FREEZ(conf->header);
1596  conf->header = strdup(header);
1597  }
1598 }
1599 
1600 
1610 int GfParmWriteFile(const char *file, void *parmHandle, const char *name)
1611 {
1612  struct parmHandle *handle = (struct parmHandle *)parmHandle;
1613  struct parmHeader *conf = handle->conf;
1614  char line[LINE_SZ];
1615  FILE *fout;
1616 
1617  if (handle->magic != PARM_MAGIC) {
1618  GfFatal ("gfParmWriteFile: bad handle (%p)\n", parmHandle);
1619  return 1;
1620  }
1621 
1622  if (!file) {
1623  file = conf->filename;
1624  if (!file) {
1625  GfError ("gfParmWriteFile: bad file name\n");
1626  return 1;
1627  }
1628  }
1629 
1630  fout = fopen (file, "wb");
1631  if (!fout) {
1632  GfError ("gfParmSetStr: fopen (%s, \"wb\") failed\n", file);
1633  return 1;
1634  }
1635 
1636  if (name) {
1637  FREEZ (conf->name);
1638  conf->name = strdup (name);
1639  }
1640 
1641  handle->outCtrl.state = 0;
1642  handle->outCtrl.curSection = NULL;
1643  handle->outCtrl.curParam = NULL;
1644 
1645  while (xmlGetOuputLine (handle, line, sizeof (line))) {
1646  fputs (line, fout);
1647  }
1648 
1649  GfOut ("GfParmWriteFile: %s file written\n", file);
1650 
1651  fclose (fout);
1652 
1653  return 0;
1654 }
1655 
1656 
1665 int GfParmCreateDirectory(const char *file, void *parmHandle)
1666 {
1667  struct parmHandle *handle = (struct parmHandle *)parmHandle;
1668  struct parmHeader *conf = handle->conf;
1669 
1670  if (handle->magic != PARM_MAGIC) {
1671  GfFatal ("GfParmCreateDirectory: bad handle (%p)\n", parmHandle);
1672  return 1;
1673  }
1674 
1675  if (!file) {
1676  file = conf->filename;
1677  if (!file) {
1678  GfError ("GfParmCreateDirectory: bad file name\n");
1679  return 1;
1680  }
1681  }
1682 
1683  if (GfCreateDirForFile(file) != GF_DIR_CREATED) {
1684  return 1;
1685  }
1686 
1687  return 0;
1688 }
1689 
1690 
1698 void GfParmRemove(void *parmHandle, char *sectionName, char *paramName)
1699 {
1700  struct parmHandle *handle = (struct parmHandle *)parmHandle;
1701  struct parmHeader *conf;
1702 
1703  conf = handle->conf;
1704 
1705  if (handle->magic != PARM_MAGIC) {
1706  GfFatal ("gfParmRemove: bad handle (%p)\n", parmHandle);
1707  return;
1708  }
1709 
1710  removeParamByName(conf, sectionName, paramName);
1711 }
1712 
1713 
1719 static void parmClean(struct parmHeader *conf)
1720 {
1721  struct section *section;
1722 
1723  while ((section = GF_TAILQ_FIRST (&(conf->rootSection->subSectionList))) !=
1725  {
1726  removeSection (conf, section);
1727  }
1728 }
1729 
1730 
1742 {
1743  struct parmHandle *handle = (struct parmHandle *)parmHandle;
1744  struct parmHeader *conf;
1745 
1746  conf = handle->conf;
1747 
1748  if (handle->magic != PARM_MAGIC) {
1749  GfFatal ("gfParmClean: bad handle (%p)\n", parmHandle);
1750  return;
1751  }
1752 
1753  parmClean (conf);
1754 }
1755 
1756 
1765 static void parmReleaseHeader(struct parmHeader *conf)
1766 {
1767  conf->refcount--;
1768  if (conf->refcount > 0) {
1769  return;
1770  }
1771 
1772  GfOut ("parmReleaseHeader: refcount null free \"%s\"\n", conf->filename);
1773 
1774  parmClean (conf);
1775 
1776  freez (conf->filename);
1777  if (conf->paramHash) {
1778  GfHashRelease (conf->paramHash, NULL);
1779  }
1780 
1781  if (conf->sectionHash) {
1782  GfHashRelease (conf->sectionHash, NULL);
1783  }
1784 
1785  freez (conf->rootSection->fullName);
1786  freez (conf->rootSection);
1787  freez (conf->dtd);
1788  freez (conf->name);
1789  freez (conf->header);
1790  freez (conf);
1791 }
1792 
1793 
1803 {
1804  struct parmHeader *conf = parmHandle->conf;
1805 
1806  GfOut ("parmReleaseHandle: release \"%s\" (%p)\n", conf->filename, parmHandle);
1807 
1808  GF_TAILQ_REMOVE (&parmHandleList, parmHandle, linkHandle);
1809  parmHandle->magic = 0;
1810  freez (parmHandle);
1811 
1812  parmReleaseHeader(conf);
1813 }
1814 
1815 
1835 {
1836  struct parmHandle *handle = (struct parmHandle *)parmHandle;
1837 
1838  if (handle->magic != PARM_MAGIC) {
1839  GfFatal ("gfParmReleaseHandle: bad handle (%p)\n", parmHandle);
1840  return;
1841  }
1842 
1843  parmReleaseHandle(handle);
1844 }
1845 
1846 
1859 static void evalUnit(char *unit, tdble *dest, int flg)
1860 {
1861  tdble coeff = 1.0;
1862 
1863  if (strcmp(unit, "m") == 0) return;
1864  if (strcmp(unit, "kg") == 0) return;
1865  if (strcmp(unit, "s") == 0) return;
1866  if (strcmp(unit, "rad") == 0) return;
1867  if (strcmp(unit, "Pa") == 0) return;
1868 
1869  if ((strcmp(unit, "feet") == 0) || (strcmp(unit, "ft") == 0)) {
1870  coeff = 0.304801f; /* m */
1871  } else if (strcmp(unit, "deg") == 0) {
1872  coeff = (float) (M_PI/180.0); /* rad */
1873  } else if ((strcmp(unit, "h") == 0) || (strcmp(unit, "hour") == 0) || (strcmp(unit, "hours") == 0)) {
1874  coeff = 3600.0; /* s */
1875  } else if ((strcmp(unit, "day") == 0) || (strcmp(unit, "days") == 0)) {
1876  coeff = 24*3600.0; /* s */
1877  } else if (strcmp(unit, "km") == 0) {
1878  coeff = 1000.0; /* m */
1879  } else if (strcmp(unit, "mm") == 0) {
1880  coeff = 0.001f; /* m */
1881  } else if (strcmp(unit, "cm") == 0) {
1882  coeff = 0.01f; /* m */
1883  } else if ((strcmp(unit, "in") == 0) || (strcmp(unit, "inch") == 0) || (strcmp(unit, "inches") == 0)) {
1884  coeff = 0.0254f; /* m */
1885  } else if ((strcmp(unit, "lbs") == 0) || (strcmp(unit, "lb") == 0)) {
1886  coeff = 0.45359237f; /* kg */
1887  } else if (strcmp(unit, "lbf") == 0) {
1888  coeff = 0.45359237f*G; /* N (kg*m/s^2) */
1889  } else if ((strcmp(unit, "slug") == 0) || (strcmp(unit, "slugs") == 0)) {
1890  coeff = 14.59484546f; /* kg */
1891  } else if (strcmp(unit, "kPa") == 0) {
1892  coeff = 1000.0; /* Pa */
1893  } else if (strcmp(unit, "MPa") == 0) {
1894  coeff = 1000000.0; /* Pa */
1895  } else if ((strcmp(unit, "PSI") == 0) || (strcmp(unit, "psi") == 0)){
1896  coeff = 6894.76f; /* Pa */
1897  } else if ((strcmp(unit, "rpm") == 0) || (strcmp(unit, "RPM") == 0)) {
1898  coeff = 0.104719755f; /* rad/s */
1899  } else if ((strcmp(unit, "percent") == 0) || (strcmp(unit, "%") == 0)) {
1900  coeff = 0.01f;
1901  } else if ((strcmp(unit, "mph") == 0) || (strcmp(unit, "MPH") == 0)) {
1902  coeff = 0.44704f; /* m/s */
1903  }
1904 
1905  if (flg) {
1906  *dest /= coeff;
1907  } else {
1908  *dest *= coeff;
1909  }
1910 
1911  return;
1912 }
1913 
1914 
1944 tdble GfParmUnit2SI(const char *unit, tdble val)
1945 {
1946  char buf[256];
1947  int idx;
1948  const char *s;
1949  int inv;
1950  tdble dest = val;
1951 
1952  if ((unit == NULL) || (strlen(unit) == 0)) return dest;
1953 
1954  s = unit;
1955  buf[0] = 0;
1956  inv = 0;
1957  idx = 0;
1958 
1959  while (*s != 0) {
1960  switch (*s) {
1961  case '.':
1962  evalUnit(buf, &dest, inv);
1963  buf[0] = 0;
1964  idx = 0;
1965  break;
1966  case '/':
1967  evalUnit(buf, &dest, inv);
1968  buf[0] = 0;
1969  idx = 0;
1970  inv = 1;
1971  break;
1972  case '2':
1973  evalUnit(buf, &dest, inv);
1974  evalUnit(buf, &dest, inv);
1975  buf[0] = 0;
1976  idx = 0;
1977  break;
1978  default:
1979  buf[idx++] = *s;
1980  buf[idx] = 0;
1981  break;
1982  }
1983  s++;
1984  }
1985 
1986  evalUnit(buf, &dest, inv);
1987  return dest;
1988 }
1989 
1990 
1998 tdble GfParmSI2Unit(const char *unit, tdble val)
1999 {
2000  char buf[256];
2001  int idx;
2002  const char *s;
2003  int inv;
2004  tdble dest = val;
2005 
2006  if ((unit == NULL) || (strlen(unit) == 0)) return dest;
2007 
2008  s = unit;
2009  buf[0] = 0;
2010  inv = 1;
2011  idx = 0;
2012 
2013  while (*s != 0) {
2014  switch (*s) {
2015  case '.':
2016  evalUnit(buf, &dest, inv);
2017  buf[0] = 0;
2018  idx = 0;
2019  break;
2020  case '/':
2021  evalUnit(buf, &dest, inv);
2022  buf[0] = 0;
2023  idx = 0;
2024  inv = 0;
2025  break;
2026  case '2':
2027  evalUnit(buf, &dest, inv);
2028  evalUnit(buf, &dest, inv);
2029  buf[0] = 0;
2030  idx = 0;
2031  break;
2032  default:
2033  buf[idx++] = *s;
2034  buf[idx] = 0;
2035  break;
2036  }
2037  s++;
2038  }
2039 
2040  evalUnit(buf, &dest, inv);
2041  return dest;
2042 }
2043 
2044 
2045 
2057 char* GfParmGetName(void *handle)
2058 {
2059  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2060  struct parmHeader *conf = parmHandle->conf;
2061 
2062  if (parmHandle->magic != PARM_MAGIC) {
2063  GfFatal ("GfParmGetName: bad handle (%p)\n", parmHandle);
2064  return NULL;
2065  }
2066 
2067  return conf->name;
2068 }
2069 
2070 
2082 char* GfParmGetFileName(void *handle)
2083 {
2084  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2085  struct parmHeader *conf = parmHandle->conf;
2086 
2087  if (parmHandle->magic != PARM_MAGIC) {
2088  GfFatal ("GfParmGetFileName: bad handle (%p)\n", parmHandle);
2089  return NULL;
2090  }
2091 
2092  return conf->filename;
2093 }
2094 
2095 
2106 int GfParmGetEltNb(void *handle, const char *path)
2107 {
2108  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2109  struct parmHeader *conf = parmHandle->conf;
2110  struct section *section;
2111  int count;
2112 
2113  if (parmHandle->magic != PARM_MAGIC) {
2114  GfFatal ("GfParmGetEltNb: bad handle (%p)\n", parmHandle);
2115  return 0;
2116  }
2117 
2118  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2119  if (!section) {
2120  return 0;
2121  }
2122 
2123  count = 0;
2125  while (section) {
2126  count++;
2127  section = GF_TAILQ_NEXT (section, linkSection);
2128  }
2129 
2130  return count;
2131 }
2132 
2133 
2134 
2148 int GfParmListSeekFirst(void *handle, const char *path)
2149 {
2150  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2151  struct parmHeader *conf = parmHandle->conf;
2152  struct section *section;
2153 
2154  if (parmHandle->magic != PARM_MAGIC) {
2155  GfFatal ("GfParmListSeekFirst: bad handle (%p)\n", parmHandle);
2156  return -1;
2157  }
2158 
2159  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2160  if (!section) {
2161  return -1;
2162  }
2163 
2165 
2166  return 0;
2167 }
2168 
2169 
2184 int GfParmListSeekNext(void *handle, const char *path)
2185 {
2186  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2187  struct parmHeader *conf = parmHandle->conf;
2188  struct section *section;
2189 
2190  if (parmHandle->magic != PARM_MAGIC) {
2191  GfFatal ("GfParmListSeekNext: bad handle (%p)\n", parmHandle);
2192  return -1;
2193  }
2194 
2195  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2196  if ((!section) || (!section->curSubSection)) {
2197  return -1;
2198  }
2199 
2201 
2202  if (section->curSubSection) {
2203  return 0;
2204  }
2205 
2206  return 1;
2207 }
2208 
2209 
2221 int GfParmListClean(void *handle, const char *path)
2222 {
2223  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2224  struct parmHeader *conf = parmHandle->conf;
2225  struct section *listSection;
2226  struct section *section;
2227 
2228  if (parmHandle->magic != PARM_MAGIC) {
2229  GfFatal ("GfParmListSeekNext: bad handle (%p)\n", parmHandle);
2230  return -1;
2231  }
2232 
2233  listSection = (struct section *)GfHashGetStr (conf->sectionHash, path);
2234  if (!listSection) {
2235  GfOut ("GfParmListClean: \"%s\" not found\n", path);
2236  return -1;
2237  }
2238 
2239  while ((section = GF_TAILQ_FIRST (&(listSection->subSectionList))) != NULL) {
2240  removeSection (conf, section);
2241  }
2242 
2243  return 0;
2244 }
2245 
2246 
2268 char* GfParmListGetCurEltName(void *handle, const char *path)
2269 {
2270  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2271  struct parmHeader *conf = parmHandle->conf;
2272  struct section *section;
2273  char *s;
2274 
2275  if (parmHandle->magic != PARM_MAGIC) {
2276  GfFatal ("GfParmListGetCurEltName: bad handle (%p)\n", parmHandle);
2277  return NULL;
2278  }
2279 
2280  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2281  if ((!section) || (!section->curSubSection)) {
2282  return NULL;
2283  }
2284 
2285  s = strrchr(section->curSubSection->fullName, '/');
2286  if (s) {
2287  s++;
2288  return s;
2289  }
2290 
2291  return section->curSubSection->fullName;
2292 }
2293 
2294 
2311 const char* GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
2312 {
2313  struct param *param;
2314  struct parmHandle *handle = (struct parmHandle *)parmHandle;
2315  struct parmHeader *conf = handle->conf;
2316 
2317  if (handle->magic != PARM_MAGIC) {
2318  GfFatal ("gfParmGetStr: bad handle (%p)\n", parmHandle);
2319  return deflt;
2320  }
2321 
2322  param = getParamByName (conf, path, key, 0);
2323  if (!param || !(param->value) || !strlen (param->value) || (param->type != P_STR)) {
2324  return deflt;
2325  }
2326 
2327  return param->value;
2328 }
2329 
2330 
2354 const char* GfParmGetCurStr(void *handle, const char *path, const char *key, const char *deflt)
2355 {
2356  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2357  struct parmHeader *conf = parmHandle->conf;
2358  struct section *section;
2359  struct param *param;
2360 
2361  if (parmHandle->magic != PARM_MAGIC) {
2362  GfFatal ("GfParmGetCurStr: bad handle (%p)\n", parmHandle);
2363  return deflt;
2364  }
2365 
2366  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2367  if ((!section) || (!section->curSubSection)) {
2368  return deflt;
2369  }
2370 
2371  param = getParamByName (conf, section->curSubSection->fullName, key, 0);
2372  if (!param || !(param->value) || !strlen (param->value) || (param->type != P_STR)) {
2373  return deflt;
2374  }
2375 
2376  return param->value;
2377 }
2378 
2379 
2392 tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
2393 {
2394  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2395  struct parmHeader *conf = parmHandle->conf;
2396  struct param *param;
2397 
2398  if (parmHandle->magic != PARM_MAGIC) {
2399  GfFatal ("GfParmGetNum: bad handle (%p)\n", parmHandle);
2400  return deflt;
2401  }
2402 
2403  param = getParamByName (conf, path, key, 0);
2404  if (!param || (param->type != P_NUM)) {
2405  return deflt;
2406  }
2407 
2408  if (unit) {
2409  return GfParmSI2Unit(unit, param->valnum);
2410  }
2411 
2412  return param->valnum;
2413 }
2414 
2415 
2435 tdble GfParmGetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
2436 {
2437  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2438  struct parmHeader *conf = parmHandle->conf;
2439  struct section *section;
2440  struct param *param;
2441 
2442  if (parmHandle->magic != PARM_MAGIC) {
2443  GfFatal ("GfParmGetCurNum: bad handle (%p)\n", parmHandle);
2444  return deflt;
2445  }
2446 
2447  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2448  if ((!section) || (!section->curSubSection)) {
2449  return deflt;
2450  }
2451 
2452  param = getParamByName(conf, section->curSubSection->fullName, key, 0);
2453  if (!param || (param->type != P_NUM)) {
2454  return deflt;
2455  }
2456 
2457  if (unit) {
2458  return GfParmSI2Unit(unit, param->valnum);
2459  }
2460 
2461  return param->valnum;
2462 }
2463 
2464 
2477 int GfParmSetStr(void *handle, const char *path, const char *key, const char *val)
2478 {
2479  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2480  struct parmHeader *conf = parmHandle->conf;
2481  struct param *param;
2482 
2483  if (parmHandle->magic != PARM_MAGIC) {
2484  GfFatal ("GfParmSetStr: bad handle (%p)\n", parmHandle);
2485  return -1;
2486  }
2487 
2488  if (!val || !strlen (val)) {
2489  /* Remove the entry */
2490  removeParamByName (conf, path, key);
2491  return 0;
2492  }
2493 
2494  param = getParamByName (conf, path, key, PARAM_CREATE);
2495  if (!param) {
2496  return -1;
2497  }
2498 
2499  param->type = P_STR;
2500  freez (param->value);
2501  param->value = strdup (val);
2502 
2503  if (!param->value) {
2504  GfError ("gfParmSetStr: strdup (%s) failed\n", val);
2505  removeParamByName (conf, path, key);
2506  return -1;
2507  }
2508 
2509  return 0;
2510 }
2511 
2512 
2532 int GfParmSetCurStr(void *handle, const char *path, const char *key, const char *val)
2533 {
2534  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2535  struct parmHeader *conf = parmHandle->conf;
2536  struct section *section;
2537  struct param *param;
2538 
2539  if (parmHandle->magic != PARM_MAGIC) {
2540  GfFatal ("GfParmSetCurStr: bad handle (%p)\n", parmHandle);
2541  return -1;
2542  }
2543 
2544  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2545  if ((!section) || (!section->curSubSection)) {
2546  return -1;
2547  }
2548 
2549  if (!val || !strlen (val)) {
2550  /* Remove the entry */
2552  return 0;
2553  }
2554 
2556  if (!param) {
2557  return -1;
2558  }
2559 
2560  param->type = P_STR;
2561  freez (param->value);
2562  param->value = strdup (val);
2563  if (!param->value) {
2564  GfError ("gfParmSetStr: strdup (%s) failed\n", val);
2566  return -1;
2567  }
2568 
2569  return 0;
2570 }
2571 
2572 
2586 int GfParmSetNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
2587 {
2588  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2589  struct parmHeader *conf = parmHandle->conf;
2590  struct param *param;
2591 
2592  if (parmHandle->magic != PARM_MAGIC) {
2593  GfFatal ("GfParmSetNum: bad handle (%p)\n", parmHandle);
2594  return -1;
2595  }
2596 
2597  param = getParamByName (conf, path, key, PARAM_CREATE);
2598  if (!param) {
2599  return -11;
2600  }
2601 
2602  param->type = P_NUM;
2603  FREEZ (param->unit);
2604  if (unit) {
2605  param->unit = strdup (unit);
2606  }
2607 
2608  val = GfParmUnit2SI (unit, val);
2609  param->valnum = val;
2610  param->min = val;
2611  param->max = val;
2612 
2613  return 0;
2614 }
2615 
2616 
2629 int GfParmSetNumEx(void *handle, const char *path, const char *key, const char *unit, tdble val, tdble min, tdble max)
2630 {
2631  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2632  struct parmHeader *conf = parmHandle->conf;
2633  struct param *param;
2634 
2635  if (parmHandle->magic != PARM_MAGIC) {
2636  GfFatal ("GfParmSetNumEx: bad handle (%p)\n", parmHandle);
2637  return -1;
2638  }
2639 
2640  param = getParamByName (conf, path, key, PARAM_CREATE);
2641  if (!param) {
2642  return -1;
2643  }
2644 
2645  param->type = P_NUM;
2646  FREEZ (param->unit);
2647  if (unit) {
2648  param->unit = strdup (unit);
2649  }
2650 
2651  param->valnum = GfParmUnit2SI (unit, val);
2652  param->min = GfParmUnit2SI (unit, min);
2653  param->max = GfParmUnit2SI (unit, max);
2654 
2655  return 0;
2656 }
2657 
2658 
2679 int GfParmSetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
2680 {
2681  struct parmHandle *parmHandle = (struct parmHandle *)handle;
2682  struct parmHeader *conf = parmHandle->conf;
2683  struct section *section;
2684  struct param *param;
2685 
2686  if (parmHandle->magic != PARM_MAGIC) {
2687  GfFatal ("GfParmSetCurNum: bad handle (%p)\n", parmHandle);
2688  return -1;
2689  }
2690 
2691  section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2692  if ((!section) || (!section->curSubSection)) {
2693  return -1;
2694  }
2695 
2697  if (!param) {
2698  return -1;
2699  }
2700 
2701  param->type = P_NUM;
2702  FREEZ (param->unit);
2703  if (unit) {
2704  param->unit = strdup (unit);
2705  }
2706 
2707  val = GfParmUnit2SI (unit, val);
2708  param->valnum = val;
2709  param->min = val;
2710  param->max = val;
2711 
2712  return 0;
2713 }
2714 
2715 
2716 
2728 int GfParmCheckHandle(void *ref, void *tgt)
2729 {
2730  struct parmHandle *parmHandleRef = (struct parmHandle *)ref;
2731  struct parmHandle *parmHandle = (struct parmHandle *)tgt;
2732  struct parmHeader *confRef = parmHandleRef->conf;
2733  struct parmHeader *conf = parmHandle->conf;
2734  struct section *curSectionRef;
2735  struct section *nextSectionRef;
2736  struct param *curParamRef;
2737  struct param *curParam;
2738  struct within *curWithinRef;
2739  int found;
2740  int error = 0;
2741 
2742  if ((parmHandleRef->magic != PARM_MAGIC) || (parmHandle->magic != PARM_MAGIC)) {
2743  GfFatal ("GfParmCheckHandle: bad handle (%p)\n", parmHandle);
2744  return -1;
2745  }
2746 
2747  /* Traverse all the reference tree */
2748  curSectionRef = GF_TAILQ_FIRST (&(confRef->rootSection->subSectionList));
2749  while (curSectionRef) {
2750  curParamRef = GF_TAILQ_FIRST (&(curSectionRef->paramList));
2751  while (curParamRef) {
2752  /* compare params */
2753  curParam = getParamByName (conf, curSectionRef->fullName, curParamRef->name, 0);
2754  if (curParam) {
2755  if (curParamRef->type != curParam->type) {
2756  GfError("GfParmCheckHandle: type mismatch for parameter \"%s\" in (\"%s\" - \"%s\")\n",
2757  curParamRef->fullName, conf->name, conf->filename);
2758  error = -1;
2759  } else if (curParamRef->type == P_NUM) {
2760  if ((curParam->valnum < curParamRef->min) || (curParam->valnum > curParamRef->max)) {
2761  GfError("GfParmCheckHandle: parameter \"%s\" out of bounds: min:%g max:%g val:%g in (\"%s\" - \"%s\")\n",
2762  curParamRef->fullName, curParamRef->min, curParamRef->max, curParam->valnum, conf->name, conf->filename);
2763  }
2764  } else {
2765  curWithinRef = GF_TAILQ_FIRST (&(curParamRef->withinList));
2766  found = 0;
2767  while (!found && curWithinRef) {
2768  if (!strcmp (curWithinRef->val, curParam->value)) {
2769  found = 1;
2770  } else {
2771  curWithinRef = GF_TAILQ_NEXT (curWithinRef, linkWithin);
2772  }
2773  }
2774  if (!found && strcmp (curParamRef->value, curParam->value)) {
2775  GfError("GfParmCheckHandle: parameter \"%s\" value:\"%s\" not allowed in (\"%s\" - \"%s\")\n",
2776  curParamRef->fullName, curParam->value, conf->name, conf->filename);
2777  }
2778  }
2779  }
2780  curParamRef = GF_TAILQ_NEXT (curParamRef, linkParam);
2781  }
2782 
2783  nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
2784  while (!nextSectionRef) {
2785  nextSectionRef = curSectionRef->parent;
2786  if (!nextSectionRef) {
2787  /* Reached the root */
2788  break;
2789  }
2790  curSectionRef = nextSectionRef;
2791  nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
2792  }
2793  curSectionRef = nextSectionRef;
2794  }
2795 
2796  return error;
2797 }
2798 
2799 
2814 static void insertParamMerge(struct parmHandle *parmHandle, char *path, struct param *paramRef, struct param *param)
2815 {
2816  struct parmHeader *conf = parmHandle->conf;
2817  struct param *paramNew;
2818  struct within *withinRef;
2819  struct within *within;
2820  tdble num;
2821  char *str;
2822 
2823  paramNew = getParamByName (conf, path, param->name, PARAM_CREATE);
2824  if (!paramNew) {
2825  return;
2826  }
2827 
2828  if (param->type == P_NUM) {
2829  paramNew->type = P_NUM;
2830  FREEZ (paramNew->unit);
2831  if (param->unit) {
2832  paramNew->unit = strdup (param->unit);
2833  }
2834 
2835  if (param->min < paramRef->min) {
2836  num = paramRef->min;
2837  } else {
2838  num = param->min;
2839  }
2840  paramNew->min = num;
2841 
2842  if (param->max > paramRef->max) {
2843  num = paramRef->max;
2844  } else {
2845  num = param->max;
2846  }
2847  paramNew->max = num;
2848  num = param->valnum;
2849 
2850  if (num < paramNew->min) {
2851  num = paramNew->min;
2852  }
2853 
2854  if (num > paramNew->max) {
2855  num = paramNew->max;
2856  }
2857  paramNew->valnum = num;
2858  } else {
2859  paramNew->type = P_STR;
2860  FREEZ (paramNew->value);
2862 
2863  while (within) {
2864  withinRef = GF_TAILQ_FIRST (&(paramRef->withinList));
2865  while (withinRef) {
2866  if (!strcmp (withinRef->val, within->val)) {
2867  addWithin (paramNew, within->val);
2868  break;
2869  }
2870  withinRef = GF_TAILQ_NEXT (withinRef, linkWithin);
2871  }
2872  within = GF_TAILQ_NEXT (within, linkWithin);
2873  }
2874  str = NULL;
2875  withinRef = GF_TAILQ_FIRST (&(paramRef->withinList));
2876 
2877  while (withinRef) {
2878  if (!strcmp (withinRef->val, param->value)) {
2879  str = param->value;
2880  break;
2881  }
2882  withinRef = GF_TAILQ_NEXT (withinRef, linkWithin);
2883  }
2884 
2885  if (!str) {
2886  str = paramRef->value;
2887  }
2888 
2889  paramNew->value = strdup (str);
2890  }
2891 }
2892 
2893 
2906 static void insertParam(struct parmHandle *parmHandle, char *path, struct param *param)
2907 {
2908  struct parmHeader *conf = parmHandle->conf;
2909  struct param *paramNew;
2910  struct within *within;
2911 
2912  paramNew = getParamByName (conf, path, param->name, PARAM_CREATE);
2913  if (!paramNew) {
2914  return;
2915  }
2916 
2917  if (param->type == P_NUM) {
2918  paramNew->type = P_NUM;
2919  FREEZ (paramNew->unit);
2920  if (param->unit) {
2921  paramNew->unit = strdup (param->unit);
2922  }
2923  paramNew->valnum = param->valnum;
2924  paramNew->min = param->min;
2925  paramNew->max = param->max;
2926  } else {
2927  paramNew->type = P_STR;
2928  FREEZ (paramNew->value);
2929  paramNew->value = strdup (param->value);
2931  while (within) {
2932  addWithin (paramNew, within->val);
2933  within = GF_TAILQ_NEXT (within, linkWithin);
2934  }
2935  }
2936 }
2937 
2938 
2962 void *GfParmMergeHandles(void *ref, void *tgt, int mode)
2963 {
2964  struct parmHandle *parmHandleRef = (struct parmHandle *)ref;
2965  struct parmHandle *parmHandleTgt = (struct parmHandle *)tgt;
2966  struct parmHandle *parmHandleOut;
2967  struct parmHeader *confRef = parmHandleRef->conf;
2968  struct parmHeader *confTgt = parmHandleTgt->conf;
2969  struct parmHeader *confOut;
2970  struct section *curSectionRef;
2971  struct section *nextSectionRef;
2972  struct section *curSectionTgt;
2973  struct section *nextSectionTgt;
2974  struct param *curParamRef;
2975  struct param *curParamTgt;
2976  const unsigned long parmHandleSize = sizeof (struct parmHandle);
2977 
2978  GfOut ("Merging \"%s\" and \"%s\" (%s - %s)\n", confRef->filename, confTgt->filename, ((mode & GFPARM_MMODE_SRC) ? "SRC" : ""), ((mode & GFPARM_MMODE_DST) ? "DST" : ""));
2979 
2980  if (parmHandleRef->magic != PARM_MAGIC) {
2981  GfFatal ("GfParmMergeHandles: bad handle (%p)\n", parmHandleRef);
2982  return NULL;
2983  }
2984  if (parmHandleTgt->magic != PARM_MAGIC) {
2985  GfFatal ("GfParmMergeHandles: bad handle (%p)\n", parmHandleTgt);
2986  return NULL;
2987  }
2988 
2989  /* Conf Header creation */
2990  confOut = createParmHeader ("");
2991  if (!confOut) {
2992  GfError ("gfParmReadBuf: conf header creation failed\n");
2993  return NULL;
2994  }
2995 
2996  /* Handle creation */
2997  parmHandleOut = (struct parmHandle *) calloc (1, parmHandleSize);
2998  if (!parmHandleOut) {
2999  GfError ("gfParmReadBuf: calloc (1, %lu) failed\n", parmHandleSize);
3000  parmReleaseHeader (confOut);
3001  return NULL;
3002  }
3003 
3004  parmHandleOut->magic = PARM_MAGIC;
3005  parmHandleOut->conf = confOut;
3006  parmHandleOut->flag = PARM_HANDLE_FLAG_PRIVATE;
3007 
3008  if (mode & GFPARM_MMODE_SRC) {
3009  /* Traverse all the reference tree */
3010  curSectionRef = GF_TAILQ_FIRST (&(confRef->rootSection->subSectionList));
3011  while (curSectionRef) {
3012  curParamRef = GF_TAILQ_FIRST (&(curSectionRef->paramList));
3013  while (curParamRef) {
3014  /* compare params */
3015  curParamTgt = getParamByName (confTgt, curSectionRef->fullName, curParamRef->name, 0);
3016  if (curParamTgt) {
3017  insertParamMerge (parmHandleOut, curSectionRef->fullName, curParamRef, curParamTgt);
3018  } else {
3019  insertParam (parmHandleOut, curSectionRef->fullName, curParamRef);
3020  }
3021  curParamRef = GF_TAILQ_NEXT (curParamRef, linkParam);
3022  }
3023  nextSectionRef = GF_TAILQ_FIRST (&(curSectionRef->subSectionList));
3024  if (nextSectionRef) {
3025  curSectionRef = nextSectionRef;
3026  } else {
3027  nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
3028  while (!nextSectionRef) {
3029  nextSectionRef = curSectionRef->parent;
3030  if (!nextSectionRef) {
3031  /* Reached the root */
3032  break;
3033  }
3034  curSectionRef = nextSectionRef;
3035  nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
3036  }
3037  curSectionRef = nextSectionRef;
3038  }
3039  }
3040  }
3041 
3042  if (mode & GFPARM_MMODE_DST) {
3043  /* Traverse all the target tree */
3044  curSectionTgt = GF_TAILQ_FIRST (&(confTgt->rootSection->subSectionList));
3045  while (curSectionTgt) {
3046  curParamTgt = GF_TAILQ_FIRST (&(curSectionTgt->paramList));
3047  while (curParamTgt) {
3048  /* compare params */
3049  curParamRef = getParamByName (confRef, curSectionTgt->fullName, curParamTgt->name, 0);
3050  if (curParamRef) {
3051  insertParamMerge (parmHandleOut, curSectionTgt->fullName, curParamRef, curParamTgt);
3052  } else {
3053  insertParam (parmHandleOut, curSectionTgt->fullName, curParamTgt);
3054  }
3055  curParamTgt = GF_TAILQ_NEXT (curParamTgt, linkParam);
3056  }
3057 
3058  nextSectionTgt = GF_TAILQ_FIRST (&(curSectionTgt->subSectionList));
3059  if (nextSectionTgt) {
3060  curSectionTgt = nextSectionTgt;
3061  } else {
3062  nextSectionTgt = GF_TAILQ_NEXT (curSectionTgt, linkSection);
3063  while (!nextSectionTgt) {
3064  nextSectionTgt = curSectionTgt->parent;
3065  if (!nextSectionTgt) {
3066  /* Reached the root */
3067  break;
3068  }
3069  curSectionTgt = nextSectionTgt;
3070  nextSectionTgt = GF_TAILQ_NEXT (curSectionTgt, linkSection);
3071  }
3072  curSectionTgt = nextSectionTgt;
3073  }
3074  }
3075  }
3076 
3077  if (mode & GFPARM_MMODE_RELSRC) {
3078  GfParmReleaseHandle(ref);
3079  }
3080 
3081  if (mode & GFPARM_MMODE_RELDST) {
3082  GfParmReleaseHandle(tgt);
3083  }
3084 
3085  GF_TAILQ_INSERT_HEAD (&parmHandleList, parmHandleOut, linkHandle);
3086 
3087  return (void*)parmHandleOut;
3088 }
3089 
3090 
3101 int GfParmGetNumBoundaries(void *handle, const char *path, const char *key, tdble *min, tdble *max)
3102 {
3103  struct parmHandle *parmHandle = (struct parmHandle *)handle;
3104  struct parmHeader *conf = parmHandle->conf;
3105  struct param *param;
3106 
3107  if (parmHandle->magic != PARM_MAGIC) {
3108  GfFatal ("GfParmGetNumBoundaries: bad handle (%p)\n", parmHandle);
3109  return -1;
3110  }
3111 
3112  param = getParamByName (conf, path, key, 0);
3113  if (!param || (param->type != P_NUM)) {
3114  return -1;
3115  }
3116 
3117  *min = param->min;
3118  *max = param->max;
3119 
3120  return 0;
3121 }
3122 
3123 
struct parmHeader * conf
Header of the parameter set.
Definition: params.cpp:128
int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser)
void XMLPARSEAPI XML_SetUserData(XML_Parser parser, void *userData)
struct withinHead withinList
Linked list containing the options for legal string values.
Definition: params.cpp:73
static int myStrcmp(const void *s1, const void *s2)
Definition: params.cpp:662
#define GF_HASH_TYPE_STR
String key based hash table.
Definition: tgf.h:606
#define GfError
Definition: tgf.h:351
struct section * curSection
Current section, for iterations, see GfParmListSeekFirst and GfParmListSeekNext.
Definition: params.cpp:131
int GfParmSetStr(void *handle, const char *path, const char *key, const char *val)
Set a string parameter in the parameter set handle.
Definition: params.cpp:2477
static void evalUnit(char *unit, tdble *dest, int flg)
Support function to multiply or divide dest with unit conversion factor.
Definition: params.cpp:1859
static void removeParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName)
Helper function to remove a parameter with given name paramName.
Definition: params.cpp:254
tdble GfParmUnit2SI(const char *unit, tdble val)
Convert a value given in unit to SI.
Definition: params.cpp:1944
static void GfFatal(const char *fmt,...)
Definition: tgf.h:339
char * unit
Unit, see GfParmUnit2SI for supported units.
Definition: params.cpp:70
int GfParmCheckHandle(void *ref, void *tgt)
Check the values in the parameter set tgt against the min/max/within definitions in the ref parameter...
Definition: params.cpp:2728
GF_TAILQ_ENTRY(struct within) linkWithin
Link to next entry.
void * GfParmReadFile(const char *file, int mode)
Read parameter set from file and return handle to parameter set.
Definition: params.cpp:1157
void XMLPARSEAPI XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler)
static int xmlGetOuputLine(struct parmHandle *parmHandle, char *buffer, int size)
Helper function to output one line of XML generated from the given parameter set. ...
Definition: params.cpp:1373
Scalar max(Scalar x, Scalar y)
Definition: Basic.h:50
int GfParmListSeekNext(void *handle, const char *path)
Go the the next subsection element in the parameter set handle.
Definition: params.cpp:2184
static void xmlStartElement(void *userData, const char *name, const char **atts)
Helper function to process opening XML elements.
Definition: params.cpp:698
static char * getFullName(const char *sectionName, const char *paramName)
Helper function to get the full name of a parameter (full name: "sectionName/paramName").
Definition: params.cpp:187
void * GfParmMergeHandles(void *ref, void *tgt, int mode)
Merge two parameter sets into a new one, either containing parameters from ref, tgt or from both sets...
Definition: params.cpp:2962
char * name
Name of the data.
Definition: params.cpp:100
static tdble getValNumFromStr(const char *str)
Helper function to parse number.
Definition: params.cpp:674
#define GF_TAILQ_INSERT_TAIL(head, elm, field)
Insert an element at the tail.
Definition: tgf.h:511
static struct section * addSection(struct parmHeader *conf, const char *sectionName)
Helper function to add a section to a parameter set.
Definition: params.cpp:481
struct parmOutput outCtrl
Ouput control structure used for serializing parameter set into XML.
Definition: params.cpp:132
#define FREEZ(x)
Definition: tgf.h:60
Ouput control structure used for serializing parameter set into XML.
Definition: params.cpp:114
int GfParmSetNumEx(void *handle, const char *path, const char *key, const char *unit, tdble val, tdble min, tdble max)
Set a numerical parameter in the parameter set handle including min and max.
Definition: params.cpp:2629
GF_TAILQ_ENTRY(struct section) linkSection
Next section at the same level.
static char * handleEntities(char *buf, const int BUFSIZE, const char *val)
Helper function to convert the input line given in val into proper XML notation, the output goes into...
Definition: params.cpp:1254
#define PARM_HANDLE_FLAG_PRIVATE
Definition: params.cpp:109
void GfParmReleaseHandle(void *parmHandle)
Release given parameter set handle parmHandle.
Definition: params.cpp:1834
#define PARM_MAGIC
Definition: params.cpp:94
tdble GfParmGetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle based on subsection iteration.
Definition: params.cpp:2435
void * paramHash
Hash table for parameter access.
Definition: params.cpp:105
static struct parmHeader * createParmHeader(const char *file)
Helper function to create header for parameter set handle.
Definition: params.cpp:582
#define LINE_SZ
Definition: params.cpp:42
#define GF_TAILQ_INSERT_HEAD(head, elm, field)
Insert an element at the head.
Definition: tgf.h:499
Section header structure.
Definition: params.cpp:83
void GfHashRelease(void *hash, tfHashFree hashFree)
Release a hash table.
Definition: hash.cpp:353
#define PARM_HANDLE_FLAG_PARSE_ERROR
Definition: params.cpp:110
void GfParmSetDTD(void *parmHandle, char *dtd, char *header)
Set the dtd path and header.
Definition: params.cpp:1584
static int parserXmlInit(struct parmHandle *parmHandle)
Helper function to set up XML parser in parmHandle.
Definition: params.cpp:1072
char * filename
Name of the output file.
Definition: params.cpp:119
static void createIn(char *buf, const int BUFSIZE, withinHead *head)
Helper function to support the serialization into the XML of the "within" attribute.
Definition: params.cpp:1325
int GfParmWriteFile(const char *file, void *parmHandle, const char *name)
Write parameter set into file.
Definition: params.cpp:1610
const void * GfHashGetStr(void *hash, const char *key)
Get the user data associated with a string key.
Definition: hash.cpp:245
void XMLPARSEAPI XML_ParserFree(XML_Parser parser)
tdble GfParmSI2Unit(const char *unit, tdble val)
Convert a value from SI to given unit.
Definition: params.cpp:1998
int GfParmCreateDirectory(const char *file, void *parmHandle)
Create directory for parameter set handle if it does not yet exist.
Definition: params.cpp:1665
char * fullName
Name of the parameter including the full section name (&#39;/&#39; separated)
Definition: params.cpp:66
tdble valnum
Numeric value of the parameter.
Definition: params.cpp:68
void GfParmInit(void)
Parameter set library API initialization, set up parameter set handle cache.
Definition: params.cpp:158
const char * GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle.
Definition: params.cpp:2311
#define GFPARM_MMODE_RELDST
release tgt after the merge
Definition: tgf.h:316
static void parmReleaseHeader(struct parmHeader *conf)
Helper function to release the parameter set if the reference counter is 0.
Definition: params.cpp:1765
char * filename
Name of the configuration file.
Definition: params.cpp:99
char * GfParmListGetCurEltName(void *handle, const char *path)
Get current subsection name of the parameter set handle during subsection iteration.
Definition: params.cpp:2268
static struct parmHeader * getSharedHeader(const char *file, int mode)
Helper function for looking up parameter sets in the cache.
Definition: params.cpp:546
int GfParmListSeekFirst(void *handle, const char *path)
Go the the first subsection element in the parameter set handle.
Definition: params.cpp:2148
static void parmClean(struct parmHeader *conf)
Helper function to release the parameter set content.
Definition: params.cpp:1719
void * GfHashCreate(int type)
Create a new hash table.
Definition: hash.cpp:98
int GfParmGetNumBoundaries(void *handle, const char *path, const char *key, tdble *min, tdble *max)
Get the min and max of a numerical parameter from the parameter set handle.
Definition: params.cpp:3101
tdble max
Maximum for numeric value.
Definition: params.cpp:72
int XMLPARSEAPI XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
float tdble
Floating point type used in TORCS.
Definition: tgf.h:48
#define GfOut
Definition: tgf.h:373
#define XML_GetUserData(parser)
Definition: xmlparse.h:276
static struct param * addParam(struct parmHeader *conf, struct section *section, const char *paramName, const char *value)
Helper function to add parameter, does not check for duplicated name.
Definition: params.cpp:346
struct section * curSubSection
Current subsection, for iterations, see GfParmListSeekFirst and GfParmListSeekNext.
Definition: params.cpp:89
int magic
Magic number (to detect wrong type casts and such)
Definition: params.cpp:127
GF_TAILQ_HEAD(withinHead, struct within)
static Point p[4]
Definition: Convex.cpp:54
enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser)
#define GFPARM_RMODE_REREAD
reread the parameters from file and release the previous ones
Definition: tgf.h:266
The Gaming Framework API.
Parameter set handle structure, multiple handles can reference the same parameter set...
Definition: params.cpp:125
void GfParmShutdown(void)
Parameter set library API shutdown, removes parameter set handle cache.
Definition: params.cpp:167
#define GF_TAILQ_INIT(head)
Head initialization (Mandatory)
Definition: tgf.h:485
int GfParmSetCurStr(void *handle, const char *path, const char *key, const char *val)
Set a string parameter in the parameter set handle based on subsection iteration. ...
Definition: params.cpp:2532
void * sectionHash
Hash table for section access.
Definition: params.cpp:106
XML_Parser XMLPARSEAPI XML_ParserCreate(const XML_Char *encoding)
char * header
Optional header (comment, xsl...)
Definition: params.cpp:102
struct paramHead paramList
List of the parameters in this section.
Definition: params.cpp:86
Parameter header structure, a parameter can either carry a numeric or a string value, numeric value is constraint by min and max, string value by options in within.
Definition: params.cpp:63
static void insertParamMerge(struct parmHandle *parmHandle, char *path, struct param *paramRef, struct param *param)
Helper function to merge a parameter into a parameter set.
Definition: params.cpp:2814
static int parseXml(struct parmHandle *parmHandle, char *buf, int len, int done)
Helper function to parse one line of XML.
Definition: params.cpp:1049
const XML_LChar XMLPARSEAPI * XML_ErrorString(int code)
const void * GfHashRemStr(void *hash, char *key)
Remove an element with a string key from a hash table.
Definition: hash.cpp:219
#define GFPARM_RMODE_PRIVATE
Definition: tgf.h:268
void GfParmClean(void *parmHandle)
Clean all the parameters of a parameter set.
Definition: params.cpp:1741
#define GF_TAILQ_FIRST(head)
First element of a TAILQ.
Definition: tgf.h:464
int GfParmSetNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
Set a numerical parameter in the parameter set handle.
Definition: params.cpp:2586
static struct param * getParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName, int flag)
Helper function to get (or create) a parameter by name.
Definition: params.cpp:213
char * name
Name of the parameter.
Definition: params.cpp:65
static struct parmHead parmHandleList
Definition: params.cpp:139
tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle.
Definition: params.cpp:2392
static void xmlEndElement(void *userData, const XML_Char *name)
Helper function to process closing XML elements.
Definition: params.cpp:943
#define GF_TAILQ_REMOVE(head, elm, field)
Remove an element.
Definition: tgf.h:541
Scalar min(Scalar x, Scalar y)
Definition: Basic.h:49
int GfParmSetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
Set a numerical parameter in the parameter set handle based on subsection iteration.
Definition: params.cpp:2679
int GfParmListClean(void *handle, const char *path)
Remove all the subsections in a section in the parameter set handle.
Definition: params.cpp:2221
char * dtd
Optional DTD location.
Definition: params.cpp:101
GF_TAILQ_ENTRY(struct parmHandle) linkHandle
Next configuration handle.
int indent
Keep track of indentation.
Definition: params.cpp:120
struct section * parent
Parent section.
Definition: params.cpp:90
#define GF_TAILQ_END(head)
End of a TAILQ.
Definition: tgf.h:470
#define GFPARM_MMODE_RELSRC
release ref after the merge
Definition: tgf.h:315
int GfHashAddStr(void *hash, const char *key, const void *data)
Add an element with a string key to a hash table.
Definition: hash.cpp:170
struct param * curParam
Current parameter.
Definition: params.cpp:118
void GfParmRemove(void *parmHandle, char *sectionName, char *paramName)
Remove a parameter from a parameter set.
Definition: params.cpp:1698
struct section * curSection
Current section.
Definition: params.cpp:117
char * val
Value of within option.
Definition: params.cpp:51
int state
Internal state.
Definition: params.cpp:116
#define GF_TAILQ_NEXT(elm, field)
Next element of a TAILQ.
Definition: tgf.h:467
void * GfParmReadBuf(char *buffer)
Read parameter set from memory buffer and return handle to parameter set.
Definition: params.cpp:1091
int GfParmGetEltNb(void *handle, const char *path)
Count the number of subsections in a section in the parameter set handle.
Definition: params.cpp:2106
static void removeParam(struct parmHeader *conf, struct section *section, struct param *param)
Helper function to remove given parameter.
Definition: params.cpp:316
int type
Type, either P_NUM or P_STR.
Definition: params.cpp:69
char XML_Char
Definition: xmlparse.h:60
char * GfParmGetFileName(void *handle)
Get the filename property of the parameter set handle.
Definition: params.cpp:2082
static struct section * getParent(struct parmHeader *conf, const char *sectionName)
Helper function to get (or create if not found) parent section of section given in sectionName...
Definition: params.cpp:441
#define GFPARM_MMODE_DST
use tgt and verify ref parameters
Definition: tgf.h:314
char * value
String value of the parameter.
Definition: params.cpp:67
static void cleanUnusedSection(struct parmHeader *conf, struct section *section)
Helper function to clean up unused (empty) sections starting with given section.
Definition: params.cpp:291
static void createIndent(char *buf, const int BUFSIZE, const int blanks)
Helper function for indentation in the XML.
Definition: params.cpp:1307
char * fullName
Name of the section including full path (&#39;/&#39; separated)
Definition: params.cpp:85
static void removeSection(struct parmHeader *conf, struct section *section)
Helper function to remove a section and its contents (subsections, elements).
Definition: params.cpp:411
XML_Parser parser
Parser.
Definition: params.cpp:130
void * XML_Parser
Definition: xmlparse.h:33
static void parmReleaseHandle(struct parmHandle *parmHandle)
Helper function to release the handle and eventually the referenced parameter set (if the reference c...
Definition: params.cpp:1802
Configuration header structure.
Definition: params.cpp:97
static void addWithin(struct param *curParam, char *s1)
Helper function to add "within" options to parameter curParam.
Definition: params.cpp:648
Structure to hold linked list of within options.
Definition: params.cpp:49
#define P_STR
Definition: params.cpp:46
static void * parmHandle
#define PARAM_CREATE
Definition: params.cpp:43
int GfParmWriteBuf(void *handle, char *buf, int size)
Write a parameter set into a memory buffer.
Definition: params.cpp:1543
void XMLPARSEAPI XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end)
int refcount
Use counter (number of conf handle)
Definition: params.cpp:103
const char * GfParmGetCurStr(void *handle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle based on subsection iteration.
Definition: params.cpp:2354
int GfCreateDirForFile(const char *filenameandpath)
Create directory for given file path recursively, so all missing parent directories are created as we...
Definition: tgf.cpp:364
GF_TAILQ_ENTRY(struct param) linkParam
Next parameter in the same section.
struct section * rootSection
List of sections at the first level.
Definition: params.cpp:104
char * GfParmGetName(void *handle)
Get the name property of the parameter set handle.
Definition: params.cpp:2057
struct sectionHead subSectionList
List of sub-sections (linked by linkSection)
Definition: params.cpp:88
tdble min
Minimum for numeric value.
Definition: params.cpp:71
#define P_NUM
Definition: params.cpp:45
static int xmlExternalEntityRefHandler(XML_Parser mainparser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId)
Helper function to handle external XML entities (XML referencing over multiple files/URI&#39;s).
Definition: params.cpp:973
#define GFPARM_RMODE_CREAT
Create the file if doesn&#39;t exist.
Definition: tgf.h:267
const tdble G
m/s/s
Definition: tgf.h:70
#define GF_DIR_CREATED
Definition: tgf.h:623
int flag
Flag (PARM_HANDLE_FLAG_PARSE_ERROR, PARM_HANDLE_FLAG_PRIVATE)
Definition: params.cpp:129
XML_Parser XMLPARSEAPI XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *encoding)
#define freez
Definition: tgf.h:67
#define GFPARM_MMODE_SRC
use ref and modify existing parameters with tgt
Definition: tgf.h:313
static void insertParam(struct parmHandle *parmHandle, char *path, struct param *param)
Helper function to insert a parameter into a parameter set.
Definition: params.cpp:2906