gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master edd5612 053/125: Single function to read all c


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master edd5612 053/125: Single function to read all configuration files
Date: Sun, 23 Apr 2017 22:36:36 -0400 (EDT)

branch: master
commit edd56124c774bb8fe80444f7f3d97fae9ac4ace8
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Single function to read all configuration files
    
    This commit mostly completes task #14300 ("Option management using new root
    data structure.", as with the last few commits). But it is not yet
    complete, Jobs that can be done immediately after reading the configuration
    (like printing values or citation and so on) aren't yet included, the
    values have to be written into the program's main paramters structure and
    also, the documentation needs to be updated.
    
    Until now, reading the configuration files heavily relied on macros, but
    now, there is a simple function that will do the job, so is much more
    easier to read, understand and debug.
    
    As part of this work, the following changes were also made:
    
     - `gal_linkedlist_add_to_stll' now has one more argument to see if the
       string should be allocated and copied, or should only the pointer be
       passed.
    
     - The final installation directory is now only necessary in the library
       installation, and not the whole of Gnuastro. So the `-DSYSCONFIG_DIR'
       `CPPFLAGS' value is now defined in the `AM_CPPFLAGS' of
       `lib/Makefile.am' and the programs can easily be compiled without it.
    
     - The `CURDIRCONFIG_DIR' is no longer included in `config.h' because it is
       easily derivable from the `PACKAGE' macro.
    
     - A new option `--config' was added so the users can specify any number of
       custom configuration files that will be read before the default ones.
    
     - The `onlydirconf' option was changed to `lastconfig'. The previous
       version was too specific. Now, which ever configuration file contains
       this option (even on the command-line) will be the last configuration
       file that is read.
    
     - The `gal_txt_line_stat' function and `gal_txt_line_status_enums' have
       now been moved into `gnuastro/txt.h' since they were also useful in
       `lib/options.c'.
    
     - The `gal_linkedlist_reverse_*' functions now check if the value is not
       NULL and also that there is more than one element in the list.
---
 bin/table/ui.c            |  21 ++-
 configure.ac              |   7 +-
 lib/Makefile.am           |   5 +-
 lib/commonopts.h          |  29 ++--
 lib/data.c                |   3 +-
 lib/gnuastro/linkedlist.h |   4 +-
 lib/gnuastro/txt.h        |  12 ++
 lib/linkedlist.c          |  34 ++--
 lib/options.c             | 410 ++++++++++++++++++++++++++++++++++++++++++++--
 lib/options.h             |   6 +-
 lib/txt.c                 |  59 +++----
 11 files changed, 509 insertions(+), 81 deletions(-)

diff --git a/bin/table/ui.c b/bin/table/ui.c
index f9a5000..752ecce 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -67,6 +67,20 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /***************       Sanity Check         *******************/
 /**************************************************************/
 void
+fill_params_from_options(struct tableparams *p)
+{
+
+
+  /* Free all the allocated spaces in the option structures. */
+  gal_options_free(options);
+  gal_options_free(gal_commonopts_options);
+}
+
+
+
+
+
+void
 sanitycheck(struct tableparams *p)
 {
   struct uiparams *up=&p->up;
@@ -165,7 +179,7 @@ preparearrays(struct tableparams *p)
         for(i=1;i<=numcols;++i)
           {
             asprintf(&numstr, "%zu", i);
-            gal_linkedlist_add_to_stll(&p->columns, numstr);
+            gal_linkedlist_add_to_stll(&p->columns, numstr, 0);
           }
     }
 
@@ -229,7 +243,10 @@ setparams(int argc, char *argv[], struct tableparams *p)
     error(EXIT_FAILURE, errno, "parsing arguments");
 
   /* Read the configuration files. */
-  gal_options_parse_configs(PROG_NAME, options, gal_commonopts_options);
+  gal_options_config_files(PROG_EXEC, options, gal_commonopts_options);
+
+  /* Fill the parameters from the options. */
+  fill_params_from_options(p);
 
   printf("\n--- back in `ui.c' ---\n");
   exit(0);
