]> Kevux Git Server - fll/commitdiff
Progress: featureless make
authorKevin Day <thekevinday@gmail.com>
Thu, 18 Jun 2020 05:27:01 +0000 (00:27 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 18 Jun 2020 05:27:01 +0000 (00:27 -0500)
Continue development in featureless make, implementing support for "make" operation.

This expands the f_string project to support additional structures.
This expands the fll_fss project to utilize these additional structures.

I have reviewed and redesigned some of the fll_fss project functions.
The fll_fss project function redesign is incomplete and not fully tested as of this commit.
(I plan on reviewing and updating the *_together functions.)

The current fakefile is a stub/example for testing and will be updated to a correct default fakefile once the "make" operation is complete.
The plan is to have the fakefile provide an example for building th featureless make project using the fakefile.
This would mean that the featuereless make project can be built by the featureless make project using either the "build" or the "make" operation.

17 files changed:
level_0/f_string/c/string.h
level_2/fll_fss/c/fss.c
level_2/fll_fss/c/fss.h
level_3/fake/c/fake.c
level_3/fake/c/fake.h
level_3/fake/c/private-build.c
level_3/fake/c/private-build.h
level_3/fake/c/private-fake.c
level_3/fake/c/private-fake.h
level_3/fake/c/private-make.c
level_3/fake/c/private-make.h
level_3/fake/c/private-print.c
level_3/fake/c/private-print.h
level_3/fake/c/private-skeleton.c
level_3/fake/c/private-skeleton.h
level_3/fake/data/build/dependencies
level_3/fake/data/build/fakefile [new file with mode: 0644]

index 6201b7a2c2dcd3f2ab5b7aedc6c1a9d9deef0738..c7bfe443285386c604e1d1678fb195702c78f7ea 100644 (file)
@@ -99,19 +99,6 @@ extern "C" {
   #define f_string_length_size_max f_type_number_size_max_unsigned
 
   #define f_string_length_printf string_format_long_integer
-
-  #define f_macro_string_length_new(status, string, length)     status = f_memory_new((void **) & string, sizeof(f_string_length), length)
-  #define f_macro_string_length_delete(status, string, length)  status = f_memory_delete((void **) & string, sizeof(f_string_length), length)
-  #define f_macro_string_length_destroy(status, string, length) status = f_memory_destroy((f_void_P *) & string, sizeof(f_string_length), length)
-
-  #define f_macro_string_length_delete_simple(string, length)  f_memory_delete((void **) & string, sizeof(f_string_length), length)
-  #define f_macro_string_length_destroy_simple(string, length) f_memory_destroy((f_void_P *) & string, sizeof(f_string_length), length)
-
-  #define f_macro_string_length_resize(status, length, old_length, new_length) \
-    status = f_memory_resize((void **) & length, sizeof(f_string_length), old_length, new_length)
-
-  #define f_macro_string_length_adjust(status, length, old_length, new_length) \
-    status = f_memory_adjust((void **) & length, sizeof(f_string_length), old_length, new_length)
 #endif // _di_f_string_length_
 
 /**
@@ -361,8 +348,8 @@ extern "C" {
   typedef struct {
     f_string_static *array;
 
-    f_string_length size;
-    f_string_length used;
+    f_array_length size;
+    f_array_length used;
   } f_string_statics;
 
   #define f_string_statics_initialize { 0, 0, 0 }
@@ -444,7 +431,7 @@ extern "C" {
   #define f_macro_string_dynamics_resize(status, dynamics, new_length) \
     status = F_none; \
     if (new_length < dynamics.size) { \
-      f_string_length i = dynamics.size - new_length; \
+      f_array_length i = dynamics.size - new_length; \
       for (; i < dynamics.size; i++) { \
         f_macro_string_dynamic_delete(status, dynamics.array[i]); \
         if (status != F_none) break; \
@@ -453,7 +440,7 @@ extern "C" {
     if (status == F_none) status = f_memory_resize((void **) & dynamics.array, sizeof(f_string_dynamic), dynamics.size, new_length); \
     if (status == F_none) { \
       if (new_length > dynamics.size) { \
-        f_string_length i = dynamics.size; \
+        f_array_length i = dynamics.size; \
         for (; i < new_length; i++) { \
           memset(&dynamics.array[i], 0, sizeof(f_string_dynamic)); \
         } \
@@ -465,7 +452,7 @@ extern "C" {
   #define f_macro_string_dynamics_adjust(status, dynamics, new_length) \
     status = F_none; \
     if (new_length < dynamics.size) { \
-      f_string_length i = dynamics.size - new_length; \
+      f_array_length i = dynamics.size - new_length; \
       for (; i < dynamics.size; i++) { \
         f_macro_string_dynamic_destroy(status, dynamics.array[i], f_string_dynamic); \
         if (status != F_none) break; \
@@ -474,7 +461,7 @@ extern "C" {
     if (status == F_none) status = f_memory_adjust((void **) & dynamics.array, sizeof(f_string_dynamic), dynamics.size, new_length); \
     if (status == F_none) { \
       if (new_length > dynamics.size) { \
-        f_string_length i = dynamics.size; \
+        f_array_length i = dynamics.size; \
         for (; i < new_length; i++) { \
           memset(&dynamics.array[i], 0, sizeof(f_string_dynamic)); \
         } \
@@ -484,6 +471,320 @@ extern "C" {
     }
 #endif // _di_f_string_dynamics_
 
+/**
+ * A string map consisting of a name and value.
+ *
+ * name: A string representing the map name.
+ * value: A string representing the map value.
+ */
+#ifndef _di_f_string_map_
+  typedef struct {
+    f_string_dynamic name;
+    f_string_dynamic value;
+  } f_string_map;
+
+  #define f_string_map_initialize { f_string_dynamic_initialize, f_string_dynamic_initialize }
+
+  #define f_macro_string_map_clear(map) \
+    map.array = 0; \
+    map.size = 0; \
+    map.used = 0;
+
+  #define f_macro_string_map_delete(status, map) \
+    f_macro_string_dynamic_delete(status, map.name) \
+    if (status == F_none) { \
+      f_macro_string_dynamic_delete(status, map.value) \
+    }
+
+  #define f_macro_string_map_destroy(status, map) \
+    f_macro_string_dynamic_destroy(status, map.name) \
+    if (status == F_none) { \
+      f_macro_string_dynamic_destroy(status, map.value) \
+    }
+
+  #define f_macro_string_map_delete_simple(map) \
+    f_macro_string_dynamic_delete_simple(map.name) \
+    f_macro_string_dynamic_delete_simple(map.value)
+
+  #define f_macro_string_map_destroy_simple(map) \
+    f_macro_string_dynamic_destroy_simple(map.name) \
+    f_macro_string_dynamic_destroy_simple(map.value)
+#endif // _di_f_string_map_
+
+/**
+ * An array of string maps.
+ *
+ * array: the array of string maps.
+ * size: total amount of allocated space.
+ * used: total number of allocated spaces used.
+ */
+#ifndef _di_f_string_maps_
+  typedef struct {
+    f_string_map *array;
+
+    f_array_length size;
+    f_array_length used;
+  } f_string_maps;
+
+  #define f_string_maps_initialize f_string_statics_initialize
+
+  #define f_macro_string_maps_clear(maps) \
+    maps.array = 0; \
+    maps.size = 0; \
+    maps.used = 0;
+
+  #define f_macro_string_maps_new(status, maps, length) \
+    f_macro_string_maps_clear(maps) \
+    status = f_memory_new((void **) & maps.array, sizeof(f_string_map), length); \
+    if (status == F_none) { \
+      maps.size = length; \
+      maps.used = 0; \
+    }
+
+  #define f_macro_string_maps_delete(status, maps) \
+    status = F_none; \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_delete(status, maps.array[maps.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) status = f_memory_delete((void **) & maps.array, sizeof(f_string_map), maps.size); \
+    if (status == F_none) maps.size = 0;
+
+  #define f_macro_string_maps_destroy(status, maps) \
+    status = F_none; \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_destroy(status, maps.array[maps.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) status = f_memory_destroy((void **) & maps.array, sizeof(f_string_map), maps.size); \
+    if (status == F_none) maps.size = 0;
+
+  #define f_macro_string_maps_delete_simple(maps) \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_delete_simple(maps.array[maps.used]); \
+      if (maps.used == 0) { \
+        if (f_memory_delete((void **) & maps.array, sizeof(f_string_map), maps.size)) { \
+          maps.size = 0; \
+        } \
+      } \
+    }
+
+  #define f_macro_string_maps_destroy_simple(maps) \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_destroy_simple(maps.array[maps.used]); \
+      if (maps.used == 0) { \
+        if (f_memory_destroy((void **) & maps.array, sizeof(f_string_map), maps.size)) { \
+          maps.size = 0; \
+        } \
+      } \
+    }
+
+  #define f_macro_string_maps_resize(status, maps, new_length) \
+    status = F_none; \
+    if (new_length < maps.size) { \
+      f_array_length i = maps.size - new_length; \
+      for (; i < maps.size; i++) { \
+        f_macro_string_map_delete(status, maps.array[i]); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_resize((void **) & maps.array, sizeof(f_string_map), maps.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > maps.size) { \
+        f_array_length i = maps.size; \
+        for (; i < new_length; i++) { \
+          memset(&maps.array[i], 0, sizeof(f_string_map)); \
+        } \
+      } \
+      maps.size = new_length; \
+      if (maps.used > maps.size) maps.used = new_length; \
+    }
+
+  #define f_macro_string_maps_adjust(status, maps, new_length) \
+    status = F_none; \
+    if (new_length < maps.size) { \
+      f_array_length i = maps.size - new_length; \
+      for (; i < maps.size; i++) { \
+        f_macro_string_map_destroy(status, maps.array[i], f_string_map); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_adjust((void **) & maps.array, sizeof(f_string_map), maps.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > maps.size) { \
+        f_array_length i = maps.size; \
+        for (; i < new_length; i++) { \
+          memset(&maps.array[i], 0, sizeof(f_string_map)); \
+        } \
+      } \
+      maps.size = new_length; \
+      if (maps.used > maps.size) maps.used = new_length; \
+    }
+#endif // _di_f_string_maps_
+
+/**
+ * A string map consisting of a name and multiple values.
+ *
+ * name: A string representing the map name.
+ * value: An array of strings representing the map value.
+ */
+#ifndef _di_f_string_map_multi_
+  typedef struct {
+    f_string_dynamic name;
+    f_string_dynamics value;
+  } f_string_map_multi;
+
+  #define f_string_map_multi_initialize { f_string_dynamic_initialize, f_string_dynamics_initialize }
+
+  #define f_macro_string_map_multi_clear(map) \
+    f_macro_string_dynamic_clear(map.name) \
+    f_macro_string_dynamics_clear(map.value)
+
+  #define f_macro_string_map_multi_delete(status, map) \
+    f_macro_string_dynamic_delete(status, map.name) \
+    if (status == F_none) { \
+      f_macro_string_dynamics_delete(status, map.value) \
+    }
+
+  #define f_macro_string_map_multi_destroy(status, map) \
+    f_macro_string_dynamic_destroy(status, map.name) \
+    if (status == F_none) { \
+      f_macro_string_dynamics_destroy(status, map.value) \
+    }
+
+  #define f_macro_string_map_multi_delete_simple(map) \
+    f_macro_string_dynamic_delete_simple(map.name) \
+    f_macro_string_dynamics_delete_simple(map.value)
+
+  #define f_macro_string_map_multi_destroy_simple(map) \
+    f_macro_string_dynamic_destroy_simple(map.name) \
+    f_macro_string_dynamics_destroy_simple(map.value)
+#endif // _di_f_string_map_multi_
+
+/**
+ * An array of string maps.
+ *
+ * array: the array of string maps.
+ * size: total amount of allocated space.
+ * used: total number of allocated spaces used.
+ */
+#ifndef _di_f_string_map_multis_
+  typedef struct {
+    f_string_map_multi *array;
+
+    f_array_length size;
+    f_array_length used;
+  } f_string_map_multis;
+
+  #define f_string_map_multis_initialize f_string_statics_initialize
+
+  #define f_macro_string_map_multis_clear(maps) f_macro_string_statics_clear(maps)
+
+  #define f_macro_string_map_multis_new(status, maps, length) \
+    f_macro_string_map_multis_clear(maps) \
+    status = f_memory_new((void **) & maps.array, sizeof(f_string_map_multi), length); \
+    if (status == F_none) { \
+      maps.size = length; \
+      maps.used = 0; \
+    }
+
+  #define f_macro_string_map_multis_delete(status, maps) \
+    status = F_none; \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_multi_delete(status, maps.array[maps.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) status = f_memory_delete((void **) & maps.array, sizeof(f_string_map_multi), maps.size); \
+    if (status == F_none) maps.size = 0;
+
+  #define f_macro_string_map_multis_destroy(status, maps) \
+    status = F_none; \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_multi_destroy(status, maps.array[maps.used]); \
+      if (status != F_none) break; \
+    } \
+    if (status == F_none) status = f_memory_destroy((void **) & maps.array, sizeof(f_string_map_multi), maps.size); \
+    if (status == F_none) maps.size = 0;
+
+  #define f_macro_string_map_multis_delete_simple(maps) \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_multi_delete_simple(maps.array[maps.used]); \
+      if (maps.used == 0) { \
+        if (f_memory_delete((void **) & maps.array, sizeof(f_string_map_multi), maps.size)) { \
+          maps.size = 0; \
+        } \
+      } \
+    }
+
+  #define f_macro_string_map_multis_destroy_simple(maps) \
+    maps.used = maps.size; \
+    while (maps.used > 0) { \
+      maps.used--; \
+      f_macro_string_map_multi_destroy_simple(maps.array[maps.used]); \
+      if (maps.used == 0) { \
+        if (f_memory_destroy((void **) & maps.array, sizeof(f_string_map_multi), maps.size)) { \
+          maps.size = 0; \
+        } \
+      } \
+    }
+
+  #define f_macro_string_map_multis_resize(status, maps, new_length) \
+    status = F_none; \
+    if (new_length < maps.size) { \
+      f_array_length i = maps.size - new_length; \
+      for (; i < maps.size; i++) { \
+        f_macro_string_map_multi_delete(status, maps.array[i]); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_resize((void **) & maps.array, sizeof(f_string_map_multi), maps.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > maps.size) { \
+        f_array_length i = maps.size; \
+        for (; i < new_length; i++) { \
+          memset(&maps.array[i], 0, sizeof(f_string_map_multi)); \
+        } \
+      } \
+      maps.size = new_length; \
+      if (maps.used > maps.size) maps.used = new_length; \
+    }
+
+  #define f_macro_string_map_multis_adjust(status, maps, new_length) \
+    status = F_none; \
+    if (new_length < maps.size) { \
+      f_array_length i = maps.size - new_length; \
+      for (; i < maps.size; i++) { \
+        f_macro_string_map_multi_destroy(status, maps.array[i], f_string_map_multi); \
+        if (status != F_none) break; \
+      } \
+    } \
+    if (status == F_none) status = f_memory_adjust((void **) & maps.array, sizeof(f_string_map_multi), maps.size, new_length); \
+    if (status == F_none) { \
+      if (new_length > maps.size) { \
+        f_array_length i = maps.size; \
+        for (; i < new_length; i++) { \
+          memset(&maps.array[i], 0, sizeof(f_string_map_multi)); \
+        } \
+      } \
+      maps.size = new_length; \
+      if (maps.used > maps.size) maps.used = new_length; \
+    }
+#endif // _di_f_string_map_multis_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 54c755c429d771e395d6a470d7c30fff51b47413..1485fde375e765a27fb52d503a35c2c9b9a01d95 100644 (file)
@@ -5,9 +5,10 @@ extern "C" {
 #endif
 
 #ifndef _di_fll_fss_snatch_
-  f_return_status fll_fss_snatch(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size) {
+  f_return_status fll_fss_snatch(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_dynamic *values[]) {
     #ifndef _di_level_2_parameter_checking_
       if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
     if (buffer.used == 0) return F_data_not;
@@ -21,22 +22,27 @@ extern "C" {
     f_array_length j = 0;
     f_array_length k = 0;
 
+    bool matched[size];
+
+    memset(&matched, 0, sizeof(bool) * size);
+
     for (; i < objects.used; i++) {
       length_object = (objects.array[i].stop - objects.array[i].start) + 1;
 
       for (j = 0; j < size; j++) {
+        if (matched[j]) continue;
+
         status = fl_string_compare_trim(buffer.string + objects.array[i].start, names[j], length_object, lengths[j]);
 
         if (F_status_is_error(status)) return status;
         if (status == F_equal_to_not) continue;
 
-        if (values[j]->used == 0) {
-          for (k = 0; k < contents.array[i].used; k++) {
-            status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[k], values[j]);
+        matched[j] = F_true;
 
-            if (F_status_is_error(status)) return status;
-          } // for
-        }
+        if (!contents.array[i].used) continue;
+
+        status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[0], values[j]);
+        if (F_status_is_error(status)) return status;
       } // for
     } // for
 
@@ -45,9 +51,10 @@ extern "C" {
 #endif // _di_fll_fss_snatch_
 
 #ifndef _di_fll_fss_snatch_apart_
-  f_return_status fll_fss_snatch_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamics *values[], const f_string_length size) {
+  f_return_status fll_fss_snatch_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_dynamics *values[]) {
     #ifndef _di_level_2_parameter_checking_
       if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
     if (buffer.used == 0) return F_data_not;
@@ -70,10 +77,12 @@ extern "C" {
         if (F_status_is_error(status)) return status;
         if (status == F_equal_to_not) continue;
 
-        if (values[j]->used + contents.used > values[j]->size) {
-          if (values[j]->used + contents.used > f_array_length_size) return F_status_set_error(F_buffer_too_large);
+        if (values[j]->used + contents.array[i].used > values[j]->size) {
+          if (values[j]->used + contents.array[i].used > f_array_length_size) {
+            return F_status_set_error(F_buffer_too_large);
+          }
 
-          f_macro_string_dynamics_resize(status, (*values[j]), values[j]->used + contents.used);
+          f_macro_string_dynamics_resize(status, (*values[j]), values[j]->used + contents.array[i].used);
           if (F_status_is_error(status)) return status;
         }
 
@@ -90,10 +99,122 @@ extern "C" {
   }
 #endif // _di_fll_fss_snatch_apart_
 
-#ifndef _di_fll_fss_snatch_together_
-  f_return_status fll_fss_snatch_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size) {
+#ifndef _di_fll_fss_snatch_map_
+  f_return_status fll_fss_snatch_map(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_maps *values[]) {
+    #ifndef _di_level_2_parameter_checking_
+      if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
+
+    if (buffer.used == 0) return F_data_not;
+    if (objects.used == 0) return F_data_not;
+    if (contents.used == 0) return F_data_not;
+
+    f_status status = F_none;
+    f_string_length length_name = 0;
+    f_string_dynamic name = f_string_dynamic_initialize;
+
+    f_array_length i = 0;
+    f_array_length j = 0;
+    f_array_length k = 0;
+
+    bool matched = F_false;
+
+    f_string_map *map = 0;
+
+    for (; i < objects.used; i++) {
+      if (!contents.array[i].used) continue;
+
+      length_name = (objects.array[i].stop - objects.array[i].start) + 1;
+
+      for (j = 0; j < size; j++) {
+        status = fl_string_compare_trim(buffer.string + objects.array[i].start, names[j], length_name, lengths[j]);
+
+        if (F_status_is_error(status)) return status;
+        if (status == F_equal_to_not) continue;
+
+        status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[0], &name);
+        if (F_status_is_error(status)) {
+          f_macro_string_dynamic_delete_simple(name);
+          return status;
+        }
+
+        matched = F_false;
+        length_name = (contents.array[i].array[0].stop - contents.array[i].array[0].start) + 1;
+
+        for (k = 0; k < values[j]->used; k++) {
+          status = fl_string_compare_trim(buffer.string + contents.array[i].array[0].start, values[j]->array[k].name.string, length_name, values[j]->array[k].name.used);
+
+          if (F_status_is_error(status)) {
+            f_macro_string_dynamic_delete_simple(name);
+            return status;
+          }
+
+          if (status == F_equal_to) {
+            matched = F_true;
+
+            f_macro_string_dynamic_delete_simple(name);
+            break;
+          }
+        } // for
+
+        if (matched) {
+          name.used = 0;
+          continue;
+        }
+
+        if (values[j]->used + 1 > values[j]->size) {
+          if (values[j]->used + f_fss_default_allocation_step > f_array_length_size) {
+            if (values[j]->used + 1 > f_array_length_size) {
+              f_macro_string_dynamic_delete_simple(name);
+              return F_status_set_error(F_buffer_too_large);
+            }
+
+            f_macro_string_maps_resize(status, (*values[j]), values[j]->used + 1);
+            if (F_status_is_error(status)) {
+              f_macro_string_dynamic_delete_simple(name);
+              return status;
+            }
+          }
+          else {
+            f_macro_string_maps_resize(status, (*values[j]), values[j]->used + f_fss_default_allocation_step);
+            if (F_status_is_error(status)) {
+              f_macro_string_dynamic_delete_simple(name);
+              return status;
+            }
+          }
+        }
+
+        map = &values[j]->array[values[j]->used];
+
+        if (contents.array[i].used > 1) {
+          status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[1], &map->value);
+          if (F_status_is_error(status)) {
+            f_macro_string_dynamic_delete_simple(name);
+            return status;
+          }
+        }
+
+        map->name.string = name.string;
+        map->name.used = name.used;
+        map->name.size = name.size;
+
+        values[j]->used++;
+
+        f_macro_string_dynamic_clear(name);
+      } // for
+    } // for
+
+    f_macro_string_dynamic_delete_simple(name);
+    return F_none;
+  }
+#endif // _di_fll_fss_snatch_map_
+
+#ifndef _di_fll_fss_snatch_map_apart_
+  f_return_status fll_fss_snatch_map_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_map_multis *values[]) {
     #ifndef _di_level_2_parameter_checking_
       if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
     if (buffer.used == 0) return F_data_not;
@@ -107,7 +228,11 @@ extern "C" {
     f_array_length j = 0;
     f_array_length k = 0;
 
+    f_string_map_multi *map_multi = 0;
+
     for (; i < objects.used; i++) {
+      if (!contents.array[i].used) continue;
+
       length_object = (objects.array[i].stop - objects.array[i].start) + 1;
 
       for (j = 0; j < size; j++) {
@@ -116,21 +241,55 @@ extern "C" {
         if (F_status_is_error(status)) return status;
         if (status == F_equal_to_not) continue;
 
-        for (k = 0; k < contents.array[i].used; k++) {
-          status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[k], values[j]);
-          if (F_status_is_error(status)) return status;
-        } // for
+        if (values[j]->used + 1 > values[j]->size) {
+          if (values[j]->used + f_fss_default_allocation_step > f_array_length_size) {
+            if (values[j]->used + 1 > f_array_length_size) {
+              return F_status_set_error(F_buffer_too_large);
+            }
+
+            f_macro_string_map_multis_resize(status, (*values[j]), values[j]->used + 1);
+            if (F_status_is_error(status)) return status;
+          }
+          else {
+            f_macro_string_map_multis_resize(status, (*values[j]), values[j]->used + f_fss_default_allocation_step);
+            if (F_status_is_error(status)) return status;
+          }
+        }
+
+        map_multi = &values[j]->array[values[j]->used];
+
+        status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[0], &map_multi->name);
+        if (F_status_is_error(status)) return status;
+
+        values[j]->used++;
+
+        if (contents.array[i].used > 1) {
+          if (map_multi->value.used + contents.array[i].used - 1 > map_multi->value.size) {
+            if (map_multi->value.used + contents.array[i].used - 1 > f_array_length_size) return F_status_set_error(F_buffer_too_large);
+
+            f_macro_string_dynamics_resize(status, map_multi->value, map_multi->value.used + contents.array[i].used - 1);
+            if (F_status_is_error(status)) return status;
+          }
+
+          for (k = 1; k < contents.array[i].used; k++) {
+            status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[k], &map_multi->value.array[map_multi->value.used]);
+            if (F_status_is_error(status)) return status;
+
+            map_multi->value.used++;
+          } // for
+        }
       } // for
     } // for
 
     return F_none;
   }
-#endif // _di_fll_fss_snatch_together_
+#endif // _di_fll_fss_snatch_map_apart_
 
-#ifndef _di_fll_fss_snatch_mash_
-  f_return_status fll_fss_snatch_mash(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size, const f_string glue, const f_string_length glue_length) {
+#ifndef _di_fll_fss_snatch_map_mash_
+  f_return_status fll_fss_snatch_map_mash(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_maps *values[]) {
     #ifndef _di_level_2_parameter_checking_
       if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
     if (buffer.used == 0) return F_data_not;
@@ -144,7 +303,11 @@ extern "C" {
     f_array_length j = 0;
     f_array_length k = 0;
 
+    f_string_map *map = 0;
+
     for (; i < objects.used; i++) {
+      if (!contents.array[i].used) continue;
+
       length_object = (objects.array[i].stop - objects.array[i].start) + 1;
 
       for (j = 0; j < size; j++) {
@@ -153,9 +316,31 @@ extern "C" {
         if (F_status_is_error(status)) return status;
         if (status == F_equal_to_not) continue;
 
-        if (values[j]->used == 0) {
-          for (k = 0; k < contents.array[i].used; k++) {
-            status = fl_string_dynamic_partial_mash_nulless(glue, glue_length, buffer, contents.array[i].array[k], values[j]);
+        if (values[j]->used + 1 > values[j]->size) {
+          if (values[j]->used + f_fss_default_allocation_step > f_array_length_size) {
+            if (values[j]->used + 1 > f_array_length_size) {
+              return F_status_set_error(F_buffer_too_large);
+            }
+
+            f_macro_string_maps_resize(status, (*values[j]), values[j]->used + 1);
+            if (F_status_is_error(status)) return status;
+          }
+          else {
+            f_macro_string_maps_resize(status, (*values[j]), values[j]->used + f_fss_default_allocation_step);
+            if (F_status_is_error(status)) return status;
+          }
+        }
+
+        map = &values[j]->array[values[j]->used];
+
+        status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[0], &map->name);
+        if (F_status_is_error(status)) return status;
+
+        values[j]->used++;
+
+        if (contents.array[i].used > 1) {
+          for (k = 1; k < contents.array[i].used; k++) {
+            status = fl_string_dynamic_partial_mash_nulless(glue, glue_length, buffer, contents.array[i].array[k], &map->value);
             if (F_status_is_error(status)) return status;
           } // for
         }
@@ -164,12 +349,174 @@ extern "C" {
 
     return F_none;
   }
+#endif // _di_fll_fss_snatch_map_mash_
+
+#ifndef _di_fll_fss_snatch_map_mash_apart_
+  f_return_status fll_fss_snatch_map_mash_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_map_multis *values[]) {
+    #ifndef _di_level_2_parameter_checking_
+      if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
+
+    if (buffer.used == 0) return F_data_not;
+    if (objects.used == 0) return F_data_not;
+    if (contents.used == 0) return F_data_not;
+
+    f_status status = F_none;
+    f_string_length length_name = 0;
+    f_string_dynamic name = f_string_dynamic_initialize;
+
+    f_array_length i = 0;
+    f_array_length j = 0;
+    f_array_length k = 0;
+
+    bool matched = F_false;
+
+    f_string_map_multi *map_multi = 0;
+
+    for (; i < objects.used; i++) {
+      if (!contents.array[i].used) continue;
+
+      length_name = (objects.array[i].stop - objects.array[i].start) + 1;
+
+      for (j = 0; j < size; j++) {
+        status = fl_string_compare_trim(buffer.string + objects.array[i].start, names[j], length_name, lengths[j]);
+
+        if (F_status_is_error(status)) return status;
+        if (status == F_equal_to_not) continue;
+
+        status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[0], &name);
+        if (F_status_is_error(status)) {
+          f_macro_string_dynamic_delete_simple(name);
+          return status;
+        }
+
+        matched = F_false;
+        length_name = (contents.array[i].array[0].stop - contents.array[i].array[0].start) + 1;
+
+        for (k = 0; k < values[j]->used; k++) {
+          status = fl_string_compare_trim(buffer.string + contents.array[i].array[0].start, values[j]->array[k].name.string, length_name, values[j]->array[k].name.used);
+
+          if (F_status_is_error(status)) {
+            f_macro_string_dynamic_delete_simple(name);
+            return status;
+          }
+
+          if (status == F_equal_to) {
+            matched = F_true;
+            break;
+          }
+        } // for
+
+        if (matched) {
+          name.used = 0;
+
+          if (contents.array[i].used == 1) continue;
+
+          map_multi = &values[j]->array[k];
+        }
+        else {
+          if (values[j]->used + 1 > values[j]->size) {
+            if (values[j]->used + f_fss_default_allocation_step > f_array_length_size) {
+              if (values[j]->used + 1 > f_array_length_size) {
+                return F_status_set_error(F_buffer_too_large);
+              }
+
+              f_macro_string_map_multis_resize(status, (*values[j]), values[j]->used + 1);
+              if (F_status_is_error(status)) return status;
+            }
+            else {
+              f_macro_string_map_multis_resize(status, (*values[j]), values[j]->used + f_fss_default_allocation_step);
+              if (F_status_is_error(status)) return status;
+            }
+          }
+
+          map_multi = &values[j]->array[values[j]->used];
+          map_multi->name.string = name.string;
+          map_multi->name.used = name.used;
+          map_multi->name.size = name.size;
+
+          values[j]->used++;
+
+          f_macro_string_dynamic_clear(name);
+
+          if (contents.array[i].used == 1) continue;
+        }
+
+        if (map_multi->value.used + 1 > map_multi->value.size) {
+          if (map_multi->value.used + 1 > f_array_length_size) {
+            return F_status_set_error(F_buffer_too_large);
+          }
+
+          f_macro_string_dynamics_resize(status, map_multi->value, map_multi->value.used + 1);
+          if (F_status_is_error(status)) return status;
+        }
+
+        for (k = 1; k < contents.array[i].used; k++) {
+          status = fl_string_dynamic_partial_mash_nulless(glue, glue_length, buffer, contents.array[i].array[k], &map_multi->value.array[map_multi->value.used]);
+          if (F_status_is_error(status)) return status;
+        } // for
+
+        map_multi->value.used++;
+      } // for
+    } // for
+
+    f_macro_string_dynamic_delete_simple(name);
+    return F_none;
+  }
+#endif // _di_fll_fss_snatch_map_mash_apart_
+
+#ifndef _di_fll_fss_snatch_mash_
+  f_return_status fll_fss_snatch_mash(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_dynamic *values[]) {
+    #ifndef _di_level_2_parameter_checking_
+      if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
+
+    if (buffer.used == 0) return F_data_not;
+    if (objects.used == 0) return F_data_not;
+    if (contents.used == 0) return F_data_not;
+
+    f_status status = F_none;
+    f_string_length length_object = 0;
+
+    f_array_length i = 0;
+    f_array_length j = 0;
+    f_array_length k = 0;
+
+    bool matched[size];
+
+    memset(&matched, 0, sizeof(bool) * size);
+
+    for (; i < objects.used; i++) {
+      length_object = (objects.array[i].stop - objects.array[i].start) + 1;
+
+      for (j = 0; j < size; j++) {
+        if (matched[j]) continue;
+
+        status = fl_string_compare_trim(buffer.string + objects.array[i].start, names[j], length_object, lengths[j]);
+
+        if (F_status_is_error(status)) return status;
+        if (status == F_equal_to_not) continue;
+
+        matched[j] = F_true;
+
+        for (k = 0; k < contents.array[i].used; k++) {
+          status = fl_string_dynamic_partial_mash_nulless(glue, glue_length, buffer, contents.array[i].array[k], values[j]);
+          if (F_status_is_error(status)) return status;
+        } // for
+      } // for
+    } // for
+
+    return F_none;
+  }
 #endif // _di_fll_fss_snatch_mash_
 
 #ifndef _di_fll_fss_snatch_mash_apart_
-  f_return_status fll_fss_snatch_mash_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamics *values[], const f_string_length size, const f_string glue, const f_string_length glue_length) {
+  f_return_status fll_fss_snatch_mash_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_dynamics *values[]) {
     #ifndef _di_level_2_parameter_checking_
       if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
     if (buffer.used == 0) return F_data_not;
@@ -212,12 +559,8 @@ extern "C" {
           if (F_status_is_error(status)) return status;
         } // for
 
-        if (F_status_is_error(status)) return status;
-
         values[j]->used++;
       } // for
-
-      if (F_status_is_error(status)) return status;
     } // for
 
     return F_none;
@@ -225,9 +568,10 @@ extern "C" {
 #endif // _di_fll_fss_snatch_mash_apart_
 
 #ifndef _di_fll_fss_snatch_mash_together_
-  f_return_status fll_fss_snatch_mash_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size, const f_string glue, const f_string_length glue_length) {
+  f_return_status fll_fss_snatch_mash_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_dynamic *values[]) {
     #ifndef _di_level_2_parameter_checking_
       if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
     #endif // _di_level_2_parameter_checking_
 
     if (buffer.used == 0) return F_data_not;
@@ -261,6 +605,44 @@ extern "C" {
   }
 #endif // _di_fll_fss_snatch_mash_together_
 
+#ifndef _di_fll_fss_snatch_together_
+  f_return_status fll_fss_snatch_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_dynamic *values[]) {
+    #ifndef _di_level_2_parameter_checking_
+      if (size == 0) return F_status_set_error(F_parameter);
+      if (objects.used != contents.used) return F_status_set_error(F_parameter);
+    #endif // _di_level_2_parameter_checking_
+
+    if (buffer.used == 0) return F_data_not;
+    if (objects.used == 0) return F_data_not;
+    if (contents.used == 0) return F_data_not;
+
+    f_status status = F_none;
+    f_string_length length_object = 0;
+
+    f_array_length i = 0;
+    f_array_length j = 0;
+    f_array_length k = 0;
+
+    for (; i < objects.used; i++) {
+      length_object = (objects.array[i].stop - objects.array[i].start) + 1;
+
+      for (j = 0; j < size; j++) {
+        status = fl_string_compare_trim(buffer.string + objects.array[i].start, names[j], length_object, lengths[j]);
+
+        if (F_status_is_error(status)) return status;
+        if (status == F_equal_to_not) continue;
+
+        for (k = 0; k < contents.array[i].used; k++) {
+          status = fl_string_dynamic_partial_append_nulless(buffer, contents.array[i].array[k], values[j]);
+          if (F_status_is_error(status)) return status;
+        } // for
+      } // for
+    } // for
+
+    return F_none;
+  }
+#endif // _di_fll_fss_snatch_together_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 7985e97191a57dd71a9c45830479d77269d903f9..7714daae6dbc40f28b316fead0e06175e1f75887 100644 (file)
@@ -33,16 +33,14 @@ extern "C" {
 /**
  * Perform simple search through all objects against the given set, saving all values when matched.
  *
- * Multiple contents for a single object are appended.
- * Only content for the first of each identical object is snatched, all others are ignored.
+ * Only the first match for each distinct object is snatched.
+ * Only the first content for each object is snatched.
  *
  * This will trim the object names when comparing (removing leading/trailing whitespace).
- * This will strip NULL charactes when copying.
+ * This will strip NULL characters when copying.
  *
  * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
  *
- * This assumes values[].used is 0 at start to determine if value is already snatched.
- *
  * @param buffer
  *   The buffer to read from.
  * @param objects
@@ -53,31 +51,36 @@ extern "C" {
  *   An array of strings to "snatch" from the buffer.
  * @param lengths
  *   An array of lengths for each names string.
- * @param values
- *   An array of values where "snatched" content is stored.
  * @param size
  *   The total size of the names, lengths, and values arrays.
+ * @param values
+ *   An array of values where "snatched" content is stored.
  *
  * @return
  *   F_none on success.
  *   F_data_not when there is no buffer, objects or contents to process.
- *   F_memory_reallocation (with error bit) on reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if any combined string is too large when processing values.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_append_nulless().
+ *
+ * @see fl_string_compare_trim()
+ * @see fl_string_dynamic_partial_append_nulless()
  */
 #ifndef _di_fll_fss_snatch_
-  extern f_return_status fll_fss_snatch(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size);
+  extern f_return_status fll_fss_snatch(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_dynamic *values[]);
 #endif // _di_fll_fss_snatch_
 
 /**
  * Perform simple search through all objects against the given set, saving all values when matched.
  *
- * All matches for each name is snatched.
+ * All matches for each object is snatched.
+ * All content for each object is snatched.
+ *
  * Multiple contents for a single object are stored in separate strings.
- * Content for multiple identical objects are added in separate strings from other objects.
  *
  * This will trim the object names when comparing (removing leading/trailing whitespace).
- * This will strip NULL charactes when copying.
+ * This will strip NULL characters when copying.
  *
  * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
  *
@@ -91,32 +94,38 @@ extern "C" {
  *   An array of strings to "snatch" from the buffer.
  * @param lengths
  *   An array of lengths for each names string.
- * @param values
- *   An array of values where "snatched" content is stored.
  * @param size
  *   The total size of the names, lengths, and values arrays.
+ * @param values
+ *   An array of values where "snatched" content is stored.
  *
  * @return
  *   F_none on success.
  *   F_data_not when there is no buffer, objects or contents to process.
- *   F_memory_reallocation (with error bit) on reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
- *   F_buffer_too_large (with error bit) on maximum buffer limit reached when processing values.
- *   F_string_too_large (with error bit) if any combined string is too large when processing values.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_append_nulless().
+ *
+ * @see fl_string_compare_trim()
+ * @see fl_string_dynamic_partial_append_nulless()
  */
 #ifndef _di_fll_fss_snatch_apart_
-  extern f_return_status fll_fss_snatch_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamics *values[], const f_string_length size);
+  extern f_return_status fll_fss_snatch_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_dynamics *values[]);
 #endif // _di_fll_fss_snatch_apart_
 
 /**
- * Perform simple search through all objects against the given set, saving all values when matched.
+ * Perform simple search through all objects against the given set, saving all values to a map when matched.
  *
- * All matches for each name is snatched.
- * Multiple contents for a single object are appended.
- * Content for multiple identical objects are appended.
+ * Only the first match for each distinct object and map name is snatched (map names are therefore distinct).
+ * Only the first content map value for each object and map name is snatched.
+ *
+ * The first content is considered the map name, all other content are considered a map value.
+ *
+ * This will ignore any object that has no map name.
  *
  * This will trim the object names when comparing (removing leading/trailing whitespace).
- * This will strip NULL charactes when copying.
+ * This will strip NULL characters when copying.
  *
  * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
  *
@@ -130,34 +139,136 @@ extern "C" {
  *   An array of strings to "snatch" from the buffer.
  * @param lengths
  *   An array of lengths for each names string.
+ * @param size
+ *   The total size of the names, lengths, and values arrays.
  * @param values
- *   An array of values where "snatched" content is stored.
+ *   An array of map arrays where "snatched" content is stored.
+ *
+ * @return
+ *   F_none on success.
+ *   F_data_not when there is no buffer, objects or contents to process.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_append_nulless().
+ *
+ * @see fl_string_compare_trim()
+ * @see fl_string_dynamic_partial_append_nulless()
+ */
+#ifndef _di_fll_fss_snatch_map_
+  extern f_return_status fll_fss_snatch_map(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_maps *values[]);
+#endif // _di_fll_fss_snatch_map_
+
+/**
+ * Perform simple search through all objects against the given set, saving all values to a multi map when matched.
+ *
+ * All matches for each object and map name is snatched.
+ * All content map values for each object and map name is snatched.
+ *
+ * The first content value is considered the map name, all other content values are considered a map value.
+ * Multiple contents, after the first, for a single object are stored in separate map value strings.
+ * Content for multiple identical objects and map names are added in separate maps from other objects (map names are therefore non-distinct).
+ *
+ * This will ignore any object that has no map name.
+ *
+ * This will trim the object names when comparing (removing leading/trailing whitespace).
+ * This will strip NULL characters when copying.
+ *
+ * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
+ *
+ * @param buffer
+ *   The buffer to read from.
+ * @param objects
+ *   This object mappings to process.
+ * @param contents
+ *   This content mappings to process.
+ * @param names
+ *   An array of strings to "snatch" from the buffer.
+ * @param lengths
+ *   An array of lengths for each names string.
  * @param size
  *   The total size of the names, lengths, and values arrays.
+ * @param values
+ *   An array of multi map arrays where "snatched" content is stored.
  *
  * @return
  *   F_none on success.
  *   F_data_not when there is no buffer, objects or contents to process.
- *   F_memory_reallocation (with error bit) on reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if any combined string is too large when processing values.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_append_nulless().
+ *
+ * @see fl_string_compare_trim()
+ * @see fl_string_dynamic_partial_append_nulless()
  */
-#ifndef _di_fll_fss_snatch_together_
-  extern f_return_status fll_fss_snatch_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size);
-#endif // _di_fll_fss_snatch_together_
+#ifndef _di_fll_fss_snatch_map_apart_
+  extern f_return_status fll_fss_snatch_map_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_map_multis *values[]);
+#endif // _di_fll_fss_snatch_map_apart_
 
 /**
- * Perform simple search through all objects against the given set, saving all values when matched.
+ * Perform simple search through all objects against the given set, saving all values to a map when matched.
  *
- * Multiple contents for a single object are appended using the provided glue.
- * Only content for the first of each identical object is snatched, all others are ignored.
+ * Only the first match for each distinct object and map name is snatched (map names are therefore distinct).
+ * All content values for each object and map name is snatched.
+ *
+ * The first content value is considered the map name, all other content values are considered a map value.
+ * Multiple contents, after the first, for a single object are appended to a single map value string using the provided glue.
+ *
+ * This will ignore any object that has no map name.
  *
  * This will trim the object names when comparing (removing leading/trailing whitespace).
- * This will strip NULL charactes when copying.
+ * This will strip NULL characters when copying.
  *
  * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
  *
- * This assumes values[].used is 0 at start to determine if value is already snatched.
+ * @param buffer
+ *   The buffer to read from.
+ * @param objects
+ *   This object mappings to process.
+ * @param contents
+ *   This content mappings to process.
+ * @param names
+ *   An array of strings to "snatch" from the buffer.
+ * @param lengths
+ *   An array of lengths for each names string.
+ * @param size
+ *   The total size of the names, lengths, and values arrays.
+ * @param glue
+ *   A string to append between each duplicate name found when "snatching".
+ * @param glue_length
+ *   The length of the glue string
+ * @param values
+ *   An array of multi map value arrays where "snatched" content is stored.
+ *
+ * @return
+ *   F_none on success.
+ *   F_data_not when there is no buffer, objects or contents to process.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_mash_nulless().
+ */
+#ifndef _di_fll_fss_snatch_map_mash_
+  extern f_return_status fll_fss_snatch_map_mash(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_maps *values[]);
+#endif // _di_fll_fss_snatch_map_mash_
+
+/**
+ * Perform simple search through all objects against the given set, saving all values to a multi map when matched.
+ *
+ * All matches for each object is snatched.
+ * All content for each object and map name is snatched.
+ *
+ * The first content value is considered the map name, all other content values are considered a map value.
+ * Multiple contents, after the first, for a single object are appended to a single map value string using the provided glue.
+ * Content for multiple identical objects are added in separate maps from other objects (map names are therefore non-distinct).
+ *
+ * This will ignore any object that has no map name.
+ *
+ * This will trim the object names when comparing (removing leading/trailing whitespace).
+ * This will strip NULL characters when copying.
+ *
+ * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
  *
  * @param buffer
  *   The buffer to read from.
@@ -169,35 +280,85 @@ extern "C" {
  *   An array of strings to "snatch" from the buffer.
  * @param lengths
  *   An array of lengths for each names string.
+ * @param size
+ *   The total size of the names, lengths, and values arrays.
+ * @param glue
+ *   A string to append between each duplicate name found when "snatching".
+ * @param glue_length
+ *   The length of the glue string
  * @param values
- *   An array of values where "snatched" content is stored.
+ *   An array of multi map value arrays where "snatched" content is stored.
+ *
+ * @return
+ *   F_none on success.
+ *   F_data_not when there is no buffer, objects or contents to process.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_append_nulless().
+ *
+ * @see fl_string_compare_trim()
+ * @see fl_string_dynamic_partial_append_nulless()
+ */
+#ifndef _di_fll_fss_snatch_map_mash_apart_
+  extern f_return_status fll_fss_snatch_map_mash_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_map_multis *values[]);
+#endif // _di_fll_fss_snatch_map_mash_apart_
+
+/**
+ * Perform simple search through all objects against the given set, saving all values when matched.
+ *
+ * Only the first match for each distinct object is snatched.
+ * All content for each object is snatched.
+ *
+ * Multiple contents for a single object are appended using the provided glue.
+ *
+ * This will trim the object names when comparing (removing leading/trailing whitespace).
+ * This will strip NULL characters when copying.
+ *
+ * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
+ *
+ * @param buffer
+ *   The buffer to read from.
+ * @param objects
+ *   This object mappings to process.
+ * @param contents
+ *   This content mappings to process.
+ * @param names
+ *   An array of strings to "snatch" from the buffer.
+ * @param lengths
+ *   An array of lengths for each names string.
  * @param size
  *   The total size of the names, lengths, and values arrays.
  * @param glue
  *   A string to append between each duplicate name found when "snatching".
  * @param glue_length
  *   The length of the glue string.
+ * @param values
+ *   An array of values where "snatched" content is stored.
  *
  * @return
  *   F_none on success.
  *   F_data_not when there is no buffer, objects or contents to process.
- *   F_memory_reallocation (with error bit) on reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if any combined string is too large when processing values.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_mash_nulless().
  */
 #ifndef _di_fll_fss_snatch_mash_
-  extern f_return_status fll_fss_snatch_mash(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size, const f_string glue, const f_string_length glue_length);
+  extern f_return_status fll_fss_snatch_mash(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_dynamic *values[]);
 #endif // _di_fll_fss_snatch_mash_
 
 /**
  * Perform simple search through all objects against the given set, saving all values when matched.
  *
- * All matches for each name is snatched.
+ * All matches for each object is snatched.
+ * All content for each object is snatched.
+ *
  * Multiple contents for a single object are appended using the provided glue.
  * Content for multiple identical objects are added in separate strings from other objects.
  *
  * This will trim the object names when comparing (removing leading/trailing whitespace).
- * This will strip NULL charactes when copying.
+ * This will strip NULL characters when copying.
  *
  * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
  *
@@ -211,38 +372,44 @@ extern "C" {
  *   An array of strings to "snatch" from the buffer.
  * @param lengths
  *   An array of lengths for each names string.
- * @param values
- *   An array of values where "snatched" content is stored.
  * @param size
  *   The total size of the names, lengths, and values arrays.
  * @param glue
  *   A string to append between each duplicate name found when "snatching".
  * @param glue_length
- *   The length of the glue string.
+ *   The length of the glue string
+ * @param values
+ *   An array of values where "snatched" content is stored.
  *
  * @return
  *   F_none on success.
  *   F_data_not when there is no buffer, objects or contents to process.
- *   F_memory_reallocation (with error bit) on reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if any combined string is too large when processing values.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_append_nulless().
+ *
+ * @see fl_string_compare_trim()
+ * @see fl_string_dynamic_partial_append_nulless()
  */
 #ifndef _di_fll_fss_snatch_mash_apart_
-  extern f_return_status fll_fss_snatch_mash_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamics *values[], const f_string_length size, const f_string glue, const f_string_length glue_length);
+  extern f_return_status fll_fss_snatch_mash_apart(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_dynamics *values[]);
 #endif // _di_fll_fss_snatch_mash_apart_
 
 /**
  * Perform simple search through all objects against the given set, saving all values when matched.
  *
- * All matches for each name is snatched.
+ * All matches for each object is snatched.
  * Multiple contents for a single object are appended using the provided glue.
  * Content for multiple identical objects are appended using the provided glue.
  *
  * This will trim the object names when comparing (removing leading/trailing whitespace).
- * This will strip NULL charactes when copying.
+ * This will strip NULL characters when copying.
  *
  * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
  *
+ * @fixme redesign to match all based on content column, mash each value by glue for each column, and finally mash each column into the final dynamic value.
+ *
  * @param buffer
  *   The buffer to read from.
  * @param objects
@@ -253,26 +420,71 @@ extern "C" {
  *   An array of strings to "snatch" from the buffer.
  * @param lengths
  *   An array of lengths for each names string.
- * @param values
- *   An array of values where "snatched" content is stored.
  * @param size
  *   The total size of the names, lengths, and values arrays.
  * @param glue
  *   A string to append between each duplicate name found when "snatching".
  * @param glue_length
  *   The length of the glue string.
+ * @param values
+ *   An array of values where "snatched" content is stored.
  *
  * @return
  *   F_none on success.
  *   F_data_not when there is no buffer, objects or contents to process.
- *   F_memory_reallocation (with error bit) on reallocation error.
  *   F_parameter (with error bit) if a parameter is invalid.
- *   F_string_too_large (with error bit) if any combined string is too large when processing values.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_mash_nulless().
  */
 #ifndef _di_fll_fss_snatch_mash_together_
-  extern f_return_status fll_fss_snatch_mash_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], f_string_dynamic *values[], const f_string_length size, const f_string glue, const f_string_length glue_length);
+  extern f_return_status fll_fss_snatch_mash_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, const f_string glue, const f_string_length glue_length, f_string_dynamic *values[]);
 #endif // _di_fll_fss_snatch_mash_together_
 
