d: Use read() to load contents of stdin into memory.
authorIain Buclaw <ibuclaw@gdcproject.org>
Tue, 25 Aug 2020 09:23:24 +0000 (11:23 +0200)
committerIain Buclaw <ibuclaw@gdcproject.org>
Wed, 26 Aug 2020 08:03:55 +0000 (10:03 +0200)
This would be an improvement over reading one character at a time.

An ICE was discovered when mixing reading from stdin with `-v', this has been
fixed in upstream DMD and backported as well.

Reviewed-on: https://github.com/dlang/dmd/pull/11620

gcc/d/ChangeLog:

* d-lang.cc (d_parse_file): Use read() to load contents from stdin,
allow the front-end to free the memory after parsing.
* dmd/MERGE: Merge upstream dmd 2cc25c219.

gcc/d/d-lang.cc
gcc/d/dmd/MERGE
gcc/d/dmd/func.c

index 6183389007ad0f20d69b96e39c899783564f69bd..c5254a02446d1d8d9d13d70c1753c88d44574c71 100644 (file)
@@ -906,32 +906,43 @@ d_parse_file (void)
     {
       if (strcmp (in_fnames[i], "-") == 0)
        {
-         /* Handling stdin, generate a unique name for the module.  */
-         obstack buffer;
-         gcc_obstack_init (&buffer);
-         int c;
+         /* Load the entire contents of stdin into memory.  8 kilobytes should
+            be a good enough initial size, but double on each iteration.
+            16 bytes are added for the final '\n' and 15 bytes of padding.  */
+         ssize_t size = 8 * 1024;
+         uchar *buffer = XNEWVEC (uchar, size + 16);
+         ssize_t len = 0;
+         ssize_t count;
+
+         while ((count = read (STDIN_FILENO, buffer + len, size - len)) > 0)
+           {
+             len += count;
+             if (len == size)
+               {
+                 size *= 2;
+                 buffer = XRESIZEVEC (uchar, buffer, size + 16);
+               }
+           }
 
+         if (count < 0)
+           {
+             error (Loc ("stdin", 0, 0), "%s", xstrerror (errno));
+             free (buffer);
+             continue;
+           }
+
+         /* Handling stdin, generate a unique name for the module.  */
          Module *m = Module::create (in_fnames[i],
                                      Identifier::generateId ("__stdin"),
                                      global.params.doDocComments,
                                      global.params.doHdrGeneration);
          modules.push (m);
 
-         /* Load the entire contents of stdin into memory.  */
-         while ((c = getc (stdin)) != EOF)
-           obstack_1grow (&buffer, c);
-
-         if (!obstack_object_size (&buffer))
-           obstack_1grow (&buffer, '\0');
-
          /* Overwrite the source file for the module, the one created by
             Module::create would have a forced a `.d' suffix.  */
          m->srcfile = File::create ("<stdin>");
-         m->srcfile->len = obstack_object_size (&buffer);
-         m->srcfile->buffer = (unsigned char *) obstack_finish (&buffer);
-
-         /* Tell the front-end not to free the buffer after parsing.  */
-         m->srcfile->ref = 1;
+         m->srcfile->len = len;
+         m->srcfile->buffer = buffer;
        }
       else
        {
index d0e5f4422476d99971b9cef8a05080dbdb6585f0..8445bfaf343365f1e32da5db28d873d9e72f1927 100644 (file)
@@ -1,4 +1,4 @@
-1b5a53d01c465109ce47edf49ace6143b69b118b
+2cc25c2191928f865e1b711f30b6a4268d6a0d9a
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index b6849559bf6c7b230463e6c3d4962eadf899464e..30ba8dd93be95c3c0c05d29256cc823aa9285ea1 100644 (file)
@@ -1212,8 +1212,9 @@ Ldone:
         if (type && mod)
         {
             printedMain = true;
-            const char *name = FileName::searchPath(global.path, mod->srcfile->toChars(), true);
-            message("entry     %-10s\t%s", type, name);
+            const char *name = mod->srcfile->toChars();
+            const char *path = FileName::searchPath(global.path, name, true);
+            message("entry     %-10s\t%s", type, path ? path : name);
         }
     }