diff --git a/configure.ac b/configure.ac
index 171598a..68bdf2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -107,7 +107,7 @@ AC_DEFINE([IN_GNUASTRO_BUILD], [1], [In building, not 
usage])
 # layers of quotations there.
 CFLAGS="-Wall -O3 $CFLAGS"
 LDFLAGS="-L\$(top_builddir)/lib $LDFLAGS"
-CPPFLAGS="-DSYSCONFIG_DIR=\\\"$sysconfdir\\\" -I\$(top_srcdir)/lib $CPPFLAGS"
+CPPFLAGS="-I\$(top_srcdir)/lib $CPPFLAGS"
 
 
 
@@ -248,10 +248,7 @@ AM_CONDITIONAL([COND_GNULIBCHECK], [test 
$enable_gnulibcheck = yes])
 
 # Set the one general parameters:
 AC_DEFINE_UNQUOTED([CONF_POSTFIX], [".conf"], [Configuration file post fix.])
-AC_DEFINE_UNQUOTED([CURDIRCONFIG_DIR], [".AC_PACKAGE_TARNAME/"],
-                   [Local data dir.])
-AC_DEFINE_UNQUOTED([USERCONFIG_DIR], [".local/etc/"],
-                   [User data dir.])
+AC_DEFINE_UNQUOTED([USERCONFIG_DIR], [".local/etc"], [User data dir.])
 AC_DEFINE_UNQUOTED([CONF_SHOWFMT], [" %-20s"],
                    [Configuration file name format.])
 
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 6bd9d54..f613e10 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -25,7 +25,10 @@
 ## Necessary flags. NOTE: $(top_srcdir)/bootstrapped/lib is only necessary
 ## for internally compiled utilities and libraries. It must not be included
 ## during the tests since the bootstrapped libraries are not installed.
-AM_CPPFLAGS = -I\$(top_srcdir)/bootstrapped/lib
+##
+## The SYSCONFIG_DIR is necessary in `options.c'
+AM_CPPFLAGS = -I\$(top_srcdir)/bootstrapped/lib      \
+             -DSYSCONFIG_DIR=\"$(sysconfdir)\"
 
 
 
diff --git a/lib/commonopts.h b/lib/commonopts.h
index a4e3b4c..1e79102 100644
--- a/lib/commonopts.h
+++ b/lib/commonopts.h
@@ -96,7 +96,7 @@ struct argp_option gal_commonopts_options[] =
       0,
       0,
       "Only report errors, remain quiet about steps.",
-      -1,                       /* Operating mode. */
+      -1,
       NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
@@ -105,7 +105,7 @@ struct argp_option gal_commonopts_options[] =
       "INT",
       0,
       "Number of CPU threads to use.",
-      -1,                       /* Operating mode. */
+      -1,
       NULL, GAL_DATA_TYPE_ULONG
     },
     {
@@ -114,7 +114,7 @@ struct argp_option gal_commonopts_options[] =
       "INT",
       0,
       "Minimum no. bytes to map arrays to hdd/ssd.",
-      -1,                       /* Operating mode. */
+      -1,
       NULL, GAL_DATA_TYPE_ULONG
     },
     {
@@ -123,7 +123,7 @@ struct argp_option gal_commonopts_options[] =
       0,
       0,
       "No log file for programs which make one.",
-      -1,                       /* Operating mode. */
+      -1,
       NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
 
@@ -136,7 +136,7 @@ struct argp_option gal_commonopts_options[] =
       0,
       0,
       "BibTeX citation for this program.",
-      -1,                       /* Operating mode. */
+      -1,
       NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
@@ -149,6 +149,15 @@ struct argp_option gal_commonopts_options[] =
       NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
+      "config",
+      1005,
+      "STR",
+      0,
+      "Read file STR before default configuration files.",
+      -1,
+      NULL, GAL_DATA_TYPE_STRLL
+    },
+    {
       "setdirconf",
       'S',
       0,
@@ -167,12 +176,12 @@ struct argp_option gal_commonopts_options[] =
       NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
-      "onlydirconf",
+      "lastconfig",
       1001,
       0,
       0,
-      "Only read current directory configuration file.",
-      -1,                       /* Operating mode. */
+      "Do not parse any more configuration files.",
+      -1,
       NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
@@ -180,8 +189,8 @@ struct argp_option gal_commonopts_options[] =
       1002,
       "STR",
       0,
-      "Only run if the program version is this.",
-      -1,                       /* Operating mode. */
+      "Only run if the program version is STR.",
+      -1,
       NULL, GAL_DATA_TYPE_STRING
     },
 
