[m-rev.] diff: add -f option to mkinit to avoid command line overflows

Peter Ross pro at missioncriticalit.com
Fri Jun 15 10:34:23 AEST 2007


Hi,


===================================================================


Estimated hours taken: 4
Branches: main

Windows has a limit on the command line length.  Allow mkinit
to be passed a list of files to be processed in a file via
-f to avoid this limit.

compiler/compile_target_code.m:
	Use the -f option to avoid overflowing the windows
	command line.

util/mkinit.c:
	Add code to handle the -f option.


Index: compiler/compile_target_code.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/compile_target_code.m,v
retrieving revision 1.111
diff -u -r1.111 compile_target_code.m
--- compiler/compile_target_code.m	14 Jun 2007 00:18:26 -0000	1.111
+++ compiler/compile_target_code.m	14 Jun 2007 07:22:39 -0000
@@ -995,12 +995,33 @@
         InitFileRes = ok(InitFileStream),
         list.map_foldl(module_name_to_file_name_ext(TargetExt, no),
             AllModules, AllTargetFilesList, !IO),
-        join_quoted_string_list(AllTargetFilesList, "", "", " ",
+        join_quoted_string_list(AllTargetFilesList, "", "\n", "",
             TargetFileNames),
         
-        MkInitCmd = string.append_list([MkInit, " -k ", TargetFileNames]),
-        invoke_system_command(InitFileStream, cmd_verbose, MkInitCmd, MkInitOK,
-            !IO),
+        io.make_temp(TmpFile, !IO),
+        io.open_output(TmpFile, OpenResult, !IO),
+        (
+            OpenResult = ok(TmpStream),
+            io.write_string(TmpStream, TargetFileNames, !IO),
+            io.close_output(TmpStream, !IO),
+
+            MkInitCmd = string.append_list([MkInit, " -k -f ", TmpFile]),
+            invoke_system_command(InitFileStream, cmd_verbose,
+                MkInitCmd, MkInitOK0, !IO),
+
+            io.remove_file(TmpFile, RemoveResult, !IO),
+            (
+                RemoveResult = ok,
+                MkInitOK = MkInitOK0
+            ;
+                RemoveResult = error(_),
+                MkInitOK = no
+            )
+        ;
+            OpenResult = error(_),
+            MkInitOK = no
+        ),
+
        
         ( 
             MkInitOK =  yes,
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.116
diff -u -r1.116 mkinit.c
--- util/mkinit.c	8 Jun 2007 00:47:15 -0000	1.116
+++ util/mkinit.c	14 Jun 2007 07:22:40 -0000
@@ -59,7 +59,11 @@
 #endif
 
 /* --- adjustable limits --- */
-#define MAXCALLS    40  /* maximum number of calls per function */
+#define MAXCALLS    40      /* maximum number of calls per function */
+
+#define MAXFILENAME 4096    /* maximimum file name length           */
+#define NUMFILES    128     /* intial size of files array           */
+#define FACTOR      2       /* factor to increase files array by    */
 
 /* --- used to collect a list of strings --- */
 
@@ -277,7 +281,8 @@
 static const char   *grade = "";
 static int          maxcalls = MAXCALLS;
 static int          num_files;
-static char         **files;
+static int          size_of_files;
+static char         **files = NULL;
 static MR_bool      output_main_func = MR_TRUE;
 static MR_bool      need_initialization_code = MR_FALSE;
 static MR_bool      need_tracing = MR_FALSE;
@@ -528,6 +533,7 @@
 
 /* --- function prototypes --- */
 static  void    parse_options(int argc, char *argv[]);
+static  void    process_file_list_file(char *filename);
 static  void    usage(void);
 static  void    output_complexity_proc(const char *procname);
 static  void    output_complexity_experiment_table(const char *filename);
@@ -721,12 +727,13 @@
     int         c;
     int         i;
     String_List *tmp_slist;
+    int         seen_f_option = 0;
 
     /*
     ** The set of options for mkinit and mkinit_erl should be
     ** kept in sync, even if they may not necessarily make sense.
     */
-    while ((c = getopt(argc, argv, "A:c:g:iI:lm:o:r:tw:xX:ks")) != EOF) {
+    while ((c = getopt(argc, argv, "A:c:f:g:iI:lm:o:r:tw:xX:ks")) != EOF) {
         switch (c) {
         case 'A':
             /*
@@ -751,6 +758,11 @@
 
             break;
 
+        case 'f':
+            process_file_list_file(optarg);
+            seen_f_option = 1;
+            break;
+
         case 'g':
             grade = optarg;
             break;
@@ -825,12 +837,66 @@
         }
     }
 
-    num_files = argc - optind;
+    if (seen_f_option) {
+        /* 
+        ** -f could be made compatible if we copied the filenames
+        ** from argv into files.
+        ** 
+        */
+        if ((argc - optind) > 0) {
+            fprintf(stderr,
+                "%s: -f incompatible with filenames on the command line\n",
+                MR_progname);
+            exit(EXIT_FAILURE);
+        }
+    } else {
+        num_files = argc - optind;
+        files = argv + optind;
+    }
+
     if (num_files <= 0) {
         usage();
     }
+}
+
+static void
+process_file_list_file(char *filename)
+{
+    FILE *fp;
+    char *line;
 
-    files = argv + optind;
+    fp = fopen(filename, "r");
+    if (fp == NULL) {
+        fprintf(stderr, "%s: error opening file `%s': %s\n",
+            MR_progname, filename, strerror(errno));
+        num_errors++;
+        return;
+    } 
+        /* intialize the files structure, if required */
+    if (files == NULL) {
+        num_files = 0;
+        size_of_files = NUMFILES;
+        files = (char **) checked_malloc(sizeof(char *) * NUMFILES);
+    }
+
+    while ((line = read_line(filename, fp, MAXFILENAME)) != NULL) {
+            /* Ignore blank lines */
+        if (line[0] != '\0') {
+            if (num_files >= size_of_files) {
+                size_of_files *= FACTOR;
+                files = (char **)
+                    realloc(files, size_of_files * sizeof(char *));
+
+                if (files == NULL) {
+                    fprintf(stderr, "%s: unable to realloc\n", MR_progname);
+                    exit(EXIT_FAILURE);
+                }
+            }
+
+            files[num_files] = line;
+            num_files++;
+        }
+    }
 }
 
 static void
@@ -839,6 +905,7 @@
     fputs("Usage: mkinit [options] files...\n", stderr);
     fputs("Options:\n", stderr);
     fputs("  -c maxcalls:\tset the max size of an init function\n", stderr);
+    fputs("  -f filename:\tprocess the files one per line in filename\n", stderr);
     fputs("  -g grade:\tset the grade of the executable\n", stderr);
     fputs("  -i:\t\tenable initialization code\n", stderr);
     fputs("  -l:\t\tdo not output main function\n", stderr);

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list