+/**
+ * Perform simple search through all objects against the given set, saving all values when matched.
+ *
+ * All matches for each object is snatched.
+ * Multiple contents for a single object are appended.
+ * Content for multiple identical objects are appended.
+ *
+ * This will trim the object names when comparing (removing leading/trailing whitespace).
+ * This will strip NULL characters when copying.
+ *
+ * This performs only a simple search algorithm that should be acceptable for small sets where performance is generally not a concern.
+ *
+ * @fixme redesign to match all based on content column, mash each value by glue for each column, storing them as separate content string.
+ *
+ * @param buffer
+ *   The buffer to read from.
+ * @param objects
+ *   This object mappings to process.
+ * @param contents
+ *   This content mappings to process.
+ * @param names
+ *   An array of strings to "snatch" from the buffer.
+ * @param lengths
+ *   An array of lengths for each names string.
+ * @param size
+ *   The total size of the names, lengths, and values arrays.
+ * @param values
+ *   An array of values where "snatched" content is stored.
+ *
+ * @return
+ *   F_none on success.
+ *   F_data_not when there is no buffer, objects or contents to process.
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors from (with error bit): fl_string_compare_trim().
+ *   Errors from (with error bit): fl_string_dynamic_partial_append_nulless().
+ *
+ * @see fl_string_compare_trim()
+ * @see fl_string_dynamic_partial_append_nulless()
+ */
+#ifndef _di_fll_fss_snatch_together_
+  extern f_return_status fll_fss_snatch_together(const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, const f_string names[], const f_string_length lengths[], const f_string_length size, f_string_dynamic *values[]);
+#endif // _di_fll_fss_snatch_together_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index d4277655bad05d01bb88874217a9b3e89c4755c7..b92d4435ecebc3d04b1efc19f0f4a5bd38858ee0 100644 (file)
@@ -267,7 +267,7 @@ extern "C" {
 
       status = fake_process_console_parameters(arguments, data);
 
-      if (!F_status_is_error(status)) {
+      if (F_status_is_not_error(status)) {
         status = fake_path_generate(data);
       }
 
@@ -285,7 +285,7 @@ extern "C" {
             validate_parameter_directories = F_false;
           }
 
-          if (!F_status_is_error(status)) {
+          if (F_status_is_not_error(status)) {
             status = fake_build_operate(*data);
           }
         }
@@ -295,7 +295,7 @@ extern "C" {
             validate_parameter_directories = F_false;
           }
 
-          if (!F_status_is_error(status)) {
+          if (F_status_is_not_error(status)) {
             status = fake_clean_operate(*data);
           }
         }
@@ -305,12 +305,16 @@ extern "C" {
             validate_parameter_directories = F_false;
           }
 
-          if (data->verbosity != fake_verbosity_quiet) {
+          if (F_status_is_not_error(status)) {
+            status = fake_make_operate(*data);
+          }
+
+          /*if (data->verbosity != fake_verbosity_quiet) {
             fprintf(f_type_error, "%c", f_string_eol[0]);
             fl_color_print(f_type_error, data->context.error, data->context.reset, "ERROR: the operation '");
             fl_color_print(f_type_error, data->context.notable, data->context.reset, "%s", fake_other_operation_make);
             fl_color_print_line(f_type_error, data->context.error, data->context.reset, "' is not yet implemented.");
-          }
+          }*/
         }
         else if (operations[i] == fake_operation_skeleton) {
           status = fake_skeleton_operate(*data);
@@ -412,6 +416,7 @@ extern "C" {
 
     f_macro_string_dynamic_delete_simple(data->file_data_build_defines);
     f_macro_string_dynamic_delete_simple(data->file_data_build_dependencies);
+    f_macro_string_dynamic_delete_simple(data->file_data_build_fakefile);
     f_macro_string_dynamic_delete_simple(data->file_data_build_settings);
 
     f_macro_string_dynamic_delete_simple(data->file_documents_readme);
index fef82a0e7b939457bd39f4030fe4c94bbc0ded41..e15b6987c67778712dd3c0cd28493fe09512d8d7 100644 (file)
@@ -39,9 +39,6 @@
  * The "progams/" directory will contain compiled programs or program-like scripts in their respective sub-directories.
  * The "settings/" directory contains all configuration data, such as files commonly found under /etc in a standard GNU Linux system.
  * The "stage/" directory will contain build-time data.
- *
- * @todo this will eventually support fakefile, which is akin to makefile.
- *       All of the setting data will be loaded and available for a fakefile.
  */
 #ifndef _fake_h
 
@@ -69,6 +66,7 @@
 // fll-2 includes
 #include <level_2/execute.h>
 #include <level_2/fss.h>
+#include <level_2/fss_basic_list.h>
 #include <level_2/fss_extended.h>
 #include <level_2/program.h>
 
@@ -140,6 +138,7 @@ extern "C" {
 #ifndef _di_fake_file_
   #define fake_file_defines      "defines"
   #define fake_file_dependencies "dependencies"
+  #define fake_file_fakefile     "fakefile"
   #define fake_file_process_post "process_post.sh"
   #define fake_file_process_pre  "process_pre.sh"
   #define fake_file_readme       "readme"
@@ -147,6 +146,7 @@ extern "C" {
 
   #define fake_file_defines_length      7
   #define fake_file_dependencies_length 12
+  #define fake_file_fakefile_length     8
   #define fake_file_process_post_length 15
   #define fake_file_process_pre_length  14
   #define fake_file_readme_length       6
@@ -420,7 +420,9 @@ extern "C" {
 
     f_string_dynamic file_data_build_defines;
     f_string_dynamic file_data_build_dependencies;
+    f_string_dynamic file_data_build_fakefile;
     f_string_dynamic file_data_build_settings;
+
     f_string_dynamic file_documents_readme;
 
     fl_color_context context;
@@ -478,6 +480,7 @@ extern "C" {
       f_string_dynamic_initialize, \
       f_string_dynamic_initialize, \
       f_string_dynamic_initialize, \
+      f_string_dynamic_initialize, \
       fl_color_context_initialize, \
     }
 #endif // _di_fake_data_
index a3ffd1e151f5aa098ca10af01a9bd08456eeaa53..8f5636730f41d046c1e7aada3fff616b4868a3fd 100644 (file)
@@ -395,7 +395,10 @@ extern "C" {
       *status = f_directory_create(directorys[i]->string, mode);
 
       if (F_status_is_error(*status)) {
-        if (F_status_set_fine(*status) == F_file_found) continue;
+        if (F_status_set_fine(*status) == F_file_found) {
+          *status = F_none;
+          continue;
+        }
 
         fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), "f_directory_create", directorys[i]->string, "create", F_false, F_true);
         return;
@@ -420,7 +423,7 @@ extern "C" {
     *status = fll_execute_arguments_add(fake_other_operation_build, fake_other_operation_build_length, &arguments);
 
     // ensure console color mode is passed to the scripts so that they can also react to color mode.
-    if (!F_status_is_error(*status) && data.context.mode != f_color_mode_none) {
+    if (F_status_is_not_error(*status) && data.context.mode != f_color_mode_none) {
       char argument[3] = { f_console_symbol_disable, 0, 0 };
 
       if (data.context.mode == f_color_mode_dark) {
@@ -437,7 +440,7 @@ extern "C" {
     }
 
     // ensure verbosity level is passed to the scripts so that they can also react to requested verbosity.
-    if (!F_status_is_error(*status) && data.verbosity != fake_verbosity_normal) {
+    if (F_status_is_not_error(*status) && data.verbosity != fake_verbosity_normal) {
       char argument[3] = { f_console_symbol_disable, 0, 0 };
 
       if (data.verbosity == fake_verbosity_quiet) {
@@ -572,11 +575,11 @@ extern "C" {
         *status = fl_string_dynamic_append_nulless(data.path_data_build, &path);
       }
 
-      if (!F_status_is_error(*status)) {
+      if (F_status_is_not_error(*status)) {
         *status = fl_string_dynamic_append_nulless(process_script, &path);
       }
 
-      if (!F_status_is_error(*status)) {
+      if (F_status_is_not_error(*status)) {
         function = "fl_string_dynamic_terminate_after";
         *status = fl_string_dynamic_terminate_after(&path);
       }
@@ -875,6 +878,15 @@ extern "C" {
       if (F_status_is_fine(*status) && data.verbosity == fake_verbosity_verbose) {
         printf("Linked file '%s' to '%s'.%c", parameter_file_path, parameter_file_name_micro, f_string_eol[0]);
       }
+      else if (F_status_is_error(*status)) {
+        if (F_status_set_fine(*status) == F_file_found) {
+          fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), "f_file_link", parameter_file_path, "link", F_true, F_true);
+          return;
+        }
+
+        fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), "f_file_link", parameter_file_name_micro, "link", F_true, F_true);
+        return;
+      }
     }
 
     if (F_status_is_fine(*status)) {
@@ -913,11 +925,25 @@ extern "C" {
 
         printf("'.%c", f_string_eol[0]);
       }
-    }
+      else if (F_status_is_error(*status)) {
+        if (F_status_set_fine(*status) == F_file_found) {
+          fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), "f_file_link", parameter_file_path, "link", F_true, F_true);
 
-    if (F_status_is_error(*status)) {
-      fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "f_file_link", F_true);
-      return;
+          return;
+        }
+
+        if (data_build.setting.version_target == fake_build_version_type_major) {
+          fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), "f_file_link", parameter_file_name_major, "link", F_true, F_true);
+        }
+        else if (data_build.setting.version_target == fake_build_version_type_minor) {
+          fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), "f_file_link", parameter_file_name_minor, "link", F_true, F_true);
+        }
+        else if (data_build.setting.version_target == fake_build_version_type_micro) {
+          fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), "f_file_link", parameter_file_name_micro, "link", F_true, F_true);
+        }
+
+        return;
+      }
     }
 
     fake_build_touch(data, file_stage, status);
@@ -1054,7 +1080,7 @@ extern "C" {
 #endif // _di_fake_build_library_static_
 
 #ifndef _di_fake_build_load_environment_
-  void fake_build_load_environment(const fake_data data, const fake_build_data data_build, fake_build_environment *environment, f_status *status) {
+  void fake_build_load_environment(const fake_data data, const fake_build_data data_build, fake_environment *environment, f_status *status) {
     if (F_status_is_error(*status)) return;
 
     f_string_dynamics names = f_string_dynamics_initialize;
@@ -1093,7 +1119,7 @@ extern "C" {
         f_macro_string_dynamic_clear(part);
       } // for
 
-      if (!F_status_is_error(*status)) {
+      if (F_status_is_not_error(*status)) {
         if (names.used + data_build.setting.environment.used > names.size) {
           if (names.used + data_build.setting.environment.used > f_array_length_size) {
             if (data.verbosity != fake_verbosity_quiet) {
@@ -1160,7 +1186,7 @@ extern "C" {
       if (environment->names.used + 1 > environment->names.size) {
         f_macro_string_dynamics_resize(*status, environment->names, environment->names.size + f_memory_default_allocation_step);
 
-        if (!F_status_is_error(*status)) {
+        if (F_status_is_not_error(*status)) {
           f_macro_string_dynamics_resize(*status, environment->values, environment->values.size + f_memory_default_allocation_step);
         }
 
@@ -1205,698 +1231,648 @@ extern "C" {
   void fake_build_load_setting(const fake_data data, fake_build_setting *setting, f_status *status) {
     if (F_status_is_error(*status)) return;
 
-    f_file file = f_file_initialize;
-    f_string_dynamic buffer = f_string_dynamic_initialize;
-
-    *status = F_none;
-
     {
-      f_string name_function = f_string_initialize;
+      f_string_dynamic buffer = f_string_dynamic_initialize;
 
-      name_function = "f_file_exists";
-      *status = f_file_exists(data.file_data_build_settings.string);
+      f_fss_objects objects = f_fss_objects_initialize;
+      f_fss_contents contents = f_fss_contents_initialize;
 
-      if (*status == F_true) {
-        name_function = "f_file_open";
-        *status = f_file_open(data.file_data_build_settings.string, 0, &file);
+      *status = fake_file_buffer(data, data.file_data_build_settings.string, &buffer);
+      if (F_status_is_error(*status)) return;
 
-        if (*status == F_none) {
-          name_function = "f_file_read";
-          *status = f_file_read(file, &buffer);
+      f_string_range range = f_macro_string_range_initialize(buffer.used);
 
-          f_file_close(&file.id);
-        }
-      }
-      else if (*status == F_false) {
-        *status = F_status_set_error(F_file_found_not);
+      *status = fll_fss_extended_read(&buffer, &range, &objects, &contents);
+      if (F_status_is_error(*status)) {
+        fake_print_error_fss(data.context, data.verbosity, *status, "fll_fss_extended_read", data.file_data_build_settings.string, range, F_true);
       }
 
-      if (F_status_is_error(*status)) {
-        fake_print_error_file(data.context, data.verbosity, F_status_set_fine(*status), name_function, data.file_data_build_settings.string, "create", F_true, F_true);
+      fake_build_load_setting_process(data, data.file_data_build_settings.string, buffer, objects, contents, setting, status);
 
-        f_macro_string_dynamic_delete_simple(buffer);
-        return;
-      }
+      f_macro_string_dynamic_delete_simple(buffer);
+      f_macro_fss_objects_delete_simple(objects);
+      f_macro_fss_contents_delete_simple(contents);
     }
 
-    if (buffer.used > 0) {
-      f_fss_objects objects = f_fss_objects_initialize;
-      f_fss_contents contents = f_fss_contents_initialize;
-      f_string_range range = f_string_range_initialize;
-      bool error_printed = F_false;
+    // error when required settings are not specified.
+    if (F_status_is_not_error(*status)) {
+      bool failed = F_false;
 
-      range.start = 0;
-      range.stop = buffer.used - 1;
+      f_string_static *settings[] = {
+        &setting->project_name,
+      };
 
-      *status = fll_fss_extended_read(&buffer, &range, &objects, &contents);
+      f_string names[] = {
+        fake_build_setting_name_project_name,
+      };
 
-      if (F_status_is_error(*status)) {
-        f_macro_fss_objects_delete_simple(objects);
-        f_macro_fss_contents_delete_simple(contents);
-        f_macro_string_dynamic_delete_simple(buffer);
+      for (uint8_t i = 0; i < 1; i++) {
+        if (settings[i]->used == 0) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: the setting '");
+          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", names[i]);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "' is required but is not specified in the settings file '");
+          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
+          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
 
-        if (*status == F_status_set_error(F_incomplete_utf_stop)) {
-          if (data.verbosity != fake_verbosity_quiet) {
-            fprintf(f_type_error, "%c", f_string_eol[0]);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, "ENCODING ERROR: error occurred on invalid UTF-8 character at stop position (at ");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%d", range.start);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, " of setting file '");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "').");
-          }
-        }
-        else if (*status == F_status_set_error(F_incomplete_utf_stop)) {
-          if (data.verbosity != fake_verbosity_quiet) {
-            fprintf(f_type_error, "%c", f_string_eol[0]);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, "ENCODING ERROR: error occurred on invalid UTF-8 character at end of string (at ");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%d", range.start);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, " of setting file '");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "').");
-          }
-        }
-        else {
-          fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fll_fss_extended_read", F_true);
+          failed = F_true;
         }
+      } // for
 
-        f_macro_fss_objects_delete_simple(objects);
-        f_macro_fss_contents_delete_simple(contents);
-        f_macro_string_dynamic_delete_simple(buffer);
-
+      if (failed) {
+        *status = F_status_set_error(F_failure);
         return;
       }
+    }
 
-      {
-        const f_string settings_name[] = {
-          fake_build_setting_name_build_compiler,
-          fake_build_setting_name_build_language,
-          fake_build_setting_name_build_libraries,
-          fake_build_setting_name_build_linker,
-          fake_build_setting_name_build_script,
-          fake_build_setting_name_build_shared,
-          fake_build_setting_name_build_sources_headers,
-          fake_build_setting_name_build_sources_library,
-          fake_build_setting_name_build_sources_program,
-          fake_build_setting_name_build_sources_settings,
-          fake_build_setting_name_build_sources_script,
-          fake_build_setting_name_build_static,
-          fake_build_setting_name_defines_all,
-          fake_build_setting_name_defines_shared,
-          fake_build_setting_name_defines_static,
-          fake_build_setting_name_environment,
-          fake_build_setting_name_flags_all,
-          fake_build_setting_name_flags_library,
-          fake_build_setting_name_flags_program,
-          fake_build_setting_name_flags_shared,
-          fake_build_setting_name_flags_static,
-          fake_build_setting_name_modes,
-          fake_build_setting_name_modes_default,
-          fake_build_setting_name_path_headers,
-          fake_build_setting_name_path_language,
-          fake_build_setting_name_path_library_script,
-          fake_build_setting_name_path_library_shared,
-          fake_build_setting_name_path_library_static,
-          fake_build_setting_name_path_program_script,
-          fake_build_setting_name_path_program_shared,
-          fake_build_setting_name_path_program_static,
-          fake_build_setting_name_process_post,
-          fake_build_setting_name_process_pre,
-          fake_build_setting_name_project_name,
-          fake_build_setting_name_search_exclusive,
-          fake_build_setting_name_search_shared,
-          fake_build_setting_name_search_static,
-          fake_build_setting_name_version_major,
-          fake_build_setting_name_version_micro,
-          fake_build_setting_name_version_minor,
-          fake_build_setting_name_version_target,
-        };
-
-        const f_string_length settings_length[] = {
-          fake_build_setting_name_build_compiler_length,
-          fake_build_setting_name_build_language_length,
-          fake_build_setting_name_build_libraries_length,
-          fake_build_setting_name_build_linker_length,
-          fake_build_setting_name_build_script_length,
-          fake_build_setting_name_build_shared_length,
-          fake_build_setting_name_build_sources_headers_length,
-          fake_build_setting_name_build_sources_library_length,
-          fake_build_setting_name_build_sources_program_length,
-          fake_build_setting_name_build_sources_settings_length,
-          fake_build_setting_name_build_sources_script_length,
-          fake_build_setting_name_build_static_length,
-          fake_build_setting_name_defines_all_length,
-          fake_build_setting_name_defines_shared_length,
-          fake_build_setting_name_defines_static_length,
-          fake_build_setting_name_environment_length,
-          fake_build_setting_name_flags_all_length,
-          fake_build_setting_name_flags_library_length,
-          fake_build_setting_name_flags_program_length,
-          fake_build_setting_name_flags_shared_length,
-          fake_build_setting_name_flags_static_length,
-          fake_build_setting_name_modes_length,
-          fake_build_setting_name_modes_default_length,
-          fake_build_setting_name_path_headers_length,
-          fake_build_setting_name_path_language_length,
-          fake_build_setting_name_path_library_script_length,
-          fake_build_setting_name_path_library_shared_length,
-          fake_build_setting_name_path_library_static_length,
-          fake_build_setting_name_path_program_script_length,
-          fake_build_setting_name_path_program_shared_length,
-          fake_build_setting_name_path_program_static_length,
-          fake_build_setting_name_process_post_length,
-          fake_build_setting_name_process_pre_length,
-          fake_build_setting_name_project_name_length,
-          fake_build_setting_name_search_exclusive_length,
-          fake_build_setting_name_search_shared_length,
-          fake_build_setting_name_search_static_length,
-          fake_build_setting_name_version_major_length,
-          fake_build_setting_name_version_micro_length,
-          fake_build_setting_name_version_minor_length,
-          fake_build_setting_name_version_target_length,
-        };
-
-        f_string_dynamics build_compiler = f_string_dynamics_initialize;
-        f_string_dynamics build_language = f_string_dynamics_initialize;
-        f_string_dynamics build_linker = f_string_dynamics_initialize;
-        f_string_dynamics build_script = f_string_dynamics_initialize;
-        f_string_dynamics build_shared = f_string_dynamics_initialize;
-        f_string_dynamics build_static = f_string_dynamics_initialize;
-        f_string_dynamics path_headers = f_string_dynamics_initialize;
-        f_string_dynamics path_language = f_string_dynamics_initialize;
-        f_string_dynamics path_library_script = f_string_dynamics_initialize;
-        f_string_dynamics path_library_shared = f_string_dynamics_initialize;
-        f_string_dynamics path_library_static = f_string_dynamics_initialize;
-        f_string_dynamics path_program_script = f_string_dynamics_initialize;
-        f_string_dynamics path_program_shared = f_string_dynamics_initialize;
-        f_string_dynamics path_program_static = f_string_dynamics_initialize;
-        f_string_dynamics process_post = f_string_dynamics_initialize;
-        f_string_dynamics process_pre = f_string_dynamics_initialize;
-        f_string_dynamics project_name = f_string_dynamics_initialize;
-        f_string_dynamics search_exclusive = f_string_dynamics_initialize;
-        f_string_dynamics search_shared = f_string_dynamics_initialize;
-        f_string_dynamics search_static = f_string_dynamics_initialize;
-        f_string_dynamics version_major = f_string_dynamics_initialize;
-        f_string_dynamics version_micro = f_string_dynamics_initialize;
-        f_string_dynamics version_minor = f_string_dynamics_initialize;
-        f_string_dynamics version_target = f_string_dynamics_initialize;
-
-        f_string_dynamics *settings_value[] = {
-          &build_compiler,
-          &build_language,
-          &setting->build_libraries,
-          &build_linker,
-          &build_script,
-          &build_shared,
-          &setting->build_sources_headers,
-          &setting->build_sources_library,
-          &setting->build_sources_program,
-          &setting->build_sources_setting,
-          &setting->build_sources_script,
-          &build_static,
-          &setting->defines_all,
-          &setting->defines_shared,
-          &setting->defines_static,
-          &setting->environment,
-          &setting->flags_all,
-          &setting->flags_library,
-          &setting->flags_program,
-          &setting->flags_shared,
-          &setting->flags_static,
-          &setting->modes,
-          &setting->modes_default,
-          &path_headers,
-          &path_language,
-          &path_library_script,
-          &path_library_shared,
-          &path_library_static,
-          &path_program_script,
-          &path_program_shared,
-          &path_program_static,
-          &process_post,
-          &process_pre,
-          &project_name,
-          &search_exclusive,
-          &search_shared,
-          &search_static,
-          &version_major,
-          &version_micro,
-          &version_minor,
-          &version_target,
-        };
-
-        f_string function = "fll_fss_snatch_apart";
-
-        *status = fll_fss_snatch_apart(buffer, objects, contents, settings_name, settings_length, settings_value, fake_build_setting_total);
-
-        if (*status == F_none) {
-          f_string_dynamic settings_mode_name_dynamic[fake_build_setting_total];
-          f_string settings_mode_names[fake_build_setting_total];
-          f_string_length setting_mode_lengths[fake_build_setting_total];
+    fake_build_load_setting_defaults(data, setting, status);
+  }
+#endif // _di_fake_build_load_setting_
 
-          const f_string_dynamics *modes = &setting->modes_default;
-          bool found = F_false;
+#ifndef _di_fake_build_load_setting_process_
+  void fake_build_load_setting_process(const fake_data data, const f_string path_file, const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, fake_build_setting *setting, f_status *status) {
+    if (F_status_is_error(*status) && buffer.used) return;
+
+    bool error_printed = F_false;
+
+    const f_string settings_name[] = {
+      fake_build_setting_name_build_compiler,
+      fake_build_setting_name_build_language,
+      fake_build_setting_name_build_libraries,
+      fake_build_setting_name_build_linker,
+      fake_build_setting_name_build_script,
+      fake_build_setting_name_build_shared,
+      fake_build_setting_name_build_sources_headers,
+      fake_build_setting_name_build_sources_library,
+      fake_build_setting_name_build_sources_program,
+      fake_build_setting_name_build_sources_settings,
+      fake_build_setting_name_build_sources_script,
+      fake_build_setting_name_build_static,
+      fake_build_setting_name_defines_all,
+      fake_build_setting_name_defines_shared,
+      fake_build_setting_name_defines_static,
+      fake_build_setting_name_environment,
+      fake_build_setting_name_flags_all,
+      fake_build_setting_name_flags_library,
+      fake_build_setting_name_flags_program,
+      fake_build_setting_name_flags_shared,
+      fake_build_setting_name_flags_static,
+      fake_build_setting_name_modes,
+      fake_build_setting_name_modes_default,
+      fake_build_setting_name_path_headers,
+      fake_build_setting_name_path_language,
+      fake_build_setting_name_path_library_script,
+      fake_build_setting_name_path_library_shared,
+      fake_build_setting_name_path_library_static,
+      fake_build_setting_name_path_program_script,
+      fake_build_setting_name_path_program_shared,
+      fake_build_setting_name_path_program_static,
+      fake_build_setting_name_process_post,
+      fake_build_setting_name_process_pre,
+      fake_build_setting_name_project_name,
+      fake_build_setting_name_search_exclusive,
+      fake_build_setting_name_search_shared,
+      fake_build_setting_name_search_static,
+      fake_build_setting_name_version_major,
+      fake_build_setting_name_version_micro,
+      fake_build_setting_name_version_minor,
+      fake_build_setting_name_version_target,
+    };
 
-          f_array_length i = 0;
-          f_array_length j = 0;
+    const f_string_length settings_length[] = {
+      fake_build_setting_name_build_compiler_length,
+      fake_build_setting_name_build_language_length,
+      fake_build_setting_name_build_libraries_length,
+      fake_build_setting_name_build_linker_length,
+      fake_build_setting_name_build_script_length,
+      fake_build_setting_name_build_shared_length,
+      fake_build_setting_name_build_sources_headers_length,
+      fake_build_setting_name_build_sources_library_length,
+      fake_build_setting_name_build_sources_program_length,
+      fake_build_setting_name_build_sources_settings_length,
+      fake_build_setting_name_build_sources_script_length,
+      fake_build_setting_name_build_static_length,
+      fake_build_setting_name_defines_all_length,
+      fake_build_setting_name_defines_shared_length,
+      fake_build_setting_name_defines_static_length,
+      fake_build_setting_name_environment_length,
+      fake_build_setting_name_flags_all_length,
+      fake_build_setting_name_flags_library_length,
+      fake_build_setting_name_flags_program_length,
+      fake_build_setting_name_flags_shared_length,
+      fake_build_setting_name_flags_static_length,
+      fake_build_setting_name_modes_length,
+      fake_build_setting_name_modes_default_length,
+      fake_build_setting_name_path_headers_length,
+      fake_build_setting_name_path_language_length,
+      fake_build_setting_name_path_library_script_length,
+      fake_build_setting_name_path_library_shared_length,
+      fake_build_setting_name_path_library_static_length,
+      fake_build_setting_name_path_program_script_length,
+      fake_build_setting_name_path_program_shared_length,
+      fake_build_setting_name_path_program_static_length,
+      fake_build_setting_name_process_post_length,
+      fake_build_setting_name_process_pre_length,
+      fake_build_setting_name_project_name_length,
+      fake_build_setting_name_search_exclusive_length,
+      fake_build_setting_name_search_shared_length,
+      fake_build_setting_name_search_static_length,
+      fake_build_setting_name_version_major_length,
+      fake_build_setting_name_version_micro_length,
+      fake_build_setting_name_version_minor_length,
+      fake_build_setting_name_version_target_length,
+    };
 
-          // if any mode is specified, the entire defaults is replaced.
-          if (data.mode.used > 0) {
-            modes = &data.mode;
-          }
+    f_string_dynamics build_compiler = f_string_dynamics_initialize;
+    f_string_dynamics build_language = f_string_dynamics_initialize;
+    f_string_dynamics build_linker = f_string_dynamics_initialize;
+    f_string_dynamics build_script = f_string_dynamics_initialize;
+    f_string_dynamics build_shared = f_string_dynamics_initialize;
+    f_string_dynamics build_static = f_string_dynamics_initialize;
+    f_string_dynamics path_headers = f_string_dynamics_initialize;
+    f_string_dynamics path_language = f_string_dynamics_initialize;
+    f_string_dynamics path_library_script = f_string_dynamics_initialize;
+    f_string_dynamics path_library_shared = f_string_dynamics_initialize;
+    f_string_dynamics path_library_static = f_string_dynamics_initialize;
+    f_string_dynamics path_program_script = f_string_dynamics_initialize;
+    f_string_dynamics path_program_shared = f_string_dynamics_initialize;
+    f_string_dynamics path_program_static = f_string_dynamics_initialize;
+    f_string_dynamics process_post = f_string_dynamics_initialize;
+    f_string_dynamics process_pre = f_string_dynamics_initialize;
+    f_string_dynamics project_name = f_string_dynamics_initialize;
+    f_string_dynamics search_exclusive = f_string_dynamics_initialize;
+    f_string_dynamics search_shared = f_string_dynamics_initialize;
+    f_string_dynamics search_static = f_string_dynamics_initialize;
+    f_string_dynamics version_major = f_string_dynamics_initialize;
+    f_string_dynamics version_micro = f_string_dynamics_initialize;
+    f_string_dynamics version_minor = f_string_dynamics_initialize;
+    f_string_dynamics version_target = f_string_dynamics_initialize;
+
+    f_string_dynamics *settings_value[] = {
+      &build_compiler,
+      &build_language,
+      &setting->build_libraries,
+      &build_linker,
+      &build_script,
+      &build_shared,
+      &setting->build_sources_headers,
+      &setting->build_sources_library,
+      &setting->build_sources_program,
+      &setting->build_sources_setting,
+      &setting->build_sources_script,
+      &build_static,
+      &setting->defines_all,
+      &setting->defines_shared,
+      &setting->defines_static,
+      &setting->environment,
+      &setting->flags_all,
+      &setting->flags_library,
+      &setting->flags_program,
+      &setting->flags_shared,
+      &setting->flags_static,
+      &setting->modes,
+      &setting->modes_default,
+      &path_headers,
+      &path_language,
+      &path_library_script,
+      &path_library_shared,
+      &path_library_static,
+      &path_program_script,
+      &path_program_shared,
+      &path_program_static,
+      &process_post,
+      &process_pre,
+      &project_name,
+      &search_exclusive,
+      &search_shared,
+      &search_static,
+      &version_major,
+      &version_micro,
+      &version_minor,
+      &version_target,
+    };
 
-          for (; i < modes->used; i++) {
-            found = F_false;
+    f_string function = "fll_fss_snatch_apart";
 
-            for (j = 0; j < setting->modes.used; j++) {
-              if (fl_string_dynamic_compare_trim(modes->array[i], setting->modes.array[j]) == F_equal_to) {
-                found = F_true;
-                break;
-              }
-            } // for
+    *status = fll_fss_snatch_apart(buffer, objects, contents, settings_name, settings_length, fake_build_setting_total, settings_value);
 
-            if (found == F_false) {
-              if (data.verbosity != fake_verbosity_quiet) {
-                fprintf(f_type_error, "%c", f_string_eol[0]);
-                fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: the specified mode '");
-                fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", modes->array[i].string);
-                fl_color_print(f_type_error, data.context.error, data.context.reset, "' is not a valid mode, according to '");
-                fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-                fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
-              }
-
-              error_printed = F_true;
-              *status = F_status_set_error(F_parameter);
-              break;
-            }
+    if (*status == F_none) {
+      f_string_dynamic settings_mode_name_dynamic[fake_build_setting_total];
+      f_string settings_mode_names[fake_build_setting_total];
+      f_string_length setting_mode_lengths[fake_build_setting_total];
 
-            memset(&settings_mode_name_dynamic, 0, sizeof(f_string_dynamic) * fake_build_setting_total);
-            memset(&settings_mode_names, 0, sizeof(f_string) * fake_build_setting_total);
-            memset(&setting_mode_lengths, 0, sizeof(f_string_length) * fake_build_setting_total);
+      const f_string_dynamics *modes = &setting->modes_default;
+      bool found = F_false;
 
-            for (j = 0; j < fake_build_setting_total; j++) {
-              setting_mode_lengths[j] = settings_length[j] + 1 + modes->array[i].used;
+      f_array_length i = 0;
+      f_array_length j = 0;
 
-              f_macro_string_dynamic_new(*status, settings_mode_name_dynamic[j], setting_mode_lengths[j]);
-              if (F_status_is_error(*status)) {
-                function = "f_macro_string_dynamic_new";
-                break;
-              }
+      // if any mode is specified, the entire defaults is replaced.
+      if (data.mode.used > 0) {
+        modes = &data.mode;
+      }
 
-              memcpy(settings_mode_name_dynamic[j].string, settings_name[j], settings_length[j]);
-              memcpy(settings_mode_name_dynamic[j].string + settings_length[j] + 1, modes->array[i].string, modes->array[i].used);
-              settings_mode_name_dynamic[j].string[settings_length[j]] = '-';
+      for (; i < modes->used; i++) {
+        found = F_false;
 
-              settings_mode_names[j] = settings_mode_name_dynamic[j].string;
-            } // for
+        for (j = 0; j < setting->modes.used; j++) {
+          if (fl_string_dynamic_compare_trim(modes->array[i], setting->modes.array[j]) == F_equal_to) {
+            found = F_true;
+            break;
+          }
+        } // for
 
-            if (*status == F_none) {
-              *status = fll_fss_snatch_apart(buffer, objects, contents, settings_mode_names, setting_mode_lengths, settings_value, fake_build_setting_total);
+        if (found == F_false) {
+          if (data.verbosity != fake_verbosity_quiet) {
+            fprintf(f_type_error, "%c", f_string_eol[0]);
+            fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: the specified mode '");
+            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", modes->array[i].string);
+            fl_color_print(f_type_error, data.context.error, data.context.reset, "' is not a valid mode, according to '");
+            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", path_file);
+            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
+          }
 
-              if (F_status_is_error(*status)) {
-                function = "fll_fss_snatch_apart";
-              }
-            }
+          error_printed = F_true;
+          *status = F_status_set_error(F_parameter);
+          break;
+        }
 
-            for (j = 0; j < fake_build_setting_total; j++) {
-              f_macro_string_dynamic_delete_simple(settings_mode_name_dynamic[j]);
-            } // for
+        memset(&settings_mode_name_dynamic, 0, sizeof(f_string_dynamic) * fake_build_setting_total);
+        memset(&settings_mode_names, 0, sizeof(f_string) * fake_build_setting_total);
+        memset(&setting_mode_lengths, 0, sizeof(f_string_length) * fake_build_setting_total);
 
-            if (F_status_is_error(*status)) break;
-          } // for
-        }
+        for (j = 0; j < fake_build_setting_total; j++) {
+          setting_mode_lengths[j] = settings_length[j] + 1 + modes->array[i].used;
 
-        if (F_status_is_error(*status)) {
-          if (*status == F_status_set_error(F_string_too_large)) {
-            if (data.verbosity != fake_verbosity_quiet) {
-              // @todo update FSS functions to return which setting index the problem happened on.
-              fprintf(f_type_error, "%c", f_string_eol[0]);
-              fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: a setting in the build setting file '");
-              fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-              fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' is too long.");
-            }
-          }
-          else if (!error_printed) {
-            fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), function, F_true);
+          f_macro_string_dynamic_new(*status, settings_mode_name_dynamic[j], setting_mode_lengths[j]);
+          if (F_status_is_error(*status)) {
+            function = "f_macro_string_dynamic_new";
+            break;
           }
-        }
-        else {
-          const f_string settings_single_name[] = {
-            fake_build_setting_name_build_compiler,
-            fake_build_setting_name_build_language,
-            fake_build_setting_name_build_linker,
-            fake_build_setting_name_build_script,
-            fake_build_setting_name_build_shared,
-            fake_build_setting_name_build_static,
-            fake_build_setting_name_path_headers,
-            fake_build_setting_name_path_language,
-            fake_build_setting_name_path_library_script,
-            fake_build_setting_name_path_library_shared,
-            fake_build_setting_name_path_library_static,
-            fake_build_setting_name_path_program_script,
-            fake_build_setting_name_path_program_shared,
-            fake_build_setting_name_path_program_static,
-            fake_build_setting_name_process_post,
-            fake_build_setting_name_process_pre,
-            fake_build_setting_name_project_name,
-            fake_build_setting_name_search_exclusive,
-            fake_build_setting_name_search_shared,
-            fake_build_setting_name_search_static,
-            fake_build_setting_name_version_major,
-            fake_build_setting_name_version_micro,
-            fake_build_setting_name_version_minor,
-            fake_build_setting_name_version_target,
-          };
-
-          const f_string_statics *settings_single_source[] = {
-            &build_compiler,
-            &build_language,
-            &build_linker,
-            &build_script,
-            &build_shared,
-            &build_static,
-            &path_headers,
-            &path_language,
-            &path_library_script,
-            &path_library_shared,
-            &path_library_static,
-            &path_program_script,
-            &path_program_shared,
-            &path_program_static,
-            &process_post,
-            &process_pre,
-            &project_name,
-            &search_exclusive,
-            &search_shared,
-            &search_static,
-            &version_major,
-            &version_micro,
-            &version_minor,
-            &version_target,
-          };
-
-          bool *settings_single_bool[] = {
-            0,
-            0,
-            0,
-            &setting->build_script,
-            &setting->build_shared,
-            &setting->build_static,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            &setting->search_exclusive,
-            &setting->search_shared,
-            &setting->search_static,
-          };
-
-          f_string_dynamic *settings_single_destination[] = {
-            &setting->build_compiler,
-            0,
-            &setting->build_linker,
-            0,
-            0,
-            0,
-            &setting->path_headers,
-            &setting->path_language,
-            &setting->path_library_script,
-            &setting->path_library_shared,
-            &setting->path_library_static,
-            &setting->path_program_script,
-            &setting->path_program_shared,
-            &setting->path_program_static,
-            &setting->process_post,
-            &setting->process_pre,
-            &setting->project_name,
-            0,
-            0,
-            0,
-            &setting->version_major,
-            &setting->version_micro,
-            &setting->version_minor,
-          };
-
-          uint8_t *settings_single_language[] = {
-            0,
-            &setting->build_language,
-          };
-
-          uint8_t *settings_single_version[] = {
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            0,
-            &setting->version_target,
-          };
-
-          // 1 = "yes" or "no", 2 = path/, 3 = literal, 4 = "bash", "c", or "c++", 5 = "major", "minor", or "micro".
-          uint8_t settings_single_type[] = {
-            3,
-            4,
-            3,
-            1,
-            1,
-            1,
-            2,
-            2,
-            2,
-            2,
-            2,
-            2,
-            2,
-            2,
-            3,
-            3,
-            3,
-            1,
-            1,
-            1,
-            3,
-            3,
-            3,
-            5,
-          };
-
-          for (f_array_length i = 0; i < 24; i++) {
-            if (settings_single_source[i]->used == 0) continue;
-
-            if (settings_single_source[i]->used > 1) {
-              if (data.verbosity != fake_verbosity_quiet) {
-                fprintf(f_type_warning, "%c", f_string_eol[0]);
-                fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
-                fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
-                fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
-                fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-                fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may only have a single property, only using the first: '");
-                fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_source[i]->array[0].string);
-                fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
-              }
-            }
 
-            if (settings_single_type[i] == 1) {
-              if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_setting_bool_yes, settings_single_source[i]->array[0].used, fake_build_setting_bool_yes_length) == F_equal_to) {
-                *settings_single_bool[i] = F_true;
-              }
-              else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_setting_bool_no, settings_single_source[i]->array[0].used, fake_build_setting_bool_no_length) == F_equal_to) {
-                *settings_single_bool[i] = F_false;
-              }
-              else {
-                *settings_single_bool[i] = F_true;
-
-                if (data.verbosity != fake_verbosity_quiet) {
-                  fprintf(f_type_warning, "%c", f_string_eol[0]);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may be either '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_setting_bool_yes);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' or '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_setting_bool_no);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', defaulting to '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_setting_bool_yes);
-                  fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
-                }
-              }
-            }
-            else if (settings_single_type[i] == 4) {
-              if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_language_bash, settings_single_source[i]->array[0].used, fake_build_language_bash_length) == F_equal_to) {
-                *settings_single_language[i] = fake_build_language_type_bash;
-              }
-              else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_language_c, settings_single_source[i]->array[0].used, fake_build_language_c_length) == F_equal_to) {
-                *settings_single_language[i] = fake_build_language_type_c;
-              }
-              else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_language_cpp, settings_single_source[i]->array[0].used, fake_build_language_cpp_length) == F_equal_to) {
-                *settings_single_language[i] = fake_build_language_type_cpp;
-              }
-              else {
-                *settings_single_language[i] = fake_build_language_type_c;
-
-                if (data.verbosity != fake_verbosity_quiet) {
-                  fprintf(f_type_warning, "%c", f_string_eol[0]);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may only be one of '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_bash);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_c);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', or '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_cpp);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', defaulting to '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_c);
-                  fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
-                }
-              }
-            }
-            else if (settings_single_type[i] == 5) {
-              if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_version_major, settings_single_source[i]->array[0].used, fake_build_version_major_length) == F_equal_to) {
-                *settings_single_version[i] = fake_build_version_type_major;
-              }
-              else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_version_micro, settings_single_source[i]->array[0].used, fake_build_version_micro_length) == F_equal_to) {
-                *settings_single_version[i] = fake_build_version_type_micro;
-              }
-              else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_version_minor, settings_single_source[i]->array[0].used, fake_build_version_minor_length) == F_equal_to) {
-                *settings_single_version[i] = fake_build_version_type_minor;
-              }
-              else {
-                *settings_single_version[i] = fake_build_version_type_major;
-
-                if (data.verbosity != fake_verbosity_quiet) {
-                  fprintf(f_type_warning, "%c", f_string_eol[0]);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may only be one of '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_major);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_minor);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', or '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_micro);
-                  fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', defaulting to '");
-                  fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_major);
-                  fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
-                }
-              }
-            }
-            else {
-              *status = fl_string_dynamic_append_nulless(settings_single_source[i]->array[0], settings_single_destination[i]);
-              if (F_status_is_error(*status)) {
-                fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_append_nulless", F_true);
-                break;
-              }
-
-              if (settings_single_type[i] == 2) {
-                *status = fl_string_append_assure(f_path_separator, f_path_separator_length, settings_single_destination[i]);
-                if (F_status_is_error(*status)) {
-                  fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_append_assure", F_true);
-                  break;
-                }
-              }
-
-              *status = fl_string_dynamic_terminate_after(settings_single_destination[i]);
-              if (F_status_is_error(*status)) {
-                fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_terminate_after", F_true);
-                break;
-              }
-            }
-          } // for
+          memcpy(settings_mode_name_dynamic[j].string, settings_name[j], settings_length[j]);
+          memcpy(settings_mode_name_dynamic[j].string + settings_length[j] + 1, modes->array[i].string, modes->array[i].used);
+          settings_mode_name_dynamic[j].string[settings_length[j]] = '-';
+
+          settings_mode_names[j] = settings_mode_name_dynamic[j].string;
+        } // for
+
+        if (*status == F_none) {
+          *status = fll_fss_snatch_apart(buffer, objects, contents, settings_mode_names, setting_mode_lengths, fake_build_setting_total, settings_value);
+
+          if (F_status_is_error(*status)) {
+            function = "fll_fss_snatch_apart";
+          }
         }
 
-        f_macro_string_dynamics_delete_simple(build_compiler);
-        f_macro_string_dynamics_delete_simple(build_language);
-        f_macro_string_dynamics_delete_simple(build_linker);
-        f_macro_string_dynamics_delete_simple(build_script);
-        f_macro_string_dynamics_delete_simple(build_shared);
-        f_macro_string_dynamics_delete_simple(build_static);
-        f_macro_string_dynamics_delete_simple(path_headers);
-        f_macro_string_dynamics_delete_simple(path_language);
-        f_macro_string_dynamics_delete_simple(path_library_script);
-        f_macro_string_dynamics_delete_simple(path_library_shared);
-        f_macro_string_dynamics_delete_simple(path_library_static);
-        f_macro_string_dynamics_delete_simple(path_program_script);
-        f_macro_string_dynamics_delete_simple(path_program_shared);
-        f_macro_string_dynamics_delete_simple(path_program_static);
-        f_macro_string_dynamics_delete_simple(process_post);
-        f_macro_string_dynamics_delete_simple(process_pre);
-        f_macro_string_dynamics_delete_simple(project_name);
-        f_macro_string_dynamics_delete_simple(search_exclusive);
-        f_macro_string_dynamics_delete_simple(search_shared);
-        f_macro_string_dynamics_delete_simple(search_static);
-        f_macro_string_dynamics_delete_simple(version_major);
-        f_macro_string_dynamics_delete_simple(version_micro);
-        f_macro_string_dynamics_delete_simple(version_minor);
-        f_macro_string_dynamics_delete_simple(version_target);
-      }
+        for (j = 0; j < fake_build_setting_total; j++) {
+          f_macro_string_dynamic_delete_simple(settings_mode_name_dynamic[j]);
+        } // for
 
-      f_macro_fss_objects_delete_simple(objects);
-      f_macro_fss_contents_delete_simple(contents);
+        if (F_status_is_error(*status)) break;
+      } // for
     }
 
-    f_macro_string_dynamic_delete_simple(buffer);
+    if (F_status_is_error(*status)) {
+      if (*status == F_status_set_error(F_string_too_large)) {
+        if (data.verbosity != fake_verbosity_quiet) {
+          // @todo update FSS functions to return which setting index the problem happened on.
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: a setting in the build setting file '");
+          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", path_file);
+          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' is too long.");
+        }
+      }
+      else if (!error_printed) {
+        fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), function, F_true);
+      }
+    }
+    else {
+      const f_string settings_single_name[] = {
+        fake_build_setting_name_build_compiler,
+        fake_build_setting_name_build_language,
+        fake_build_setting_name_build_linker,
+        fake_build_setting_name_build_script,
+        fake_build_setting_name_build_shared,
+        fake_build_setting_name_build_static,
+        fake_build_setting_name_path_headers,
+        fake_build_setting_name_path_language,
+        fake_build_setting_name_path_library_script,
+        fake_build_setting_name_path_library_shared,
+        fake_build_setting_name_path_library_static,
+        fake_build_setting_name_path_program_script,
+        fake_build_setting_name_path_program_shared,
+        fake_build_setting_name_path_program_static,
+        fake_build_setting_name_process_post,
+        fake_build_setting_name_process_pre,
+        fake_build_setting_name_project_name,
+        fake_build_setting_name_search_exclusive,
+        fake_build_setting_name_search_shared,
+        fake_build_setting_name_search_static,
+        fake_build_setting_name_version_major,
+        fake_build_setting_name_version_micro,
+        fake_build_setting_name_version_minor,
+        fake_build_setting_name_version_target,
+      };
 
-    if (F_status_is_error(*status)) return;
+      const f_string_statics *settings_single_source[] = {
+        &build_compiler,
+        &build_language,
+        &build_linker,
+        &build_script,
+        &build_shared,
+        &build_static,
+        &path_headers,
+        &path_language,
+        &path_library_script,
+        &path_library_shared,
+        &path_library_static,
+        &path_program_script,
+        &path_program_shared,
+        &path_program_static,
+        &process_post,
+        &process_pre,
+        &project_name,
+        &search_exclusive,
+        &search_shared,
+        &search_static,
+        &version_major,
+        &version_micro,
+        &version_minor,
+        &version_target,
+      };
 
-    // error when required settings are not specified.
-    {
-      bool failed = F_false;
+      bool *settings_single_bool[] = {
+        0,
+        0,
+        0,
+        &setting->build_script,
+        &setting->build_shared,
+        &setting->build_static,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        &setting->search_exclusive,
+        &setting->search_shared,
+        &setting->search_static,
+      };
 
-      f_string_static *settings[] = {
+      f_string_dynamic *settings_single_destination[] = {
+        &setting->build_compiler,
+        0,
+        &setting->build_linker,
+        0,
+        0,
+        0,
+        &setting->path_headers,
+        &setting->path_language,
+        &setting->path_library_script,
+        &setting->path_library_shared,
+        &setting->path_library_static,
+        &setting->path_program_script,
+        &setting->path_program_shared,
+        &setting->path_program_static,
+        &setting->process_post,
+        &setting->process_pre,
         &setting->project_name,
+        0,
+        0,
+        0,
+        &setting->version_major,
+        &setting->version_micro,
+        &setting->version_minor,
       };
 
-      f_string names[] = {
-        fake_build_setting_name_project_name,
+      uint8_t *settings_single_language[] = {
+        0,
+        &setting->build_language,
       };
 
-      for (uint8_t i = 0; i < 1; i++) {
-        if (settings[i]->used == 0) {
-          fprintf(f_type_error, "%c", f_string_eol[0]);
-          fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: the setting '");
-          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", names[i]);
-          fl_color_print(f_type_error, data.context.error, data.context.reset, "' is required but is not specified in the settings file '");
-          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", data.file_data_build_settings.string);
-          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
+      uint8_t *settings_single_version[] = {
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        &setting->version_target,
+      };
 
-          failed = F_true;
+      // 1 = "yes" or "no", 2 = path/, 3 = literal, 4 = "bash", "c", or "c++", 5 = "major", "minor", or "micro".
+      uint8_t settings_single_type[] = {
+        3,
+        4,
+        3,
+        1,
+        1,
+        1,
+        2,
+        2,
+        2,
+        2,
+        2,
+        2,
+        2,
+        2,
+        3,
+        3,
+        3,
+        1,
+        1,
+        1,
+        3,
+        3,
+        3,
+        5,
+      };
+
+      for (f_array_length i = 0; i < 24; i++) {
+        if (settings_single_source[i]->used == 0) continue;
+
+        if (settings_single_source[i]->used > 1) {
+          if (data.verbosity == fake_verbosity_verbose) {
+            fprintf(f_type_warning, "%c", f_string_eol[0]);
+            fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
+            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
+            fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
+            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", path_file);
+            fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may only have a single property, only using the first: '");
+            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_source[i]->array[0].string);
+            fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
+          }
         }
-      } // for
 
-      if (failed) {
-        *status = F_status_set_error(F_failure);
-        return;
-      }
+        if (settings_single_type[i] == 1) {
+          if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_common_setting_bool_yes, settings_single_source[i]->array[0].used, fake_common_setting_bool_yes_length) == F_equal_to) {
+            *settings_single_bool[i] = F_true;
+          }
+          else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_common_setting_bool_no, settings_single_source[i]->array[0].used, fake_common_setting_bool_no_length) == F_equal_to) {
+            *settings_single_bool[i] = F_false;
+          }
+          else {
+            *settings_single_bool[i] = F_true;
+
+            if (data.verbosity == fake_verbosity_verbose) {
+              fprintf(f_type_warning, "%c", f_string_eol[0]);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", path_file);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may be either '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_common_setting_bool_yes);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' or '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_common_setting_bool_no);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', defaulting to '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_common_setting_bool_yes);
+              fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
+            }
+          }
+        }
+        else if (settings_single_type[i] == 4) {
+          if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_language_bash, settings_single_source[i]->array[0].used, fake_build_language_bash_length) == F_equal_to) {
+            *settings_single_language[i] = fake_build_language_type_bash;
+          }
+          else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_language_c, settings_single_source[i]->array[0].used, fake_build_language_c_length) == F_equal_to) {
+            *settings_single_language[i] = fake_build_language_type_c;
+          }
+          else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_language_cpp, settings_single_source[i]->array[0].used, fake_build_language_cpp_length) == F_equal_to) {
+            *settings_single_language[i] = fake_build_language_type_cpp;
+          }
+          else {
+            *settings_single_language[i] = fake_build_language_type_c;
+
+            if (data.verbosity == fake_verbosity_verbose) {
+              fprintf(f_type_warning, "%c", f_string_eol[0]);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", path_file);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may only be one of '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_bash);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_c);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', or '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_cpp);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', defaulting to '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_language_c);
+              fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
+            }
+          }
+        }
+        else if (settings_single_type[i] == 5) {
+          if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_version_major, settings_single_source[i]->array[0].used, fake_build_version_major_length) == F_equal_to) {
+            *settings_single_version[i] = fake_build_version_type_major;
+          }
+          else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_version_micro, settings_single_source[i]->array[0].used, fake_build_version_micro_length) == F_equal_to) {
+            *settings_single_version[i] = fake_build_version_type_micro;
+          }
+          else if (fl_string_compare_trim(settings_single_source[i]->array[0].string, fake_build_version_minor, settings_single_source[i]->array[0].used, fake_build_version_minor_length) == F_equal_to) {
+            *settings_single_version[i] = fake_build_version_type_minor;
+          }
+          else {
+            *settings_single_version[i] = fake_build_version_type_major;
+
+            if (data.verbosity == fake_verbosity_verbose) {
+              fprintf(f_type_warning, "%c", f_string_eol[0]);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the setting '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", settings_single_name[i]);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' in the file '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", path_file);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' may only be one of '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_major);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_minor);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', or '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_micro);
+              fl_color_print(f_type_warning, data.context.warning, data.context.reset, "', defaulting to '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", fake_build_version_major);
+              fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "'.");
+            }
+          }
+        }
+        else {
+          // replace any potential existing value.
+          settings_single_destination[i]->used = 0;
+
+          *status = fl_string_dynamic_append_nulless(settings_single_source[i]->array[0], settings_single_destination[i]);
+          if (F_status_is_error(*status)) {
+            fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_append_nulless", F_true);
+            break;
+          }
+
+          if (settings_single_type[i] == 2) {
+            *status = fl_string_append_assure(f_path_separator, f_path_separator_length, settings_single_destination[i]);
+            if (F_status_is_error(*status)) {
+              fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_append_assure", F_true);
+              break;
+            }
+          }
+
+          *status = fl_string_dynamic_terminate_after(settings_single_destination[i]);
+          if (F_status_is_error(*status)) {
+            fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fl_string_dynamic_terminate_after", F_true);
+            break;
+          }
+        }
+      } // for
     }
 
-    // provide some defaults.
+    f_macro_string_dynamics_delete_simple(build_compiler);
+    f_macro_string_dynamics_delete_simple(build_language);
+    f_macro_string_dynamics_delete_simple(build_linker);
+    f_macro_string_dynamics_delete_simple(build_script);
+    f_macro_string_dynamics_delete_simple(build_shared);
+    f_macro_string_dynamics_delete_simple(build_static);
+    f_macro_string_dynamics_delete_simple(path_headers);
+    f_macro_string_dynamics_delete_simple(path_language);
+    f_macro_string_dynamics_delete_simple(path_library_script);
+    f_macro_string_dynamics_delete_simple(path_library_shared);
+    f_macro_string_dynamics_delete_simple(path_library_static);
+    f_macro_string_dynamics_delete_simple(path_program_script);
+    f_macro_string_dynamics_delete_simple(path_program_shared);
+    f_macro_string_dynamics_delete_simple(path_program_static);
+    f_macro_string_dynamics_delete_simple(process_post);
+    f_macro_string_dynamics_delete_simple(process_pre);
+    f_macro_string_dynamics_delete_simple(project_name);
+    f_macro_string_dynamics_delete_simple(search_exclusive);
+    f_macro_string_dynamics_delete_simple(search_shared);
+    f_macro_string_dynamics_delete_simple(search_static);
+    f_macro_string_dynamics_delete_simple(version_major);
+    f_macro_string_dynamics_delete_simple(version_micro);
+    f_macro_string_dynamics_delete_simple(version_minor);
+    f_macro_string_dynamics_delete_simple(version_target);
+  }
+#endif // _di_fake_build_load_setting_process_
+
+#ifndef _di_fake_build_load_setting_defaults_
+  void fake_build_load_setting_defaults(const fake_data data, fake_build_setting *setting, f_status *status) {
+    if (F_status_is_error(*status)) return;
+
     {
       f_string sources[] = {
         fake_build_setting_default_version,
@@ -1933,112 +1909,112 @@ extern "C" {
       } // for
     }
 
-    // Override setting file when any of these are specified in the command line.
-    if (F_status_is_fine(*status)) {
-      if (data.parameters[fake_parameter_shared_disabled].result == f_console_result_found) {
-        if (data.parameters[fake_parameter_shared_enabled].result == f_console_result_found) {
-          if (data.parameters[fake_parameter_shared_enabled].location > data.parameters[fake_parameter_shared_disabled].location) {
-            setting->build_shared = F_true;
-            setting->search_shared = F_true;
-          }
-          else {
-            setting->build_shared = F_false;
-            setting->search_shared = F_false;
-          }
-
-          if (data.verbosity == fake_verbosity_verbose) {
-            fprintf(f_type_warning, "%c", f_string_eol[0]);
-            fl_color_print(f_type_warning, data.context.error, data.context.reset, "WARNING: the parameters '");
-            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_disabled);
-            fl_color_print(f_type_warning, data.context.error, data.context.reset, "' and '");
-            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_enabled);
-            fl_color_print(f_type_warning, data.context.error, data.context.reset, "' contradict, defaulting to '");
-
-            if (setting->build_shared) {
-              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_enabled);
-            }
-            else {
-              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_disabled);
-            }
+    if (F_status_is_error(*status)) return;
 
-            fl_color_print_line(f_type_warning, data.context.error, data.context.reset, "'.");
-          }
+    // Override setting file when any of these are specified in the command line.
+    if (data.parameters[fake_parameter_shared_disabled].result == f_console_result_found) {
+      if (data.parameters[fake_parameter_shared_enabled].result == f_console_result_found) {
+        if (data.parameters[fake_parameter_shared_enabled].location > data.parameters[fake_parameter_shared_disabled].location) {
+          setting->build_shared = F_true;
+          setting->search_shared = F_true;
         }
         else {
           setting->build_shared = F_false;
           setting->search_shared = F_false;
         }
-      }
-      else if (data.parameters[fake_parameter_shared_enabled].result == f_console_result_found) {
-        setting->build_shared = F_true;
-        setting->search_shared = F_true;
-      }
 
-      if (data.parameters[fake_parameter_static_disabled].result == f_console_result_found) {
-        if (data.parameters[fake_parameter_static_enabled].result == f_console_result_found) {
-          if (data.parameters[fake_parameter_static_enabled].location > data.parameters[fake_parameter_static_disabled].location) {
-            setting->build_static = F_true;
-            setting->search_static = F_true;
+        if (data.verbosity == fake_verbosity_verbose) {
+          fprintf(f_type_warning, "%c", f_string_eol[0]);
+          fl_color_print(f_type_warning, data.context.error, data.context.reset, "WARNING: the parameters '");
+          fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_disabled);
+          fl_color_print(f_type_warning, data.context.error, data.context.reset, "' and '");
+          fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_enabled);
+          fl_color_print(f_type_warning, data.context.error, data.context.reset, "' contradict, defaulting to '");
+
+          if (setting->build_shared) {
+            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_enabled);
           }
           else {
-            setting->build_static = F_false;
-            setting->search_static = F_false;
+            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_shared_disabled);
           }
 
-          if (data.verbosity == fake_verbosity_verbose) {
-            fprintf(f_type_warning, "%c", f_string_eol[0]);
-            fl_color_print(f_type_warning, data.context.error, data.context.reset, "WARNING: the parameters '");
-            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_disabled);
-            fl_color_print(f_type_warning, data.context.error, data.context.reset, "' and '");
-            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_enabled);
-            fl_color_print(f_type_warning, data.context.error, data.context.reset, "' contradict, defaulting to '");
-
-            if (setting->build_static) {
-              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_enabled);
-            }
-            else {
-              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_disabled);
-            }
+          fl_color_print_line(f_type_warning, data.context.error, data.context.reset, "'.");
+        }
+      }
+      else {
+        setting->build_shared = F_false;
+        setting->search_shared = F_false;
+      }
+    }
+    else if (data.parameters[fake_parameter_shared_enabled].result == f_console_result_found) {
+      setting->build_shared = F_true;
+      setting->search_shared = F_true;
+    }
 
-            fl_color_print_line(f_type_warning, data.context.error, data.context.reset, "'.");
-          }
+    if (data.parameters[fake_parameter_static_disabled].result == f_console_result_found) {
+      if (data.parameters[fake_parameter_static_enabled].result == f_console_result_found) {
+        if (data.parameters[fake_parameter_static_enabled].location > data.parameters[fake_parameter_static_disabled].location) {
+          setting->build_static = F_true;
+          setting->search_static = F_true;
         }
         else {
           setting->build_static = F_false;
           setting->search_static = F_false;
         }
+
+        if (data.verbosity == fake_verbosity_verbose) {
+          fprintf(f_type_warning, "%c", f_string_eol[0]);
+          fl_color_print(f_type_warning, data.context.error, data.context.reset, "WARNING: the parameters '");
+          fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_disabled);
+          fl_color_print(f_type_warning, data.context.error, data.context.reset, "' and '");
+          fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_enabled);
+          fl_color_print(f_type_warning, data.context.error, data.context.reset, "' contradict, defaulting to '");
+
+          if (setting->build_static) {
+            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_enabled);
+          }
+          else {
+            fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s%s", f_console_symbol_long_enable, fake_long_static_disabled);
+          }
+
+          fl_color_print_line(f_type_warning, data.context.error, data.context.reset, "'.");
+        }
       }
-      else if (data.parameters[fake_parameter_static_enabled].result == f_console_result_found) {
-        setting->build_static = F_true;
-        setting->search_static = F_true;
+      else {
+        setting->build_static = F_false;
+        setting->search_static = F_false;
       }
+    }
+    else if (data.parameters[fake_parameter_static_enabled].result == f_console_result_found) {
+      setting->build_static = F_true;
+      setting->search_static = F_true;
+    }
 
-      if (setting->build_language == fake_build_language_type_c || setting->build_language == fake_build_language_type_cpp) {
-        if (setting->build_shared == F_false && setting->build_static == F_false) {
-          if (data.verbosity != fake_verbosity_quiet) {
-            fprintf(f_type_error, "%c", f_string_eol[0]);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: the build settings '");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_setting_name_build_shared);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, "' and '");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_setting_name_build_static);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, "' cannot both be false when using the language '");
-
-            if (setting->build_language == fake_build_language_type_c) {
-              fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_language_c);
-            }
-            else {
-              fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_language_cpp);
-            }
-
-            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
+    if (setting->build_language == fake_build_language_type_c || setting->build_language == fake_build_language_type_cpp) {
+      if (setting->build_shared == F_false && setting->build_static == F_false) {
+        if (data.verbosity != fake_verbosity_quiet) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: the build settings '");
+          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_setting_name_build_shared);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "' and '");
+          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_setting_name_build_static);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "' cannot both be false when using the language '");
+
+          if (setting->build_language == fake_build_language_type_c) {
+            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_language_c);
+          }
+          else {
+            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_build_language_cpp);
           }
 
-          *status = F_status_set_error(F_failure);
+          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
         }
+
+        *status = F_status_set_error(F_failure);
       }
     }
   }
-#endif // _di_fake_build_load_setting_
+#endif // _di_fake_build_load_setting_defaults_
 
 #ifndef _di_fake_build_load_stage_
   void fake_build_load_stage(const fake_data data, fake_build_stage *stage, f_status *status) {
index 1c1f011ae64024ebfcea969b366aff6c508c7b58..83b82283dbf14fc868597404a4ebbd461d9a7a83 100644 (file)
 extern "C" {
 #endif
 
-#ifndef _di_fake_build_environment_
-  typedef struct {
-    f_string_dynamics names;
-    f_string_dynamics values;
-  } fake_build_environment;
-
-  #define fake_build_environment_initialize { \
-    f_string_dynamics_initialize, \
-    f_string_dynamics_initialize, \
-  }
-
-  #define fake_macro_build_environment_delete_simple(environment) \
-    f_macro_string_dynamics_delete_simple(environment.names) \
-    f_macro_string_dynamics_delete_simple(environment.values)
-#endif // _di_fake_build_environment_
-
 #ifndef _di_fake_build_setting_
   typedef struct {
     uint8_t build_language;
@@ -243,12 +227,6 @@ extern "C" {
 
   #define fake_build_setting_total 41
 
-  #define fake_build_setting_bool_yes "yes"
-  #define fake_build_setting_bool_no  "no"
-
-  #define fake_build_setting_bool_yes_length 3
-  #define fake_build_setting_bool_no_length  2
-
   #define fake_build_setting_default_version "0"
 
   #define fake_build_setting_default_version_length 1
@@ -336,17 +314,17 @@ extern "C" {
 #ifndef _di_fake_build_data_
   typedef struct {
     fake_build_setting setting;
-    fake_build_environment environment;
+    fake_environment environment;
   } fake_build_data;
 
   #define fake_build_data_initialize { \
     fake_build_setting_initialize, \
-    fake_build_environment_initialize, \
+    fake_environment_initialize, \
   }
 
   #define fake_macro_build_data_delete_simple(build) \
     fake_macro_build_setting_delete_simple(build.setting) \
-    fake_macro_build_environment_delete_simple(build.environment)
+    fake_macro_environment_delete_simple(build.environment)
 #endif // _di_fake_build_data_
 
 #ifndef _di_fake_build_parameter_
@@ -625,6 +603,58 @@ extern "C" {
 #endif // _di_fake_build_load_setting_
 
 /**
+ * Assign build setting defaults.
+ *
+ * @param data
+ *   The program data.
+ * @param path_file
+ *   The path to the buffer.
+ * @param buffer
+ *   The loaded file data.
+ * @param setting
+ *   All build related setting data from the build setting file are loaded into this.
+ *   These setting will have any specified mode property applied.
+ * @param status
+ *   The return status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_build_load_setting_defaults_
+  extern void fake_build_load_setting_defaults(const fake_data data, fake_build_setting *setting, f_status *status) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_build_load_setting_defaults_
+
+/**
+ * Load and process the setting buffer.
+ *
+ * @param data
+ *   The program data.
+ * @param path_file
+ *   The path to the buffer.
+ * @param buffer
+ *   The loaded file data.
+ * @param objects
+ *   The object mapping.
+ * @param contents
+ *   The content mapping.
+ * @param setting
+ *   All build related setting data from the build setting file are loaded into this.
+ *   These setting will have any specified mode property applied.
+ * @param status
+ *   The return status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_build_load_setting_process_
+  extern void fake_build_load_setting_process(const fake_data data, const f_string path_file, const f_string_static buffer, const f_fss_objects objects, const f_fss_contents contents, fake_build_setting *setting, f_status *status) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_build_load_setting_process_
+
+/**
  * Load the environment used when executing commands.
  *
  * @param data
@@ -642,7 +672,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fake_build_load_environment_
-  extern void fake_build_load_environment(const fake_data data, const fake_build_data data_build, fake_build_environment *environment, f_status *status) f_gcc_attribute_visibility_internal;
+  extern void fake_build_load_environment(const fake_data data, const fake_build_data data_build, fake_environment *environment, f_status *status) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_build_load_environment_
 
 /**
index f2c3567bfc3185696f9acc39b7590ffa4e0f232c..37cc38c7790f84c66e30ca320fe79562803ba601 100644 (file)
@@ -6,6 +6,62 @@
 extern "C" {
 #endif
 
+#ifndef _di_fake_file_buffer_
+  f_return_status fake_file_buffer(const fake_data data, const f_string path_file, f_string_dynamic *buffer) {
+    f_file file = f_file_initialize;
+    f_string name_function = "f_file_exists";
+    f_status status = F_none;
+
+    status = f_file_exists(data.file_data_build_settings.string);
+
+    if (status == F_true) {
+      {
+        f_string_length size_file = 0;
+
+        name_function = "f_file_size";
+        status = f_file_size(path_file, F_true, &size_file);
+
+        if (F_status_is_not_error(status)) {
+          if (size_file > fake_common_initial_buffer_max) {
+            size_file = fake_common_initial_buffer_max;
+          }
+
+          f_macro_string_dynamic_new((status), (*buffer), size_file);
+          if (F_status_is_error(status)) {
+            fake_print_error_file(data.context, data.verbosity, F_status_set_fine(status), name_function, path_file, "allocate buffer size for", F_true, F_true);
+
+            f_macro_string_dynamic_delete_simple((*buffer));
+            return status;
+          }
+        }
+
+        status = F_true;
+      }
+
+      name_function = "f_file_open";
+      status = f_file_open(path_file, 0, &file);
+
+      if (F_status_is_not_error(status)) {
+        name_function = "f_file_read";
+        status = f_file_read(file, buffer);
+
+        f_file_close(&file.id);
+      }
+    }
+    else if (status == F_false) {
+      status = F_status_set_error(F_file_found_not);
+    }
+
+    if (F_status_is_error(status)) {
+      fake_print_error_file(data.context, data.verbosity, F_status_set_fine(status), name_function, path_file, "read", F_true, F_true);
+
+      f_macro_string_dynamic_delete_simple((*buffer));
+    }
+
+    return status;
+  }
+#endif // _di_fake_file_buffer_
+
 #ifndef _di_fake_path_generate_
   f_return_status fake_path_generate(fake_data *data) {
     f_status status = F_none;
@@ -138,7 +194,7 @@ extern "C" {
       const uint8_t parameters_length[] = {
         3,
         3,
-        3,
+        4,
         1,
       };
 
@@ -157,6 +213,7 @@ extern "C" {
       f_string_dynamic *parameters_value_2[] = {
         &data->file_data_build_defines,
         &data->file_data_build_dependencies,
+        &data->file_data_build_fakefile,
         &data->file_data_build_settings,
       };
 
@@ -191,6 +248,7 @@ extern "C" {
         fake_path_part_static,
         fake_file_defines,
         fake_file_dependencies,
+        fake_file_fakefile,
         fake_file_settings,
         fake_file_readme,
       };
@@ -204,6 +262,7 @@ extern "C" {
         fake_path_part_static_length,
         fake_file_defines_length,
         fake_file_dependencies_length,
+        fake_file_fakefile_length,
         fake_file_settings_length,
         fake_file_readme_length,
       };
@@ -217,11 +276,12 @@ extern "C" {
         &data->path_build_programs_static,
         &data->file_data_build_defines,
         &data->file_data_build_dependencies,
+        &data->file_data_build_fakefile,
         &data->file_data_build_settings,
         &data->file_documents_readme,
       };
 
-      for (i = 0; i < 10; i++) {
+      for (i = 0; i < 11; i++) {
         status = fl_string_append_nulless(parameters_source[i], parameters_length[i], parameters_value[i]);
 
         if (F_status_is_error(status)) {
index 779e7698cf142bcafe39adc5fc153de5ffd320b2..faca904330d6a93971b66e6ba88f1a1375cf5f8c 100644 (file)
 extern "C" {
 #endif
 
+#ifndef _di_fake_common_
+  #define fake_common_initial_buffer_max 131072 // 128k max default initial buffer size.
+
+  #define fake_common_setting_bool_yes "yes"
+  #define fake_common_setting_bool_no  "no"
+
+  #define fake_common_setting_bool_yes_length 3
+  #define fake_common_setting_bool_no_length  2
+#endif // _di_fake_common_
+
+#ifndef _di_fake_environment_
+  typedef struct {
+    f_string_dynamics names;
+    f_string_dynamics values;
+  } fake_environment;
+
+  #define fake_environment_initialize { \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+  }
+
+  #define fake_macro_environment_delete_simple(environment) \
+    f_macro_string_dynamics_delete_simple(environment.names) \
+    f_macro_string_dynamics_delete_simple(environment.values)
+#endif // _di_fake_environment_
+
+/**
+ * Load the contents of a file into the given buffer, handling all potential errors.
+ *
+ * @param data
+ *   The program data.
+ * @param path_file
+ *   The path to the file to load.
+ * @param buffer
+ *   A buffer containing the contents of the file.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_file_buffer_
+  extern f_return_status fake_file_buffer(const fake_data data, const f_string path_file, f_string_dynamic *buffer) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_file_buffer_
+
 /**
  * Generate all appropriate paths based on runtime information.
  *
index 90cbdd92a20f26d802045020affbe5a9d3a53e81..9e41acf92ce293d445f830d82dae2105cd5a992e 100644 (file)
@@ -1,7 +1,7 @@
 #include <level_3/fake.h>
+#include "private-fake.h"
 #include "private-build.h"
 #include "private-clean.h"
-#include "private-fake.h"
 #include "private-make.h"
 #include "private-print.h"
 #include "private-skeleton.h"
 extern "C" {
 #endif
 
+#ifndef _di_fake_make_load_setting_
+  void fake_make_load_setting(const fake_data data, fake_make_data *data_make, f_status *status) {
+    if (F_status_is_error(*status)) return;
+
+    *status = fake_file_buffer(data, data.file_data_build_fakefile.string, &data_make->buffer);
+    if (F_status_is_error(*status)) return;
+
+    if (!data_make->buffer.used) {
+      if (data.verbosity == fake_verbosity_verbose) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_warning, data.context.warning, data.context.reset, "WARNING: the fakefile '");
+        fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", data.file_data_build_fakefile.string);
+        fl_color_print(f_type_warning, data.context.warning, data.context.reset, "' is empty.");
+      }
+
+      return;
+    }
+
+    f_fss_objects list_objects = f_fss_objects_initialize;
+    f_fss_contents list_contents = f_fss_contents_initialize;
+
+    {
+      f_string_range range = f_macro_string_range_initialize(data_make->buffer.used);
+
+      *status = fll_fss_basic_list_read(&data_make->buffer, &range, &list_objects, &list_contents);
+      if (F_status_is_error(*status)) {
+        fake_print_error_fss(data.context, data.verbosity, *status, "fll_fss_basic_list_read", data.file_data_build_fakefile.string, range, F_true);
+
+        f_macro_fss_objects_delete_simple(list_objects);
+        f_macro_fss_contents_delete_simple(list_contents);
+        return;
+      }
+    }
+
+    {
+      bool missing_main = F_true;
+      bool missing_settings = F_true;
+
+      f_fss_set settings = f_fss_set_initialize;
+
+      const f_string_static name_settings = f_macro_string_static_initialize(fake_make_section_settings, fake_make_section_settings_length);
+      const f_string_static name_main = f_macro_string_static_initialize(fake_make_section_main, fake_make_section_main_length);
+
+      const f_string_range name_settings_range = f_macro_string_range_initialize(fake_make_section_settings_length);
+      const f_string_range name_main_range = f_macro_string_range_initialize(fake_make_section_main_length);
+
+      f_macro_fss_nameds_new((*status), data_make->fakefile, list_objects.used);
+      if (F_status_is_error(*status)) {
+        fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "f_macro_fss_nameds_new", F_true);
+
+        f_macro_fss_set_delete_simple(settings);
+        f_macro_fss_objects_delete_simple(list_objects);
+        f_macro_fss_contents_delete_simple(list_contents);
+        return;
+      }
+
+      {
+        f_string_range content_range = f_string_range_initialize;
+
+        for (f_array_length i = 0; i < list_objects.used; i++) {
+          if (fl_string_dynamic_partial_compare(name_settings, data_make->buffer, name_settings_range, list_objects.array[i]) == F_equal_to) {
+            if (!missing_settings) {
+              fake_print_warning_fakefile_object_multiple(data.context, data.verbosity, data.file_data_build_fakefile.string, "list", name_settings.string);
+              continue;
+            }
+
+            content_range = list_contents.array[i].array[0];
+
+            *status = fll_fss_extended_read(&data_make->buffer, &content_range, &settings.objects, &settings.contents);
+            if (F_status_is_error(*status)) {
+              fake_print_error_fss(data.context, data.verbosity, *status, "fll_fss_extended_read", data.file_data_build_fakefile.string, content_range, F_true);
+
+              f_macro_fss_set_delete_simple(settings);
+              f_macro_fss_objects_delete_simple(list_objects);
+              f_macro_fss_contents_delete_simple(list_contents);
+              return;
+            }
+
+            missing_settings = F_false;
+          }
+          else if (fl_string_dynamic_partial_compare(name_main, data_make->buffer, name_main_range, list_objects.array[i]) == F_equal_to) {
+            if (!missing_main) {
+              fake_print_warning_fakefile_object_multiple(data.context, data.verbosity, data.file_data_build_fakefile.string, "list", name_main.string);
+              continue;
+            }
+
+            missing_main = F_false;
+            data_make->main = i;
+          }
+        } // for
+      }
+
+      f_macro_fss_objects_delete_simple(list_objects);
+      f_macro_fss_contents_delete_simple(list_contents);
+
+      if (missing_main) {
+        if (data.verbosity != fake_verbosity_quiet) {
+          fprintf(f_type_error, "%c", f_string_eol[0]);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: the fakefile '");
+          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", data.file_data_build_fakefile.string);
+          fl_color_print(f_type_error, data.context.error, data.context.reset, "' is missing the required '");
+          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_make_section_main);
+          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' object.");
+        }
+
+        *status = F_status_set_error(F_failure);
+
+        f_macro_fss_set_delete_simple(settings);
+        return;
+      }
+
+      // look for load_build to determine if settings from the build settings file should be loaded.
+      const f_string_range range_load_build = f_macro_string_range_initialize(fake_make_setting_load_build_length);
+
+      data_make->setting_make.load_build = F_true;
+
+      if (settings.objects.used) {
+        const f_string_range range_yes = f_macro_string_range_initialize(fake_common_setting_bool_yes_length);
+        const f_string_range range_no = f_macro_string_range_initialize(fake_common_setting_bool_no_length);
+
+        const f_string_static name_settings_load_build = f_macro_string_static_initialize(fake_make_setting_load_build, fake_make_setting_load_build_length);
+        const f_string_static value_settings_load_build_yes = f_macro_string_static_initialize(fake_common_setting_bool_yes, fake_common_setting_bool_yes_length);
+        const f_string_static value_settings_load_build_no = f_macro_string_static_initialize(fake_common_setting_bool_no, fake_common_setting_bool_no_length);
+
+        for (f_array_length i = 0; i < settings.objects.used; i++) {
+          if (fl_string_dynamic_partial_compare(name_settings_load_build, data_make->buffer, range_load_build, settings.objects.array[i]) == F_equal_to) {
+            if (settings.contents.array[i].used) {
+              if (fl_string_dynamic_partial_compare(value_settings_load_build_yes, data_make->buffer, range_yes, settings.contents.array[i].array[0]) == F_equal_to) {
+                data_make->setting_make.load_build = F_true;
+              }
+              else if (fl_string_dynamic_partial_compare(value_settings_load_build_no, data_make->buffer, range_no, settings.contents.array[i].array[0]) == F_equal_to) {
+                data_make->setting_make.load_build = F_false;
+              }
+              else {
+                fake_print_error_fakefile_settings_content_invalid(data.context, data.verbosity, data.file_data_build_fakefile.string, data_make->buffer, settings.objects.array[i], settings.contents.array[i].array[0], fake_make_section_settings);
+              }
+            }
+
+            if (settings.contents.array[i].used > 1) {
+              fake_print_warning_settings_content_multiple(data.context, data.verbosity, data.file_data_build_fakefile.string, fake_make_setting_load_build);
+            }
+
+            break;
+          }
+        } // for
+      }
+
+      if (data_make->setting_make.load_build) {
+        fake_build_load_setting(data, &data_make->setting_build, status);
+      }
+
+      fake_build_load_setting_process(data, data.file_data_build_fakefile.string, data_make->buffer, settings.objects, settings.contents, &data_make->setting_build, status);
+
+      if (F_status_is_not_error(*status) && settings.objects.used) {
+        const f_string settings_name[] = {
+          fake_make_setting_define,
+          fake_make_setting_parameter,
+        };
+
+        const f_string_length settings_length[] = {
+          fake_make_setting_define_length,
+          fake_make_setting_parameter_length,
+        };
+
+        f_string_map_multis *settings_value[] = {
+          &data_make->setting_make.define,
+          &data_make->setting_make.parameter,
+        };
+
+        *status = fll_fss_snatch_map_mash_apart(data_make->buffer, settings.objects, settings.contents, settings_name, settings_length, 2, " ", 1, settings_value);
+        if (F_status_is_error(*status)) {
+          fake_print_error(data.context, data.verbosity, F_status_set_fine(*status), "fll_fss_snatch_map_mash_apart", F_true);
+
+          //@todo fake_print_error_fss(data.context, data.verbosity, *status, "fll_fss_snatch_map", data.file_data_build_fakefile.string, content_range, F_true);
+
+          f_macro_fss_set_delete_simple(settings);
+          return;
+        }
+      }
+
+      // @todo load any defaults for unassigned values.
+
+      f_macro_fss_set_delete_simple(settings);
+    }
+  }
+#endif // _di_fake_make_load_setting_
+
+#ifndef _di_fake_make_operate_
+  f_return_status fake_make_operate(const fake_data data) {
+    if (data.verbosity != fake_verbosity_quiet) {
+      printf("%c", f_string_eol[0]);
+      fl_color_print_line(f_type_output, data.color_section_set, data.color_section_reset, "Making project.");
+    }
+
+    f_status status = F_none;
+    f_mode mode = f_mode_initialize;
+
+    fake_make_data data_make = fake_make_data_initialize;
+
+    f_macro_mode_set_default_umask(mode, data.umask);
+
+    fake_make_load_setting(data, &data_make, &status);
+
+    // @todo
+
+    fake_macro_make_data_delete_simple(data_make);
+
+    return status;
+  }
+#endif // _di_fake_make_operate_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 1869040c08990be9b73dea16b5b1caa64b88275a..77b271b9d9fab71b4db4c7082d6fd50891c63710 100644 (file)
@@ -22,11 +22,32 @@ extern "C" {
 
 // @todo safety checks that ensures operations on files only happen inside the project directory, represented by "top".
 #ifndef _di_fake_make_setting_
+  typedef struct {
+    bool load_build;
+
+    f_string_map_multis define;
+    f_string_map_multis parameter;
+  } fake_make_setting;
+
+  #define fake_make_setting_initialize { \
+    0, \
+    f_string_map_multis_initialize, \
+    f_string_map_multis_initialize, \
+  }
+
+  #define fake_macro_make_setting_delete_simple(setting) \
+    f_macro_string_map_multis_delete_simple(setting.define) \
+    f_macro_string_map_multis_delete_simple(setting.parameter)
+
   #define fake_make_setting_define     "define"     // @todo 'define' means define this as an environment variable on run, only a single argument is supported. (consider a second parameter such as 'if_missing' or 'if_exists' to define this only if it is not already defined.)
   #define fake_make_setting_load_build "load_build" // @todo ("yes"/"no") as in use the build settings file, write code to import that first and match all settings from that into this.
+  #define fake_make_setting_parameter  "parameter"  // @todo see parameters below, first content is parameter name, second content is parameter values.
 
   #define fake_make_setting_define_length     6
   #define fake_make_setting_load_build_length 10
+  #define fake_make_setting_parameter_length  9
+
+  #define fake_make_setting_total_length 3
 #endif // _di_fake_make_setting_
 
 // @todo "operate" should use a call stack, but do not allow recursive calls (check to see if named operation is already on the call stack).
@@ -150,22 +171,107 @@ extern "C" {
   } fake_make_parameter;
 
   #define fake_make_parameter_initialize { \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
-    f_string_dynamics_initialize \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
+    f_string_dynamics_initialize, \
   }
+
+  #define fake_macro_make_parameter_delete_simple(parameter) \
+    f_macro_string_dynamics_delete_simple(parameter.build) \
+    f_macro_string_dynamics_delete_simple(parameter.dark) \
+    f_macro_string_dynamics_delete_simple(parameter.data) \
+    f_macro_string_dynamics_delete_simple(parameter.define) \
+    f_macro_string_dynamics_delete_simple(parameter.light) \
+    f_macro_string_dynamics_delete_simple(parameter.mode) \
+    f_macro_string_dynamics_delete_simple(parameter.no_color) \
+    f_macro_string_dynamics_delete_simple(parameter.process) \
+    f_macro_string_dynamics_delete_simple(parameter.quiet) \
+    f_macro_string_dynamics_delete_simple(parameter.settings) \
+    f_macro_string_dynamics_delete_simple(parameter.sources) \
+    f_macro_string_dynamics_delete_simple(parameter.verbose) \
+    f_macro_string_dynamics_delete_simple(parameter.work)
 #endif // _di_fake_make_parameter_
 
+#ifndef _di_fake_make_data_
+  typedef struct {
+    fake_build_setting setting_build;
+    fake_make_setting setting_make;
+
+    fake_environment environment;
+    fake_make_parameter parameter;
+
+    f_fss_nameds fakefile;
+    f_string_dynamic buffer;
+    f_string_length main;
+  } fake_make_data;
+
+  #define fake_make_data_initialize { \
+    fake_build_setting_initialize, \
+    fake_make_setting_initialize, \
+    fake_environment_initialize, \
+    fake_make_parameter_initialize, \
+    f_fss_nameds_initialize, \
+    f_string_dynamic_initialize, \
+    0, \
+  }
+
+  #define fake_macro_make_data_delete_simple(data) \
+    fake_macro_build_setting_delete_simple(data.setting_build) \
+    fake_macro_make_setting_delete_simple(data.setting_make) \
+    fake_macro_environment_delete_simple(data.environment) \
+    fake_macro_make_parameter_delete_simple(data.parameter) \
+    f_macro_fss_nameds_delete_simple(data.fakefile) \
+    f_macro_string_dynamic_delete_simple(data.buffer)
+#endif // _di_fake_make_data_
+
+/**
+ * Find the fake file, load it, validate it, and process it.
+ *
+ * This will process any additional files as necessary, such as the build settings file.
+ *
+ * @param data
+ *   The program data.
+ * @param data_make
+ *   All make related setting data, including data from the fakefile and optionally build settings file.
+ * @param status
+ *   The return status.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ *
+ * @see fake_build_load_setting()
+ */
+#ifndef _di_fake_make_load_setting_
+  extern void fake_make_load_setting(const fake_data data, fake_make_data *data_make, f_status *status) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_make_load_setting_
+
+/**
+ * Execute the make operation.
+ *
+ * @param data
+ *   The program data.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Status codes (with error bit) are returned on any problem.
+ */
+#ifndef _di_fake_make_operate_
+  extern f_return_status fake_make_operate(const fake_data data) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_make_operate_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 9f66fd5a6f6ea1854ef059868108837dec8150bf..446ed812bc82c8c8e1d75db2ec21cf9c07eb7871 100644 (file)
@@ -44,6 +44,32 @@ extern "C" {
   }
 #endif // _di_fake_print_error_
 
+#ifndef _di_fake_print_error_fakefile_settings_content_invalid_
+  void fake_print_error_fakefile_settings_content_invalid(const fl_color_context context, const uint8_t verbosity, const f_string path_file, const f_string_dynamic buffer, const f_string_range range_object, const f_string_range range_content, const f_string settings_name) {
+    if (verbosity != fake_verbosity_verbose) return;
+
+    fprintf(f_type_error, "%c", f_string_eol[0]);
+
+    fl_color_print(f_type_warning, context.warning, context.reset, "WARNING: the fakefile '");
+    fl_color_print(f_type_warning, context.notable, context.reset, "%s", path_file);
+    fl_color_print(f_type_warning, context.warning, context.reset, "' has an invalid content '");
+
+    fl_color_print_code(f_type_warning, context.notable);
+    f_print_string_dynamic_partial(f_type_warning, buffer, range_content);
+    fl_color_print_code(f_type_warning, context.reset);
+
+    fl_color_print(f_type_warning, context.warning, context.reset, "' for the '");
+    fl_color_print(f_type_warning, context.notable, context.reset, "%s", settings_name);
+    fl_color_print(f_type_warning, context.warning, context.reset, "' object '");
+
+    fl_color_print_code(f_type_warning, context.notable);
+    f_print_string_dynamic_partial(f_type_warning, buffer, range_object);
+    fl_color_print_code(f_type_warning, context.reset);
+
+    fl_color_print_line(f_type_warning, context.warning, context.reset, "'.");
+  }
+#endif // _di_fake_print_error_fakefile_settings_content_invalid_
+
 #ifndef _di_fake_print_error_file_
   bool fake_print_error_file(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string name, const f_string operation, const bool is_file, const bool fallback) {
     f_string file_or_directory = 0;
@@ -62,6 +88,17 @@ extern "C" {
       return F_false;
     }
 
+    if (status == F_file_found) {
+      if (verbosity != fake_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ERROR: the %s '", file_or_directory);
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", name);
+        fl_color_print_line(f_type_error, context.error, context.reset, "' already exists.");
+      }
+
+      return F_false;
+    }
+
     if (status == F_parameter) {
       if (verbosity != fake_verbosity_quiet) {
         fprintf(f_type_error, "%c", f_string_eol[0]);
@@ -201,6 +238,48 @@ extern "C" {
   }
 #endif // _di_fake_print_error_file_
 
+#ifndef _di_fake_print_error_fss
+  bool fake_print_error_fss(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string path_file, const f_string_range range, const bool fallback) {
+
+    if (status == F_file_found_not) {
+      if (verbosity != fake_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ENCODING ERROR: error occurred on invalid UTF-8 character at stop position (at ");
+        fl_color_print(f_type_error, context.notable, context.reset, "%d", range.start);
+        fl_color_print(f_type_error, context.error, context.reset, " of setting file '");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", path_file);
+        fl_color_print_line(f_type_error, context.error, context.reset, "').");
+      }
+
+      return F_false;
+    }
+
+    if (status == F_status_set_error(F_incomplete_utf_stop)) {
+      if (verbosity != fake_verbosity_quiet) {
+        fprintf(f_type_error, "%c", f_string_eol[0]);
+        fl_color_print(f_type_error, context.error, context.reset, "ENCODING ERROR: error occurred on invalid UTF-8 character at end of string (at ");
+        fl_color_print(f_type_error, context.notable, context.reset, "%d", range.start);
+        fl_color_print(f_type_error, context.error, context.reset, " of setting file '");
+        fl_color_print(f_type_error, context.notable, context.reset, "%s", path_file);
+        fl_color_print_line(f_type_error, context.error, context.reset, "').");
+      }
+
+      return F_false;
+    }
+
+    if (fake_print_error(context, verbosity, status, function, F_false) == F_unknown && fallback && verbosity != fake_verbosity_quiet) {
+      fprintf(f_type_error, "%c", f_string_eol[0]);
+      fl_color_print(f_type_error, context.error, context.reset, "UNKNOWN ERROR: (");
+      fl_color_print(f_type_error, context.notable, context.reset, "%d", status);
+      fl_color_print(f_type_error, context.error, context.reset, ") in function ");
+      fl_color_print(f_type_error, context.notable, context.reset, "%s", function);
+      fl_color_print_line(f_type_error, context.error, context.reset, "().");
+    }
+
+    return F_true;
+  }
+#endif // _di_fake_print_error_fss
+
 #ifndef _di_fake_print_error_operation_
   bool fake_print_error_operation(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string operation, const f_string how, const f_string source, const f_string destination, const bool fallback) {
 
@@ -426,8 +505,10 @@ extern "C" {
   void fake_print_error_parameter_missing_value(const fl_color_context context, const uint8_t verbosity, const f_string parameter) {
     if (verbosity != fake_verbosity_quiet) {
       fprintf(f_type_error, "%c", f_string_eol[0]);
+
       fl_color_print(f_type_error, context.error, context.reset, "ERROR: The parameter '");
       fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+
       fl_color_print_line(f_type_error, context.error, context.reset, "' was specified, but no value was given.");
     }
   }
@@ -437,13 +518,45 @@ extern "C" {
   void fake_print_error_parameter_too_many(const fl_color_context context, const uint8_t verbosity, const f_string parameter) {
     if (verbosity != fake_verbosity_quiet) {
       fprintf(f_type_error, "%c", f_string_eol[0]);
+
       fl_color_print(f_type_error, context.error, context.reset, "ERROR: the parameter '");
       fl_color_print(f_type_error, context.notable, context.reset, "%s%s", f_console_symbol_long_enable, parameter);
+
       fl_color_print_line(f_type_error, context.error, context.reset, "' specified too many times.");
     }
   }
 #endif // _di_fake_print_error_parameter_too_many_
 
+#ifndef _di_fake_print_warning_fakefile_object_multiple_
+  void fake_print_warning_fakefile_object_multiple(const fl_color_context context, const uint8_t verbosity, const f_string path_file, const f_string label, const f_string name_object) {
+    if (verbosity != fake_verbosity_verbose) return;
+
+    fprintf(f_type_error, "%c", f_string_eol[0]);
+
+    fl_color_print(f_type_warning, context.warning, context.reset, "WARNING: the %s object '", label);
+    fl_color_print(f_type_warning, context.notable, context.reset, "%s", name_object);
+    fl_color_print(f_type_warning, context.warning, context.reset, "' in the file '");
+    fl_color_print(f_type_warning, context.notable, context.reset, "%s", path_file);
+
+    fl_color_print_line(f_type_warning, context.warning, context.reset, "' may only be specified once, only using the first.");
+  }
+#endif // _di_fake_print_warning_fakefile_object_multiple_
+
+#ifndef _di_fake_print_warning_settings_content_multiple_
+  void fake_print_warning_settings_content_multiple(const fl_color_context context, const uint8_t verbosity, const f_string path_file, const f_string name_object) {
+    if (verbosity != fake_verbosity_verbose) return;
+
+    fprintf(f_type_error, "%c", f_string_eol[0]);
+
+    fl_color_print(f_type_warning, context.warning, context.reset, "WARNING: the setting object '");
+    fl_color_print(f_type_warning, context.notable, context.reset, "%s", name_object);
+    fl_color_print(f_type_warning, context.warning, context.reset, "' in the file '");
+    fl_color_print(f_type_warning, context.notable, context.reset, "%s", path_file);
+
+    fl_color_print_line(f_type_warning, context.warning, context.reset, "' may only have a single content, only using the first.");
+  }
+#endif // _di_fake_print_warning_settings_content_multiple_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index b15a299af66bf7582733d150a8bbd1e5b2d57876..6d056b76a5d778b01e1152cabb6a9a70d6c3276d 100644 (file)
@@ -35,6 +35,28 @@ extern "C" {
 #endif // _di_fake_print_error_
 
 /**
+ * Print error message when fake settings content is invalid.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param path_file
+ *   The path to the fakefile.
+ * @param buffer
+ *   The buffer containing the loaded file content.
+ * @param range_object
+ *   The range within the buffer representing the object.
+ * @param range_content
+ *   The range within the buffer representing the content.
+ * @param settings_name
+ *   The name of the setting that has an invalid value.
+ */
+#ifndef _di_fake_print_error_fakefile_settings_content_invalid_
+  extern void fake_print_error_fakefile_settings_content_invalid(const fl_color_context context, const uint8_t verbosity, const f_string path_file, const f_string_dynamic buffer, const f_string_range range_object, const f_string_range range_content, const f_string settings_name) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_print_error_fakefile_settings_content_invalid_
+
+/**
  * Print file/directory error messages.
  *
  * @param context
@@ -63,6 +85,32 @@ extern "C" {
 #endif // _di_fake_print_error_file_
 
 /**
+ * Print FSS error messages.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param status
+ *   The error status code to report on.
+ * @param function
+ *   The function call that returned the error.
+ * @param path_file
+ *   The path to the file.
+ * @param range
+ *   The range representing the position in the buffer such that range.start is where the error happened.
+ * @param fallback
+ *   Set to F_true to print the fallback error message for unknown errors.
+ *
+ * @return
+ *   F_true is returned if the status code has no print message.
+ *   F_false is returned on successful print of known errors.
+ */
+#ifndef _di_fake_print_error_fss
+  extern bool fake_print_error_fss(const fl_color_context context, const uint8_t verbosity, const f_status status, const f_string function, const f_string path_file, const f_string_range range, const bool fallback) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_print_error_fss
+
+/**
  * Print operation error messages.
  *
  * @param context
@@ -121,6 +169,44 @@ extern "C" {
   extern void fake_print_error_parameter_too_many(const fl_color_context context, const uint8_t verbosity, const f_string parameter) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_print_error_parameter_too_many_
 
+/**
+ * Print warning message when fakefile has too many objects with the same name.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param path_file
+ *   The path to the fakefile.
+ * @param buffer
+ *   The buffer containing the loaded file content.
+ * @param label
+ *   A label describing what this object belongs to.
+ * @param name_object
+ *   The name of the object.
+ */
+#ifndef _di_fake_print_warning_fakefile_object_multiple_
+  extern void fake_print_warning_fakefile_object_multiple(const fl_color_context context, const uint8_t verbosity, const f_string path_file, const f_string label, const f_string name_object) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_print_warning_fakefile_object_multiple_
+
+/**
+ * Print warning message when settings content has too many values.
+ *
+ * @param context
+ *   The color context.
+ * @param verbosity
+ *   The verbosity level, which determines if and what should be printed.
+ * @param path_file
+ *   The path to the fakefile.
+ * @param buffer
+ *   The buffer containing the loaded file content.
+ * @param name_object
+ *   The name of the object.
+ */
+#ifndef _di_fake_print_warning_settings_content_multiple_
+  extern void fake_print_warning_settings_content_multiple(const fl_color_context context, const uint8_t verbosity, const f_string path_file, const f_string name_object) f_gcc_attribute_visibility_internal;
+#endif // _di_fake_print_warning_settings_content_multiple_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 11ba07e124a1979bf539128b9a3fbe29f4f759de..da904da6d660dd65f7064c022e462865f4d18f97 100644 (file)
@@ -1,5 +1,6 @@
 #include <level_3/fake.h>
 #include "private-fake.h"
+#include "private-build.h"
 #include "private-print.h"
 #include "private-skeleton.h"
 
@@ -52,29 +53,58 @@ extern "C" {
 
     f_string_dynamic file_data_build_process_post = f_string_dynamic_initialize;
     f_string_dynamic file_data_build_process_pre = f_string_dynamic_initialize;
+    f_string_dynamic content = f_string_dynamic_initialize;
 
-    if (!F_status_is_error(status)) {
-      status = fake_skeleton_operate_file_create(data, data.file_data_build_defines, F_false);
+    if (F_status_is_not_error(status)) {
+      content.string = fake_make_skeleton_content_defines;
+      content.used = fake_make_skeleton_content_defines_length;
+      content.size = content.used;
+
+      status = fake_skeleton_operate_file_create(data, data.file_data_build_defines, F_false, content);
+
+      content.used = 0;
     }
 
-    if (!F_status_is_error(status)) {
-      status = fake_skeleton_operate_file_create(data, data.file_data_build_dependencies, F_false);
+    if (F_status_is_not_error(status)) {
+      content.string = fake_make_skeleton_content_dependencies;
+      content.used = fake_make_skeleton_content_dependencies_length;
+      content.size = content.used;
+
+      status = fake_skeleton_operate_file_create(data, data.file_data_build_dependencies, F_false, content);
+
+      content.used = 0;
     }
 
-    if (!F_status_is_error(status)) {
-      status = fake_skeleton_operate_file_create(data, file_data_build_process_post, F_true);
+    if (F_status_is_not_error(status)) {
+      status = fake_skeleton_operate_file_create(data, file_data_build_process_post, F_true, content);
     }
 
-    if (!F_status_is_error(status)) {
-      status = fake_skeleton_operate_file_create(data, file_data_build_process_pre, F_true);
+    if (F_status_is_not_error(status)) {
+      status = fake_skeleton_operate_file_create(data, file_data_build_process_pre, F_true, content);
+    }
+
+    if (F_status_is_not_error(status)) {
+      content.string = fake_make_skeleton_content_settings;
+      content.used = fake_make_skeleton_content_settings_length;
+      content.size = content.used;
+
+      status = fake_skeleton_operate_file_create(data, data.file_data_build_settings, F_false, content);
+
+      content.used = 0;
     }
 
-    if (!F_status_is_error(status)) {
-      status = fake_skeleton_operate_file_create(data, data.file_data_build_settings, F_false);
+    if (F_status_is_not_error(status)) {
+      status = fake_skeleton_operate_file_create(data, data.file_documents_readme, F_false, content);
     }
 
-    if (!F_status_is_error(status)) {
-      status = fake_skeleton_operate_file_create(data, data.file_documents_readme, F_false);
+    if (F_status_is_not_error(status)) {
+      content.string = fake_make_skeleton_content_fakefile;
+      content.used = fake_make_skeleton_content_fakefile_length;
+      content.size = content.used;
+
+      status = fake_skeleton_operate_file_create(data, data.file_data_build_fakefile, F_false, content);
+
+      content.used = 0;
     }
 
     if (F_status_is_error(status)) {
@@ -143,7 +173,7 @@ extern "C" {
 #endif // _di_fake_skeleton_operate_directory_create_
 
 #ifndef _di_fake_skeleton_operate_file_create_
-  f_return_status fake_skeleton_operate_file_create(const fake_data data, const f_string_dynamic path, const bool executable) {
+  f_return_status fake_skeleton_operate_file_create(const fake_data data, const f_string_dynamic path, const bool executable, const f_string_static content) {
     f_status status = F_none;
 
     if (path.used == 0) return F_none;
@@ -203,6 +233,34 @@ extern "C" {
       if (data.verbosity == fake_verbosity_verbose) {
         printf("File '%s' created.%c", path.string, f_string_eol[0]);
       }
+
+      if (content.used) {
+        f_file file = f_file_initialize;
+
+        file.flag = f_file_flag_append_wo;
+        file.size_write = content.used;
+
+        status = f_file_open(path.string, 0, &file);
+        if (F_status_is_error(status)) {
+          fake_print_error_file(data.context, data.verbosity, F_status_set_fine(status), "f_file_open", path.string, "pre-populate", F_true, F_true);
+
+          return status;
+        }
+
+        status = f_file_write(file, content, 0);
+        if (F_status_is_error(status)) {
+          fake_print_error_file(data.context, data.verbosity, F_status_set_fine(status), "f_file_write", path.string, "pre-populate", F_true, F_true);
+
+          f_file_close(&file.id);
+          return status;
+        }
+
+        if (data.verbosity == fake_verbosity_verbose) {
+          printf("File '%s' pre-populated.%c", path.string, f_string_eol[0]);
+        }
+
+        f_file_close(&file.id);
+      }
     }
     else if (F_status_is_error(status)) {
       fake_print_error_file(data.context, data.verbosity, F_status_set_fine(status), "f_file_is", path.string, "create", F_true, F_true);
index 38d0b61e51843b62bcd441386937faa503ff12e3..e44393a1db88ffe1440eabca8f6edf6417d733fd 100644 (file)
@@ -8,6 +8,18 @@
 #ifndef _PRIVATE_skeleton_h
 #define _PRIVATE_skeleton_h
 
+#ifndef _di_fake_skeleton_content_
+  #define fake_make_skeleton_content_defines      "# fss-0000\n\n"
+  #define fake_make_skeleton_content_dependencies "# fss-0000\n\n"
+  #define fake_make_skeleton_content_fakefile     "# fss-0005\n\nsettings:\n\nmain:\n\n"
+  #define fake_make_skeleton_content_settings     "# fss-0001\n\n"
+
+  #define fake_make_skeleton_content_defines_length      12
+  #define fake_make_skeleton_content_dependencies_length 12
+  #define fake_make_skeleton_content_fakefile_length     30
+  #define fake_make_skeleton_content_settings_length     12
+#endif // _di_fake_skeleton_content_
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -55,6 +67,8 @@ extern "C" {
  * @param executable
  *   Set to TRUE to make the file executable.
  *   Set to FALSE to not make the file executable.
+ * @param content
+ *   When creating a new file, write the content specified by this string to that file.
  *
  * @return
  *   F_none on success.
@@ -63,7 +77,7 @@ extern "C" {
  *   Status codes (with error bit) are returned on any problem.
  */
 #ifndef _di_fake_skeleton_operate_file_create_
-  extern f_return_status fake_skeleton_operate_file_create(const fake_data data, const f_string_dynamic path, const bool executable) f_gcc_attribute_visibility_internal;
+  extern f_return_status fake_skeleton_operate_file_create(const fake_data data, const f_string_dynamic path, const bool executable, const f_string_static content) f_gcc_attribute_visibility_internal;
 #endif // _di_fake_skeleton_operate_file_create_
 
 #ifdef __cplusplus
index 644909de6828d6042a581e5931d4bc7491897fd7..d4c781053efbdf57247eb3d4793cd602fcf95bc3 100644 (file)
@@ -1,3 +1,5 @@
+# fss-0000
+
 f_type
 f_status
 f_memory
diff --git a/level_3/fake/data/build/fakefile b/level_3/fake/data/build/fakefile
new file mode 100644 (file)
index 0000000..68cccd2
--- /dev/null
@@ -0,0 +1,11 @@
+# fss-0005
+
+settings:
+  load_build yes
+
+  define example value
+
+main:
+  print This is a line.
+
+  print This is another line.