diff --git a/lib/data.c b/lib/data.c
index 37fff2a..4e39dc2 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -2168,7 +2168,8 @@ gal_data_string_to_type(void **out, char *string, int 
type)
 
     /* Linked lists, currently only string linked lists. */
     case GAL_DATA_TYPE_STRLL:
-      gal_linkedlist_add_to_stll( (struct gal_linkedlist_stll **)out, string);
+      gal_linkedlist_add_to_stll( (struct gal_linkedlist_stll **)out,
+                                  string, 1);
       break;
 
     /* String, just allocate and copy the string and keep its pointer in
diff --git a/lib/gnuastro/linkedlist.h b/lib/gnuastro/linkedlist.h
index 105d046..df1c9b4 100644
--- a/lib/gnuastro/linkedlist.h
+++ b/lib/gnuastro/linkedlist.h
@@ -122,8 +122,8 @@ struct gal_linkedlist_stll
 };
 
 void
-gal_linkedlist_add_to_stll(struct gal_linkedlist_stll **list,
-                           char *value);
+gal_linkedlist_add_to_stll(struct gal_linkedlist_stll **list, char *value,
+                           int allocate);
 
 void
 gal_linkedlist_pop_from_stll(struct gal_linkedlist_stll **list,
diff --git a/lib/gnuastro/txt.h b/lib/gnuastro/txt.h
index 217d836..1f82e95 100644
--- a/lib/gnuastro/txt.h
+++ b/lib/gnuastro/txt.h
@@ -64,7 +64,19 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 #define GAL_TXT_MAX_FMT_LENGTH 20
 
 
+/* Status of a line: */
+enum gal_txt_line_status_enums
+{
+  GAL_TXT_LINESTAT_BLANK,
+  GAL_TXT_LINESTAT_COMMENT,
+  GAL_TXT_LINESTAT_DATAROW,
+};
+
+
 /* Functions */
+int
+gal_txt_line_stat(char *line);
+
 gal_data_t *
 gal_txt_table_info(char *filename, size_t *numcols, size_t *numrows);
 
diff --git a/lib/linkedlist.c b/lib/linkedlist.c
index d89b660..0feb159 100644
--- a/lib/linkedlist.c
+++ b/lib/linkedlist.c
@@ -30,7 +30,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/linkedlist.h>
 
-
+#include <checkset.h>
 
 
 
@@ -306,7 +306,8 @@ gal_linkedlist_free_tdll(struct gal_linkedlist_tdll *list)
  *****************           string          ********************
  ****************************************************************/
 void
-gal_linkedlist_add_to_stll(struct gal_linkedlist_stll **list, char *value)
+gal_linkedlist_add_to_stll(struct gal_linkedlist_stll **list, char *value,
+                           int allocate)
 {
   struct gal_linkedlist_stll *newnode;
 
@@ -316,7 +317,11 @@ gal_linkedlist_add_to_stll(struct gal_linkedlist_stll 
**list, char *value)
     error(EXIT_FAILURE, errno,
           "linkedlist: New element in gal_linkedlist_stll");
 
-  newnode->v=value;
+  if(allocate)
+    gal_checkset_allocate_copy(value, &newnode->v);
+  else
+    newnode->v=value;
+
   newnode->next=*list;
   *list=newnode;
 }
@@ -345,12 +350,16 @@ gal_linkedlist_reverse_stll(struct gal_linkedlist_stll 
**list)
   char *thisstring;
   struct gal_linkedlist_stll *correctorder=NULL;
 
-  while(*list!=NULL)
+  /* Only do the reversal if there is more than one element. */
+  if( *list && (*list)->next )
     {
-      gal_linkedlist_pop_from_stll(list, &thisstring);
-      gal_linkedlist_add_to_stll(&correctorder, thisstring);
+      while(*list!=NULL)
+        {
+          gal_linkedlist_pop_from_stll(list, &thisstring);
+          gal_linkedlist_add_to_stll(&correctorder, thisstring, 1);
+        }
+      *list=correctorder;
     }
-  *list=correctorder;
 }
 
 
@@ -454,12 +463,15 @@ gal_linkedlist_reverse_sll(struct gal_linkedlist_sll 
**list)
   size_t thisnum;
   struct gal_linkedlist_sll *correctorder=NULL;
 
-  while(*list!=NULL)
+  if( *list && (*list)->next )
     {
-      gal_linkedlist_pop_from_sll(list, &thisnum);
-      gal_linkedlist_add_to_sll(&correctorder, thisnum);
+      while(*list!=NULL)
+        {
+          gal_linkedlist_pop_from_sll(list, &thisnum);
+          gal_linkedlist_add_to_sll(&correctorder, thisnum);
+        }
+      *list=correctorder;
     }
-  *list=correctorder;
 }
 
 
diff --git a/lib/options.c b/lib/options.c
index f299677..48dd62b 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -27,7 +27,9 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdlib.h>
 #include <string.h>
 
+#include <gnuastro/txt.h>
 #include <gnuastro/data.h>
+#include <gnuastro/linkedlist.h>
 
 #include <options.h>
 
@@ -62,6 +64,29 @@ gal_options_is_category_title(struct argp_option *option)
 
 
 
+/* The modified `argp_option' structure contains a void pointer, depending
+   on the type of value inside it, you need to the pointer differently. */
+void
+gal_options_free(struct argp_option *options)
+{
+  size_t i;
+
+  /* Go over all the options and free those that are allocated. After
+     freeing, set them to NULL, so they are not mistakenly used later. */
+  for(i=0; !gal_options_is_last(&options[i]); ++i)
+    if(options[i].value)
+      {
+        if(options[i].type==GAL_DATA_TYPE_STRLL)
+          gal_linkedlist_free_stll(options[i].value, 1);
+        else
+          free(options[i].value);
+        options[i].value=NULL;
+      }
+}
+
+
+
+
 
 
 
@@ -87,6 +112,7 @@ error_t
 gal_options_set_from_key(int key, char *arg, struct argp_option *options)
 {
   size_t i;
+  char **strarr=NULL;
 
   /* Go through all the options and find the one that should keep this
      value, then put its value into the appropriate key. Note that the
@@ -120,8 +146,31 @@ gal_options_set_from_key(int key, char *arg, struct 
argp_option *options)
              convert the given value to the appropriate type and put it in
              the `value' element of options[i]. */
           if(arg)
-            gal_data_string_to_type(&options[i].value, arg,
-                                    options[i].type);
+            {
+              /* For strings, `gal_data_string_to_type' is going to return
+                 an allocated pointer to an allocated string (`char
+                 **'). In this context, we are just dealing with one
+                 string, and arrays of strings are never used (a linked
+                 list is defined when multiple strings must be read). So
+                 only keep the actual string and free the one that kept
+                 it. */
+              if(options[i].type==GAL_DATA_TYPE_STRING)
+                {
+                  gal_data_string_to_type((void **)(&strarr), arg,
+                                                 options[i].type);
+                  options[i].value=strarr[0];
+                  free(strarr);
+                }
+              else
+                {
+                  if( gal_data_string_to_type(&options[i].value, arg,
+                                              options[i].type) )
+                    error(EXIT_FAILURE, 0, "`%s' (value to option `%s') "
+                          "couldn't be read as a number", arg,
+                          options[i].name);
+
+                }
+            }
           else
             {
               /* Make sure the option has the type set for options with no
@@ -216,13 +265,236 @@ gal_options_common_argp_parse(int key, char *arg, struct 
argp_state *state)
 /**********************************************************************/
 /************            Configuration files            ***************/
 /**********************************************************************/
-/*
-error_t
-gal_options_set_from_name(char *name, char *arg, struct argp_option *options)
+
+/* Read the option and the argument from the line and return.*/
+static void
+options_read_name_arg(char *line, char *filename, size_t lineno,
+                        char **name, char **arg)
 {
+  int notyetfinished=1, inword=0, inquote=0;
+
+  /* Initialize name and value: */
+  *arg=NULL;
+  *name=NULL;
+
+  /* Go through the characters and set the values: */
+  do
+    switch(*line)
+      {
+      case ' ': case '\t': case '\v': case '\n': case '\r':
+        if(inword) /* Only considered in a word, not in a quote*/
+          {
+            inword=0;
+            *line='\0';
+            if(*arg && inquote==0)
+              notyetfinished=0;
+          }
+        break;
+      case '#':
+        notyetfinished=0;
+        break;
+      case '"':
+        if(inword)
+          error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                        "Quotes have to be surrounded by whitespace "
+                        "characters (space, tab, new line, etc).");
+        if(inquote)
+          {
+            *line='\0';
+            inquote=0;
+            notyetfinished=0;
+          }
+        else
+          {
+            if(*name==NULL)
+              error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                            "option name should not start with "
+                            "double quotes (\").");
+            inquote=1;
+            *arg=line+1;
+          }
+        break;
+      default:
+        if(inword==0 && inquote==0)
+          {
+            if(*name==NULL)
+              *name=line;
+            else  /* *name is set, now assign *arg. */
+              *arg=line;
+            inword=1;
+          }
+        break;
+      }
+  while(*(++line)!='\0' && notyetfinished);
+
+  /* In the last line of the file, there is no new line to be
+     converted to a '\0' character! So if value has been assigned, we
+     are not in a quote and the line has finished, it means the given
+     value has also finished. */
+  if(*line=='\0' && *arg && inquote==0)
+    notyetfinished=0;
+
+  /* This was a blank line: */
+  if(*name==NULL && *arg==NULL)
+    return;
+
+  /* Name or value were set but not yet finished. */
+  if(notyetfinished)
+    error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                  "line finished before option name and value could "
+                  "be read.");
+}
+
+
+
+
+
+static int
+options_set_from_name(char *name, char *arg, struct argp_option *options,
+                      char *filename, size_t lineno)
+{
+  size_t i;
+  char **strarr=NULL;
 
+  /* Go through all the options and find the one that should keep this
+     value, then put its value into the appropriate key. Note that the
+     options array finishs with an all zero element, so we don't need to
+     know the number before hand.*/
+  for(i=0;1;++i)
+    {
+      /* Check if the key corresponds to this option. */
+      if(options[i].name && !strcmp(options[i].name, name))
+        {
+          /* If the option already has a value and it isn't a linked
+             list, then ignore it. */
+          if(options[i].value && !gal_data_is_linked_list(options[i].type))
+            return 0;
+
+          /* For strings, `gal_data_string_to_type' is going to return an
+             allocated pointer to an allocated string (`char **'). In this
+             context, we are just dealing with one string, and arrays of
+             strings are never used (a linked list is defined when multiple
+             strings must be read). So only keep the actual string and free
+             the one that kept it. */
+          if(options[i].type==GAL_DATA_TYPE_STRING)
+            {
+              gal_data_string_to_type((void **)(&strarr), arg,
+                                      options[i].type);
+              options[i].value=strarr[0];
+              free(strarr);
+            }
+          else
+            {
+              if( gal_data_string_to_type(&options[i].value, arg,
+                                          options[i].type) )
+                error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                              "`%s' (value to option `%s') couldn't be "
+                              "read as a number", arg, options[i].name);
+            }
+
+
+          /* If this is an on/off option (with no argument), then check if
+             the given value is 0 or 1. */
+          if( options[i].type==GAL_OPTIONS_NO_ARG_TYPE
+              && *(unsigned char *)(options[i].value) > 1 )
+            error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                          "`%s' is an on/off option, so its value can only "
+                          "be 1 (for `on'), or 0 (for `off'), it was given "
+                          "a value of `%s'", options[i].name, arg);
+
+
+          /* We have found and set the value given to this option, so just
+             return success (an error_t of 0 means success). */
+          return 0;
+        }
+      else
+        {
+          /* The last option has all its values set to zero. */
+          if(gal_options_is_last(&options[i]))
+            return 1;
+        }
+    }
 }
-*/
+
+
+
+
+
+static void
+options_parse_file(char *filename,  struct argp_option *poptions,
+                   struct argp_option *coptions)
+{
+  FILE *fp;
+  char *line, *name, *arg;
+  size_t linelen=10, lineno=0;
+
+
+  /* Open the file. If the file doesn't exist, then just ignore the
+     configuration file and return. */
+  errno=0;
+  fp=fopen(filename, "r");
+  if(fp==NULL)
+    {
+      if(errno==ENOENT)
+        return;
+      else
+        error(EXIT_FAILURE, errno, "%s: to read as a configuration file",
+              filename);
+    }
+
+
+  /* Allocate the space necessary to keep a copy of each line as we parse
+     it. Note that `getline' is going to later `realloc' this space to fit
+     the line length. */
+  errno=0;
+  line=malloc(linelen*sizeof *line);
+  if(line==NULL)
+    error(EXIT_FAILURE, errno, "%zu bytes for `line' in `gal_txt_table_read'",
+          linelen*sizeof *line);
+
+
+  /* Read the parameters line by line. */
+  while( getline(&line, &linelen, fp) != -1 )
+    {
+      ++lineno;
+      if( gal_txt_line_stat(line) == GAL_TXT_LINESTAT_DATAROW )
+        {
+          /* Get the option name and argument/value. */
+          options_read_name_arg(line, filename, lineno, &name, &arg);
+
+          /* First look into this program's options, if the option isn't
+             found there, `options_set_from_name' will return 1. So the
+             condition will succeed and we will start looking into the
+             common options, if it isn't found there either, then report an
+             error.*/
+          if( options_set_from_name(name, arg, poptions, filename, lineno) )
+            if( options_set_from_name(name, arg, coptions, filename, lineno) )
+              error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                            "unrecognized option `%s', for the full list of "
+                            "options, please run with `--help'", name);
+        }
+    }
+
+
+  /* Close the file. */
+  errno=0;
+  if(fclose(fp))
+    error(EXIT_FAILURE, errno, "%s: couldn't close after reading as "
+          "a configuration file", filename);
+
+
+  /* Clean up and return. */
+  free(line);
+}
+
+
+
+
+/* Macro to easily specify if we should continue with the rest of the
+   configuration files. */
+#define OPTIONS_THIS_IS_LASTCONFIG coptions[last_config_index].value     \
+  && *((unsigned char *)(coptions[last_config_index].value))
+
 
 
 
@@ -231,14 +503,126 @@ gal_options_set_from_name(char *name, char *arg, struct 
argp_option *options)
    into it. The directories containing the configuration files are fixed
    for all the programs.
 
-    - `SYSCONFIG_DIR' is passed onto each program at compile time from the
-      command-line. You can search for it in the outputs of `make'.
+    - `SYSCONFIG_DIR' is passed onto the library functions at compile time
+      from the command-line. You can search for it in the outputs of
+      `make'. The main reason is that we want the the user still has the
+      chance to change the installation directory after `configure'.
+
+    - `USERCONFIG_DIR' is defined in `config.h'.
+
+    - `CURDIRCONFIG_DIR' is defined in `config.h'. */
+static void
+gal_options_parse_config_files(char *progexec, struct argp_option *poptions,
+                               struct argp_option *coptions)
+{
+  char *filename;
+  size_t i, last_config_index;
+  struct gal_linkedlist_stll *tmp;
+
+
+
+  /* A small sanity check because in multiple places, we have assumed the
+     on/off options have a type of `unsigned char'. */
+  if(GAL_OPTIONS_NO_ARG_TYPE != GAL_DATA_TYPE_UCHAR)
+    error(EXIT_FAILURE, 0, "A bug! Please contact us at %s so we can fix the "
+          "problem. The `GAL_OPTIONS_NO_ARG_TYPE' must have the "
+          "`unsigned char' type. But",
+          PACKAGE_BUGREPORT);
+
+
+
+  /* Set the index of the `lastconfig' option. It is important to check
+     this option after every configuration file. Thus, to avoid having to
+     loop through all the options on every check, we'll find the index and
+     just check it each time.
+
+     Although very unlikely, it might happen that the user calls this on
+     the command-line (to avoid any configuration files). So, also check if
+     we should continue with this function or not. */
+  for(i=0; gal_options_is_last(&coptions[i])==0; ++i)
+    if(!strcmp(coptions[i].name, "lastconfig"))
+      {
+        last_config_index=i;
+        if(OPTIONS_THIS_IS_LASTCONFIG) return;
+        break;
+      }
+
+
+
+  /* Before doing anything, see if the user specified any configuration
+     files to parse before the standard ones. */
+  for(i=0; gal_options_is_last(&coptions[i])==0; ++i)
+    if(!strcmp(coptions[i].name, "config"))
+      {
+        /* When more than one configuration file is given, reverse the list
+           so it comes into the same order that the user specified on the
+           command-line. */
+        gal_linkedlist_reverse_stll(
+                (struct gal_linkedlist_stll **)(&coptions[i].value) );
+
+        /* Go through all the configuration files and fill in the values. */
+        for(tmp=coptions[i].value; tmp!=NULL; tmp=tmp->next)
+          {
+            options_parse_file(tmp->v, poptions, coptions);
+            if( OPTIONS_THIS_IS_LASTCONFIG ) return;
+          }
+        break;
+      }
+
+
+
+  /* The program's current directory configuration file. */
+  asprintf(&filename, ".%s/%s.conf", PACKAGE, progexec);
+  options_parse_file(filename, poptions, coptions);
+  if( OPTIONS_THIS_IS_LASTCONFIG ) return;
+  free(filename);
+
+  /* General Gnuastro configuration file. */
+  asprintf(&filename, ".%s/%s.conf", PACKAGE, PACKAGE);
+  printf("%s\n", filename);
+  options_parse_file(filename, poptions, coptions);
+  if( OPTIONS_THIS_IS_LASTCONFIG ) return;
+  free(filename);
+
+  /* User level configuration files. */
+  asprintf(&filename, "%s/%s.conf", USERCONFIG_DIR, progexec);
+  printf("%s\n", filename);
+  options_parse_file(filename, poptions, coptions);
+  if( OPTIONS_THIS_IS_LASTCONFIG ) return;
+  free(filename);
+
+  /* User level general Gnuastro configuration file. */
+  asprintf(&filename, "%s/%s.conf", USERCONFIG_DIR, PACKAGE);
+  printf("%s\n", filename);
+  options_parse_file(filename, poptions, coptions);
+  if( OPTIONS_THIS_IS_LASTCONFIG ) return;
+  free(filename);
+
+  /* User level configuration files. */
+  asprintf(&filename, "%s/%s.conf", SYSCONFIG_DIR, progexec);
+  printf("%s\n", filename);
+  options_parse_file(filename, poptions, coptions);
+  if( OPTIONS_THIS_IS_LASTCONFIG ) return;
+  free(filename);
+
+  /* User level general Gnuastro configuration file. */
+  asprintf(&filename, "%s/%s.conf", SYSCONFIG_DIR, PACKAGE);
+  printf("%s\n", filename);
+  options_parse_file(filename, poptions, coptions);
+  if( OPTIONS_THIS_IS_LASTCONFIG ) return;
+  free(filename);
+}
+
+
+
+
 
-    - `'
-*/
 void
-gal_options_parse_configs(char *progname, struct argp_option *progopts,
-                          struct argp_option *commopts)
+gal_options_config_files(char *progexec, struct argp_option *poptions,
+                         struct argp_option *coptions)
 {
-  printf("\nhere\n");
+  /* Parse all the configuration files. */
+  gal_options_parse_config_files(progexec, poptions, coptions);
+
+  /* Do the necessary checks (printing, saving and etc). */
 }
diff --git a/lib/options.h b/lib/options.h
index 9febc1b..52e83ad 100644
--- a/lib/options.h
+++ b/lib/options.h
@@ -83,6 +83,8 @@ gal_options_is_last(struct argp_option *option);
 int
 gal_options_is_category_title(struct argp_option *option);
 
+void
+gal_options_free(struct argp_option *options);
 
 
 
@@ -104,8 +106,8 @@ gal_options_common_argp_parse(int key, char *arg, struct 
argp_state *state);
 /************            Configuration files            ***************/
 /**********************************************************************/
 void
-gal_options_parse_configs(char *progname, struct argp_option *progopts,
-                          struct argp_option *commopts);
+gal_options_config_files(char *progname, struct argp_option *poptions,
+                         struct argp_option *coptions);
 
 
 #endif
diff --git a/lib/txt.c b/lib/txt.c
index 1f52917..2c3ba2a 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -47,21 +47,9 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /************************************************************************/
 /***************           Get table information          ***************/
 /************************************************************************/
-/* Status of a line: */
-enum txt_line_stat
-{
-  TXT_LINESTAT_BLANK,
-  TXT_LINESTAT_ISCOMMENT,
-  TXT_LINESTAT_DATAROW,
-};
-
-
-
-
-
 /* Return one of the `txt_line_stat' constant values. */
-static int
-get_line_stat(char *line)
+int
+gal_txt_line_stat(char *line)
 {
   while(*line!='\n')
     {
@@ -71,13 +59,13 @@ get_line_stat(char *line)
         case ' ': case ',': case '\t':
           break;
         case '#':
-          return TXT_LINESTAT_ISCOMMENT;
+          return GAL_TXT_LINESTAT_COMMENT;
         default:
-          return TXT_LINESTAT_DATAROW;
+          return GAL_TXT_LINESTAT_DATAROW;
         }
       ++line;
     }
-  return TXT_LINESTAT_BLANK;
+  return GAL_TXT_LINESTAT_BLANK;
 }
 
 
@@ -351,7 +339,7 @@ txt_info_from_first_row(char *line, gal_data_t **colsll)
       col=*colsll;
       while(col!=NULL)
         {
-          if(col->status > n)   /* Column has no data (was only in comments) */
+          if(col->status > n) /* Column has no data (was only in comments) */
             {
               /* This column has to be removed/freed. But we have to make
                  some corrections before freeing it:
@@ -371,7 +359,7 @@ txt_info_from_first_row(char *line, gal_data_t **colsll)
               gal_data_free(col, 0);
               col=tmp;
             }
-          else                  /* Column has data.                          */
+          else                /* Column has data.                          */
             {
               prev=col;
               col=col->next;
@@ -470,22 +458,25 @@ gal_txt_table_info(char *filename, size_t *numcols, 
size_t *numrows)
      uncommented line. */
   *numrows=0;
   while( getline(&line, &linelen, fp) != -1 )
-    {
-      /* Line is a comment, see if it has formatted information. */
-      if( get_line_stat(line) == TXT_LINESTAT_ISCOMMENT )
+    switch( gal_txt_line_stat(line) )
+      {
+      case GAL_TXT_LINESTAT_COMMENT:
+        /* Line is a comment, see if it has formatted information. */
         txt_info_from_comment(line, &colsll);
+        break;
 
-      /* Line is actual data, use it to fill in the gaps.  */
-      if( get_line_stat(line) == TXT_LINESTAT_DATAROW )
-        {
-          ++(*numrows);
-          if(firstlinedone==0)
-            {
-              firstlinedone=1;
-              txt_info_from_first_row(line, &colsll);
-            }
-        }
-    }
+        /* Line is actual data, use it to fill in the gaps.  */
+      case GAL_TXT_LINESTAT_DATAROW:
+        ++(*numrows);
+        if(firstlinedone==0)
+          {
+            firstlinedone=1;
+            txt_info_from_first_row(line, &colsll);
+          }
+        break;
+
+        /* We also have the case of GAL_TXT_LINESTAT_BLANK */
+      }
 
 
   /* If there were rows in the file, then write the unorganized gathered
@@ -791,7 +782,7 @@ gal_txt_table_read(char *filename, size_t numrows, 
gal_data_t *colinfo,
   while( getline(&line, &linelen, fp) != -1 )
     {
       ++lineno;
-      if( get_line_stat(line) == TXT_LINESTAT_DATAROW )
+      if( gal_txt_line_stat(line) == GAL_TXT_LINESTAT_DATAROW )
         txt_fill_columns(line, tokens, maxcolnum, colinfo, out, rowind++,
                          lineno, filename);
     }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]