glcpp: Make standalone preprocessor work with a tty as stdin
authorCarl Worth <cworth@cworth.org>
Mon, 23 Aug 2010 17:43:27 +0000 (10:43 -0700)
committerCarl Worth <cworth@cworth.org>
Mon, 23 Aug 2010 17:48:10 +0000 (10:48 -0700)
Previously glcpp would silently abort if it couldn't fstat the file being
read, (so it would work with stdin redirected from a file, but would not
work with stdin as a tty). The stat was so that glcpp could allocate
a buffer for the file content in a single call.

We now use talloc_realloc instead, (even if the fstat is
possible). This is theoretically less efficient, but quite irrelevant,
(particularly because the standalone preprocessor is used only for
testing).

src/glsl/glcpp/glcpp.c

index 011058a36acc7e7224853fd622a41dca8e100a56..56714936bbce059ea662d359a0ea62b0dc782a67 100644 (file)
 
 extern int yydebug;
 
+/* Read from fd until EOF and return a string of everything read.
+ */
 static char *
-load_text_file(void *ctx, const char *file_name)
+load_text_fd (void *ctx, int fd)
 {
+#define CHUNK 4096
        char *text = NULL;
-       struct stat st;
+       ssize_t text_size = 0;
        ssize_t total_read = 0;
-       int fd;
+       ssize_t bytes;
+
+       while (1) {
+               if (total_read + CHUNK + 1 > text_size) {
+                       text_size = text_size ? text_size * 2 : CHUNK + 1;
+                       text = talloc_realloc_size (ctx, text, text_size);
+                       if (text == NULL) {
+                               fprintf (stderr, "Out of memory\n");
+                               return NULL;
+                       }
+               }
+               bytes = read (fd, text + total_read, CHUNK);
+               if (bytes < 0) {
+                       fprintf (stderr, "Error while reading: %s\n",
+                                strerror (errno));
+                       talloc_free (text);
+                       return NULL;
+               }
 
-       if (file_name == NULL || strcmp(file_name, "-") == 0) {
-          fd = STDIN_FILENO;
-       } else {
-          fd = open (file_name, O_RDONLY);
+               if (bytes == 0) {
+                       break;
+               }
 
-          if (fd < 0) {
-             fprintf (stderr, "Failed to open file %s: %s\n",
-                      file_name, strerror (errno));
-             return NULL;
-          }
+               total_read += bytes;
        }
 
-       if (fstat(fd, & st) == 0) {
-               text = (char *) talloc_size(ctx, st.st_size + 1);
-               if (text != NULL) {
-                       do {
-                               ssize_t bytes = read(fd, text + total_read,
-                                                    st.st_size - total_read);
-                               if (bytes < 0) {
-                                       text = NULL;
-                                       break;
-                               }
-
-                               if (bytes == 0) {
-                                       break;
-                               }
-
-                               total_read += bytes;
-                       } while (total_read < st.st_size);
-
-                       text[total_read] = '\0';
-               }
+       text[total_read] = '\0';
+
+       return text;
+}
+
+static char *
+load_text_file(void *ctx, const char *filename)
+{
+       char *text;
+       int fd;
+
+       if (filename == NULL || strcmp (filename, "-") == 0)
+               return load_text_fd (ctx, STDIN_FILENO);
+
+       fd = open (filename, O_RDONLY);
+       if (fd < 0) {
+               fprintf (stderr, "Failed to open file %s: %s\n",
+                        filename, strerror (errno));
+               return NULL;
        }
 
+       text = load_text_fd (ctx, fd);
+
        close(fd);
 
        return text;
@@ -91,7 +107,7 @@ main (int argc, char *argv[])
                filename = argv[1];
        }
 
-       shader = load_text_file(ctx, filename);
+       shader = load_text_file (ctx, filename);
        if (shader == NULL)
           return 1;