txt_configfile.c 5.15 KB
Newer Older
Philip Carns's avatar
Philip Carns committed
1 2 3 4 5 6
/*
 * Copyright (C) 2013 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */

7 8
#include <assert.h>
#include <stdio.h>
9
#include "txt_configfile.h"
10
#include "configglue.h"
Philip Carns's avatar
Philip Carns committed
11 12
#include "src/modelconfig/configparser.h"
#include "src/modelconfig/configlex.h"
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#include "configstoreadapter.h"

#define MAX_CONFIG_SIZE 10*1024*1024

/* BISON doesn't declare the prototype? */
int cfgp_parse (yyscan_t * scanner, ParserParams * param);

static void show_indent (FILE * f, unsigned int ind)
{
   unsigned int i;

   for (i=0; i<ind; ++i)
      fprintf (f, " "); 
}

static inline int mymin (int v1, int v2)
{
   return (v1 < v2 ?  v1 : v2);
}

33
static int dump_section (FILE * f, struct ConfigVTable * h, SectionHandle s, unsigned
34 35
      int indent);

36
static int dump_entry (FILE * f, struct ConfigVTable * h, SectionHandle s, 
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
      unsigned int indent, const SectionEntry * entry)
{
   int ret = 1;
   switch (entry->type)
   {
      case SE_SECTION:
         {
            SectionHandle newsec;

            fprintf (f, "%s { \n", entry->name);

            ret = mymin(ret, cf_openSection (h, s, entry->name, &newsec));
            if (ret >= 0) 
            {
               ret = mymin (dump_section (f, h, newsec, indent + 2), ret);
               show_indent (f, indent);
               fprintf (f, "}\n");
               ret = mymin (ret, cf_closeSection (h, newsec));
            }
            break;
         }
      case SE_KEY:
         {
            char buf[255];
            ret = mymin (ret, cf_getKey (h, s, entry->name, &buf[0], sizeof(buf)));
            if (ret >= 0)
            {
                fprintf (f, "%s = \"%s\";\n", entry->name, buf); 
            }
            break;
         }
      case SE_MULTIKEY:
         {
            char ** ptrs;
            size_t size;
            size_t j;
            ret = mymin (ret, cf_getMultiKey (h, s, entry->name, &ptrs, &size));
            if (ret >= 0)
            {
               fprintf (f,"%s = (", entry->name);
               for (j=0; j<size; ++j)
               {
                  fprintf (f,"\"%s\" ", (ptrs[j] ? ptrs[j] : ""));
                  free (ptrs[j]);
                  if ((j+1) < size)
                     fprintf (f,", ");
               }
               fprintf (f, ");\n");
               free (ptrs);
            }
         }
   }
   return ret;
}

92
static int dump_section (FILE * f, struct ConfigVTable * h, SectionHandle s, unsigned
93 94 95 96 97 98 99 100 101 102 103 104 105 106
      int indent)
{
   unsigned int sectionsize;
   size_t count;
   unsigned int i;
   int ret = 1;
   SectionEntry * entries = 0;

   ret = mymin (ret, cf_getSectionSize (h, s, &sectionsize));
   if (ret < 0)
      return ret;

   count = sectionsize;
  
107
   entries = (SectionEntry*)malloc (sizeof (SectionEntry) * sectionsize);
108 109 110 111 112 113

   ret = mymin(ret, cf_listSection (h, s, &entries[0], &count));

   if (ret < 0)
      goto fail;

Jonathan Jenkins's avatar
Jonathan Jenkins committed
114
   assert(sectionsize == count);
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

   for (i=0; i<count; ++i)
   {
      show_indent (f,indent);
      if (ret >= 0)
      {
         ret = mymin (ret, dump_entry (f, h, s, indent, &entries[i]));
      }
      free ((void*)entries[i].name);
   }

fail:
   free (entries);
   return ret;
}


132
int txtfile_writeConfig (struct ConfigVTable * cf, SectionHandle h, FILE * f, char ** err)
133 134
{
   int ret;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
135 136
   assert(err);
   assert(f);
137 138 139 140 141 142 143 144 145 146 147 148

   *err = 0;

   if ((ret = dump_section (f, cf, h, 0)) < 0)
   {
      *err = strdup ("Error accessing config tree!");
      return ret;
   }

   return ret;
}

149
struct ConfigVTable * txtfile_openStream (FILE * f, char ** err)
150 151 152 153 154 155 156
{
   long size;
   ParserParams p; 
   yyscan_t scanner;
   int reject;
   char buf[512];
   
Jonathan Jenkins's avatar
Jonathan Jenkins committed
157
   assert(err);
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175

   *err=0;

   /* get file size */
   fseek (f, 0, SEEK_END);
 
   size = ftell (f);

   fseek (f, 0, SEEK_SET);
   if (size > MAX_CONFIG_SIZE)
   {
      *err = strdup ("Config file too large! Not parsing!");
      return 0;
   }

   cfgp_lex_init_extra (&p, &scanner);
   cfgp_set_in (f, scanner); 
   cfgp_initparams (&p, cfsa_create (mcs_initroot ()));
176
   reject = cfgp_parse((yyscan_t*)scanner, &p);
177 178 179 180
   cfgp_lex_destroy (scanner);

   /* either we have a valid confighandle or we have a parser error... */
   /* not true: we can have a partial config tree */
Jonathan Jenkins's avatar
Jonathan Jenkins committed
181
   // assert((p.error_code || p.configfile) && (!p.error_code || !p.configfile));
182 183

   /* If ther parser failed we need to have an error code */
Jonathan Jenkins's avatar
Jonathan Jenkins committed
184 185 186
   assert(!reject || p.parser_error_code || p.lexer_error_code);
   assert(!p.lexer_error_string || p.lexer_error_code);
   assert(!p.parser_error_string || p.parser_error_code);
187 188 189 190 191 192 193

   if (!cfgp_parse_ok (&p, buf, sizeof(buf)))
   {
      *err = strdup (buf);
   }
   else
   {
Jonathan Jenkins's avatar
Jonathan Jenkins committed
194 195
      assert(!p.parser_error_string);
      assert(!p.lexer_error_string);
196 197 198 199 200 201 202 203
      if (err) *err = 0;
   }

   cfgp_freeparams (&p);

   return p.configfile;
 }

204
struct ConfigVTable * txtfile_openConfig (const char * filename, char ** error)
205 206
{
   FILE  * f;
207
   struct ConfigVTable * ret;
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225


   f = fopen (filename, "r");
   if (!f)
   {
      char buf[255];
      strerror_r (errno, buf, sizeof(buf));
      *error = strdup (buf);
      return 0;
   }

   ret = txtfile_openStream (f, error);

   fclose (f);

   return ret;
}

Philip Carns's avatar
Philip Carns committed
226 227 228 229 230 231 232 233 234

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */