]> Kevux Git Server - fll/commitdiff
Progress: featureless make.
authorKevin Day <thekevinday@gmail.com>
Thu, 20 Aug 2020 02:59:55 +0000 (21:59 -0500)
committerKevin Day <thekevinday@gmail.com>
Thu, 20 Aug 2020 03:11:13 +0000 (22:11 -0500)
Remove the 'create' section operation, it is effectively redundant with the 'touch' section operation.
There is still potential for having both because 'touch' section operation has additional actions that could be undesired.
For keeping it simple, I have decided to not support both 'create' and 'touch' at the same time.

Implement 'delete' section operatin and update validation.
Implement 'link' section operation and update validation.

Add 'deletes' section operation that performs a "recursive" delete which allows for deleting non-empty directories.

level_3/fake/c/private-make.c
level_3/fake/c/private-make.h
level_3/fake/c/private-print.c
level_3/fake/documents/fakefile.txt
level_3/fake/specifications/fakefile.txt

index a1f78d1e90f34c6aa349868ff2b308b207200c7a..4c2c5f19ade507ea87f2d25d41e452c529d6fd12 100644 (file)
@@ -1305,9 +1305,9 @@ extern "C" {
       f_macro_string_static_initialize(fake_make_operation_build, fake_make_operation_build_length),
       f_macro_string_static_initialize(fake_make_operation_clean, fake_make_operation_clean_length),
       f_macro_string_static_initialize(fake_make_operation_compile, fake_make_operation_compile_length),
-      f_macro_string_static_initialize(fake_make_operation_create, fake_make_operation_create_length),
       f_macro_string_static_initialize(fake_make_operation_define, fake_make_operation_define_length),
       f_macro_string_static_initialize(fake_make_operation_delete, fake_make_operation_delete_length),
+      f_macro_string_static_initialize(fake_make_operation_deletes, fake_make_operation_deletes_length),
       f_macro_string_static_initialize(fake_make_operation_else, fake_make_operation_else_length),
       f_macro_string_static_initialize(fake_make_operation_fail, fake_make_operation_fail_length),
       f_macro_string_static_initialize(fake_make_operation_group, fake_make_operation_group_length),
@@ -1334,9 +1334,9 @@ extern "C" {
       f_macro_string_range_initialize(fake_make_operation_build_length),
       f_macro_string_range_initialize(fake_make_operation_clean_length),
       f_macro_string_range_initialize(fake_make_operation_compile_length),
-      f_macro_string_range_initialize(fake_make_operation_create_length),
       f_macro_string_range_initialize(fake_make_operation_define_length),
       f_macro_string_range_initialize(fake_make_operation_delete_length),
+      f_macro_string_range_initialize(fake_make_operation_deletes_length),
       f_macro_string_range_initialize(fake_make_operation_else_length),
       f_macro_string_range_initialize(fake_make_operation_fail_length),
       f_macro_string_range_initialize(fake_make_operation_group_length),
@@ -1363,9 +1363,9 @@ extern "C" {
       fake_make_operation_type_build,
       fake_make_operation_type_clean,
       fake_make_operation_type_compile,
-      fake_make_operation_type_create,
       fake_make_operation_type_define,
       fake_make_operation_type_delete,
+      fake_make_operation_type_deletes,
       fake_make_operation_type_else,
       fake_make_operation_type_fail,
       fake_make_operation_type_group,
@@ -1535,24 +1535,73 @@ extern "C" {
       return;
     }
 
-    if (operation == fake_make_operation_type_create) {
-      // fake_make_assure_inside_project
-      // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
-      //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
-      //fake_execute(data, data_make->environment, data_build.setting.build_compiler, arguments, status);
-      return;
-    }
-
     if (operation == fake_make_operation_type_define) {
       // @todo: walk through each existing define to see if it already exists and replace it, otherwise create a new one.
       return;
     }
 
-    if (operation == fake_make_operation_type_delete) {
-      // fake_make_assure_inside_project
-      // *status = fll_execute_arguments_add(values[i], lengths[i], &arguments);
-      //fake_build_arguments_standard_add(data, data_build, F_true, F_true, &arguments, status);
-      //fake_execute(data, data_make->environment, data_build.setting.build_compiler, arguments, status);
+    if (operation == fake_make_operation_type_delete || operation == fake_make_operation_type_deletes) {
+      const int recursion_max = operation == fake_make_operation_type_delete ? 0 : f_directory_descriptors_max;
+      struct stat file_stat;
+
+      for (f_array_length i = 0; i < arguments.used; i++) {
+        memset(&file_stat, 0, sizeof(struct stat));
+
+        *status = f_file_stat(arguments.array[i].string, F_false, &file_stat);
+
+        if (F_status_is_error(*status)) {
+          if (F_status_set_fine(*status) == F_file_found_not) {
+            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 file '");
+              fl_color_print(f_type_warning, data.context.notable, data.context.reset, "%s", arguments.array[i].string);
+              fl_color_print_line(f_type_warning, data.context.warning, data.context.reset, "' was not found.");
+            }
+
+            *status = F_none;
+          }
+          else {
+            fake_print_error_file(data, F_status_set_fine(*status), "f_file_stat", arguments.array[i].string, "delete", F_true, F_true);
+            return;
+          }
+        }
+        else if (f_macro_file_type_is_directory(file_stat.st_mode)) {
+          if (data.verbosity == fake_verbosity_verbose) {
+            *status = f_directory_remove_custom(arguments.array[i].string, recursion_max, F_false, fake_clean_remove_recursively_verbosely);
+          }
+          else {
+            *status = f_directory_remove(arguments.array[i].string, recursion_max, F_false);
+          }
+
+          if (F_status_set_fine(*status) == F_file_found_not) {
+            if (data.verbosity == fake_verbosity_verbose) {
+              printf("The directory '%s' does not exist.%c", arguments.array[i].string, f_string_eol[0]);
+            }
+
+            *status = F_none;
+          }
+
+          if (F_status_is_error(*status)) {
+            fake_print_error_file(data, F_status_set_fine(*status), "f_directory_remove", arguments.array[i].string, "delete", F_false, F_true);
+            return;
+          }
+          else {
+            printf("Removed '%s'.\n", arguments.array[i].string);
+          }
+        }
+        else {
+          *status = f_file_remove(arguments.array[i].string);
+
+          if (F_status_is_error(*status)) {
+            fake_print_error_file(data, F_status_set_fine(*status), "f_file_remove", arguments.array[i].string, "delete", F_true, F_true);
+            return;
+          }
+          else {
+            printf("Removed '%s'.\n", arguments.array[i].string);
+          }
+        }
+      } // for
+
       return;
     }
 
@@ -1573,6 +1622,7 @@ extern "C" {
 
       for (f_array_length i = 1; i < arguments.used; i++) {
         *status = f_file_role_change(arguments.array[i].string, -1, id, F_false);
+
         if (F_status_is_error(*status)) {
           fake_print_error_file(data, *status, "f_file_role_change", arguments.array[i].string, "change group of", F_true, F_true);
         }
@@ -1590,6 +1640,7 @@ extern "C" {
       for (f_array_length i = 1; i < arguments.used; i++) {
         // @todo: recursive.
         *status = f_file_role_change(arguments.array[i].string, -1, id, F_false);
+
         if (F_status_is_error(*status)) {
           fake_print_error_file(data, *status, "f_file_role_change", arguments.array[i].string, "change group of", F_true, F_true);
         }
@@ -1604,8 +1655,12 @@ extern "C" {
     }
 
     if (operation == fake_make_operation_type_link) {
-      // fake_make_assure_inside_project
-      // @todo: create symlink.
+      *status = f_file_link(arguments.array[0].string, arguments.array[1].string);
+
+      if (F_status_is_error(*status)) {
+        fake_print_error_file(data, *status, "f_file_link", arguments.array[1].string, "create link", F_true, F_true);
+      }
+
       return;
     }
 
@@ -1881,40 +1936,42 @@ extern "C" {
 
       f_macro_mode_set_default_umask(mode, data.umask);
 
-      if (data.verbosity == fake_verbosity_verbose) {
-        printf("Touching %s '", arguments.array[0].string);
-        fl_color_print(f_type_output, data.context.notable, data.context.reset, "%s", arguments.array[1].string);
-        printf("'.%c", f_string_eol[0]);
-      }
+      for (f_array_length i = 1; i < arguments.used; i++) {
+        if (data.verbosity == fake_verbosity_verbose) {
+          printf("Touching %s '", arguments.array[0].string);
+          fl_color_print(f_type_output, data.context.notable, data.context.reset, "%s", arguments.array[i].string);
+          printf("'.%c", f_string_eol[0]);
+        }
 
-      if (fl_string_dynamic_compare_string(fake_make_operation_argument_file, arguments.array[0], fake_make_operation_argument_file_length) == F_equal_to) {
-        *status = f_file_touch(arguments.array[1].string, mode.regular, F_false);
+        if (fl_string_dynamic_compare_string(fake_make_operation_argument_file, arguments.array[0], fake_make_operation_argument_file_length) == F_equal_to) {
+          *status = f_file_touch(arguments.array[i].string, mode.regular, F_false);
 
-        if (F_status_is_error(*status)) {
-          if (F_status_is_fine(fll_path_canonical(arguments.array[1].string, &data_make->path_cache))) {
-            fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", data_make->path_cache.string, "touch", F_true, F_true);
-          }
-          else {
-            fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", arguments.array[1].string, "touch", F_true, F_true);
-          }
+          if (F_status_is_error(*status)) {
+            if (F_status_is_fine(fll_path_canonical(arguments.array[i].string, &data_make->path_cache))) {
+              fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", data_make->path_cache.string, "touch", F_true, F_true);
+            }
+            else {
+              fake_print_error_file(data, F_status_set_fine(*status), "f_file_touch", arguments.array[i].string, "touch", F_true, F_true);
+            }
 
-          return;
+            return;
+          }
         }
-      }
-      else if (fl_string_dynamic_compare_string(fake_make_operation_argument_directory, arguments.array[0], fake_make_operation_argument_directory_length) == F_equal_to) {
-        *status = f_directory_touch(arguments.array[1].string, mode.directory);
+        else if (fl_string_dynamic_compare_string(fake_make_operation_argument_directory, arguments.array[0], fake_make_operation_argument_directory_length) == F_equal_to) {
+          *status = f_directory_touch(arguments.array[i].string, mode.directory);
 
-        if (F_status_is_error(*status)) {
-          if (F_status_is_fine(fll_path_canonical(arguments.array[1].string, &data_make->path_cache))) {
-            fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", data_make->path_cache.string, "touch", F_false, F_true);
-          }
-          else {
-            fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", arguments.array[1].string, "touch", F_false, F_true);
-          }
+          if (F_status_is_error(*status)) {
+            if (F_status_is_fine(fll_path_canonical(arguments.array[i].string, &data_make->path_cache))) {
+              fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", data_make->path_cache.string, "touch", F_false, F_true);
+            }
+            else {
+              fake_print_error_file(data, F_status_set_fine(*status), "f_directory_touch", arguments.array[i].string, "touch", F_false, F_true);
+            }
 
-          return;
+            return;
+          }
         }
-      }
+      } // for
 
       return;
     }
@@ -2166,42 +2223,19 @@ extern "C" {
         *status = F_status_set_error(F_failure);
       }
     }
-    else if (operation == fake_make_operation_type_create || operation == fake_make_operation_type_delete) {
+    else if (operation == fake_make_operation_type_delete || operation == fake_make_operation_type_deletes) {
       if (arguments.used) {
-        if (fl_string_dynamic_compare_string(fake_make_operation_argument_file, arguments.array[0], fake_make_operation_argument_file_length) == F_equal_to) {
-          if (arguments.used > 2) {
-            printf("%c", f_string_eol[0]);
-            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Has too many arguments.");
-
-            *status = F_status_set_error(F_failure);
-          }
-        }
-        else if (fl_string_dynamic_compare_string(fake_make_operation_argument_directory, arguments.array[0], fake_make_operation_argument_directory_length) == F_equal_to) {
-          if (arguments.used > 3) {
-            printf("%c", f_string_eol[0]);
-            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Has too many arguments.");
+        for (f_array_length i = 0; i < arguments.used; i++) {
+          *status = fake_make_assure_inside_project(data, arguments.array[i], data_make);
 
-            *status = F_status_set_error(F_failure);
-          }
-          else if (arguments.used == 3) {
-            if (fl_string_dynamic_compare_string(fake_make_operation_argument_recursive, arguments.array[0], fake_make_operation_argument_recursive_length) == F_equal_to_not) {
-              printf("%c", f_string_eol[0]);
-              fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Third argument must be either '");
-              fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", fake_make_operation_argument_recursive);
-              fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' or not provided at all.");
+          if (F_status_is_error(*status)) {
+            fake_print_error_fakefile_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string);
 
+            if (F_status_set_fine(*status) == F_false) {
               *status = F_status_set_error(F_failure);
             }
           }
-        }
-        else {
-          printf("%c", f_string_eol[0]);
-          fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Unsupported file type '");
-          fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", arguments.array[0].string);
-          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
-
-          *status = F_status_set_error(F_failure);
-        }
+        } // for
       }
       else {
         printf("%c", f_string_eol[0]);
@@ -2295,7 +2329,6 @@ extern "C" {
       }
     }
     else if (operation == fake_make_operation_type_link) {
-      // @todo validate link is outside that the link is or is not outside the project directory.
       if (arguments.used > 2) {
         printf("%c", f_string_eol[0]);
         fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Has too many arguments.");
@@ -2303,55 +2336,23 @@ extern "C" {
         *status = F_status_set_error(F_failure);
       }
       else if (arguments.used == 2) {
-        f_status status_file = F_none;
-
-        if (arguments.array[0].used) {
-          status_file = f_file_exists(arguments.array[0].string);
-
-          if (F_status_is_error(status_file) || !status_file) {
-            printf("%c", f_string_eol[0]);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to find file '");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", arguments.array[0].string);
-            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
+        *status = fake_make_assure_inside_project(data, arguments.array[0], data_make);
+        if (F_status_is_error(*status)) {
+          fake_print_error_fakefile_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[0].string);
 
-            if (status_file == F_false) {
-              *status = F_status_set_error(F_failure);
-            }
-            else {
-              *status = status_file;
-            }
+          if (F_status_set_fine(*status) == F_false) {
+            *status = F_status_set_error(F_failure);
           }
         }
-        else {
-          printf("%c", f_string_eol[0]);
-          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: The %s filename argument must not be an empty string.", fake_make_operation_argument_target);
 
-          *status = F_status_set_error(F_failure);
-        }
-
-        if (arguments.array[1].used) {
-          status_file = f_file_exists(arguments.array[1].string);
-
-          if (F_status_is_error(status_file) || !status_file) {
-            printf("%c", f_string_eol[0]);
-            fl_color_print(f_type_error, data.context.error, data.context.reset, "ERROR: Failed to find file '");
-            fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", arguments.array[1].string);
-            fl_color_print_line(f_type_error, data.context.error, data.context.reset, "'.");
+        *status = fake_make_assure_inside_project(data, arguments.array[1], data_make);
+        if (F_status_is_error(*status)) {
+          fake_print_error_fakefile_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[1].string);
 
-            if (status_file == F_false) {
-              *status = F_status_set_error(F_failure);
-            }
-            else {
-              *status = status_file;
-            }
+          if (F_status_set_fine(*status) == F_false) {
+            *status = F_status_set_error(F_failure);
           }
         }
-        else {
-          printf("%c", f_string_eol[0]);
-          fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Filename argument must not be an empty string.", fake_make_operation_argument_point);
-
-          *status = F_status_set_error(F_failure);
-        }
       }
       else {
         printf("%c", f_string_eol[0]);
@@ -2410,13 +2411,7 @@ extern "C" {
       }
     }
     else if (operation == fake_make_operation_type_touch) {
-      if (arguments.used > 2) {
-        printf("%c", f_string_eol[0]);
-        fl_color_print_line(f_type_error, data.context.error, data.context.reset, "ERROR: Has too many arguments.");
-
-        *status = F_status_set_error(F_failure);
-      }
-      else if (arguments.used == 2) {
+      if (arguments.used > 1) {
         if (fl_string_dynamic_compare_string(fake_make_operation_argument_file, arguments.array[0], fake_make_operation_argument_file_length) == F_equal_to_not) {
           if (fl_string_dynamic_compare_string(fake_make_operation_argument_directory, arguments.array[0], fake_make_operation_argument_directory_length) == F_equal_to_not) {
             printf("%c", f_string_eol[0]);
@@ -2428,14 +2423,16 @@ extern "C" {
           }
         }
 
-        *status = fake_make_assure_inside_project(data, arguments.array[1], data_make);
-        if (F_status_is_error(*status)) {
-          fake_print_error_fakefile_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[1].string);
+        for (f_array_length i = 1; i < arguments.used; i++) {
+          *status = fake_make_assure_inside_project(data, arguments.array[i], data_make);
+          if (F_status_is_error(*status)) {
+            fake_print_error_fakefile_section_operation_path_outside(data, F_status_set_fine(*status), "fake_make_assure_inside_project", data_make->path_cache.used ? data_make->path_cache.string : arguments.array[i].string);
 
-          if (F_status_set_fine(*status) == F_false) {
-            *status = F_status_set_error(F_failure);
+            if (F_status_set_fine(*status) == F_false) {
+              *status = F_status_set_error(F_failure);
+            }
           }
-        }
+        } // for
       }
       else {
         printf("%c", f_string_eol[0]);
index 495f7347016045e30c175029f9586a78414c1c83..a56ecdfde37889fe5eada3f291936bee15dcce8b 100644 (file)
@@ -22,7 +22,6 @@ extern "C" {
   #define fake_make_section_stack_max 8192 // maximum stack call depth.
 #endif // _di_fake_make_section_
 
-// @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;
@@ -64,9 +63,9 @@ extern "C" {
   #define fake_make_operation_build    "build"
   #define fake_make_operation_clean    "clean"
   #define fake_make_operation_compile  "compile"
-  #define fake_make_operation_create   "create"
   #define fake_make_operation_define   "define"
   #define fake_make_operation_delete   "delete"
+  #define fake_make_operation_deletes  "deletes"
   #define fake_make_operation_else     "else"
   #define fake_make_operation_fail     "fail"
   #define fake_make_operation_group    "group"
@@ -91,9 +90,9 @@ extern "C" {
   #define fake_make_operation_build_length    5
   #define fake_make_operation_clean_length    5
   #define fake_make_operation_compile_length  7
-  #define fake_make_operation_create_length   6
   #define fake_make_operation_define_length   6
   #define fake_make_operation_delete_length   6
+  #define fake_make_operation_deletes_length  7
   #define fake_make_operation_else_length     4
   #define fake_make_operation_fail_length     4
   #define fake_make_operation_group_length    5
@@ -119,9 +118,9 @@ extern "C" {
     fake_make_operation_type_build,
     fake_make_operation_type_clean,
     fake_make_operation_type_compile,
-    fake_make_operation_type_create,
     fake_make_operation_type_define,
     fake_make_operation_type_delete,
+    fake_make_operation_type_deletes,
     fake_make_operation_type_else,
     fake_make_operation_type_fail,
     fake_make_operation_type_group,
index 0a420face40b4ab6c5968d85b81d0c3d3afa2127..8cca889af5650404e00400b2544a727c28f8cc17 100644 (file)
@@ -463,6 +463,17 @@ extern "C" {
       return F_false;
     }
 
+    if (status == F_directory_empty_not) {
+      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 %s '", file_or_directory);
+        fl_color_print(f_type_error, data.context.notable, data.context.reset, "%s", name);
+        fl_color_print_line(f_type_error, data.context.error, data.context.reset, "' is not empty.");
+      }
+
+      return F_false;
+    }
+
     if (status == F_parameter) {
       if (data.verbosity != fake_verbosity_quiet) {
         fprintf(f_type_error, "%c", f_string_eol[0]);
index 3ba3dd5586448255ba48ab3d04ffe0a72e18facb..2837b4d00b243e5f24bf04e78f91bef1196e33c4 100644 (file)
@@ -75,36 +75,20 @@ Fakefile Documentation:
 
       All Content are passed as arguments to the respective "gcc" program.
 
-    - create\:
-      Create a file or directory.
-
-      The first Content must be either "file" or "directory".
-      Use "file" to designate that this is a regular file being created.
-      Use "directory" to designate that this is a directory file being created.
-
-      The second Content must be the file to be created (be it a regular "file" or a "directory" file).
-
-    - creates\:
-      Identical to "create", except that this will create all directories specified in the given directory file path.
-
     - define\:
       This represents an environment variable to define on run.
       The environment variable name is case-sensitive.
       This replaces the value of any existing environment variable with this name.
 
     - delete\:
-      Delete a file or directory.
-
-      The first Content must be either "file" or "directory".
-      Use "file" to designate that this is a regular file being deleted.
-      The "directory" to designate that this is a directory file being deleted.
+      Delete one or more files or directories.
 
-      The second Content must be the file to be deleted.
+      All Content must be the file or directory to be deleted.
 
-      When the first content is "directory" and that directory is not empty, then this will not delete the directory.
+      If the path is a directory and is not empty, then this will not delete the directory.
 
     - deletes\:
-      Identical to "delete", except that when the first content is "directory" and that directory is not empty, then this will delete the directory.
+      Identical to "delete", except that when the path is a directory and is not empty, then this will delete the directory.
 
     - else\:
       Performs a programmatic "else" condition.
@@ -226,4 +210,4 @@ Fakefile Documentation:
       Manually create a new file or a directory within the project root or update its last changed timestamp if the file already exists.
 
       The first Content must be either "file" or "directory".
-      The second Content must be the file name.
+      The remaining Content must be a path to the file.
index 328306f3a086731b6b9d26b8e3190e47767cf9b8..7221d476d8c47bc15afaf8e5b602c321aac42fb8 100644 (file)
@@ -47,8 +47,6 @@ Fakefile Specification:
   - build: Zero or One Content. First Content represents path to the settings file, relative to the project root.
   - clean: Zero Content.
   - compile: One or more Content as parameters to compiler.
-  - create: Two Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file.
-  - creates: Two Content. First Content is either "file" or "directory" (case-sensitive), second Content is path to file.
   - define: Two or more Content.
   - delete: One or more Content representing paths to files.
   - deletes: One or more Content representing paths to files.
@@ -70,4 +68,4 @@ Fakefile Specification:
   - skeleton: Zero Content.
   - to: One Content. First Content is the directory path.
   - top: Zero Content.
-  - touch: One Content. First Content is the file path.
+  - touch: Two or more Content. First content is one of "file" or "directory", remaining Content are paths to files.