glsl/pp: Have sl_pp_purify() return error msg/line no.
authorMichal Krol <michal@vmware.com>
Mon, 9 Nov 2009 23:15:33 +0000 (00:15 +0100)
committerMichal Krol <michal@vmware.com>
Mon, 9 Nov 2009 23:15:33 +0000 (00:15 +0100)
src/glsl/pp/sl_pp_purify.c
src/glsl/pp/sl_pp_purify.h

index 3fb91430f3714cdab303b86f2622bc016608392c..272da1e6ea96c5385c411bba3adb46a1c2fd855f 100644 (file)
@@ -26,6 +26,8 @@
  **************************************************************************/
 
 #include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
 #include "sl_pp_purify.h"
 
 
 
 static unsigned int
 _purify_newline(const char *input,
-                char *out)
+                char *out,
+                unsigned int *current_line)
 {
    if (input[0] == '\n') {
       *out = '\n';
+      (*current_line)++;
       if (input[1] == '\r') {
          /*
           * The GLSL spec is not explicit about whether this
@@ -55,6 +59,7 @@ _purify_newline(const char *input,
    }
    if (input[0] == '\r') {
       *out = '\n';
+      (*current_line)++;
       if (input[1] == '\n') {
          return 2;
       }
@@ -67,7 +72,8 @@ _purify_newline(const char *input,
 
 static unsigned int
 _purify_backslash(const char *input,
-                  char *out)
+                  char *out,
+                  unsigned int *current_line)
 {
    unsigned int eaten = 0;
 
@@ -75,11 +81,12 @@ _purify_backslash(const char *input,
       if (input[0] == '\\') {
          char next;
          unsigned int next_eaten;
+         unsigned int next_line = *current_line;
 
          eaten++;
          input++;
 
-         next_eaten = _purify_newline(input, &next);
+         next_eaten = _purify_newline(input, &next, &next_line);
          if (next == '\n') {
             /*
              * If this is really a line continuation sequence, eat
@@ -87,6 +94,7 @@ _purify_backslash(const char *input,
              */
             eaten += next_eaten;
             input += next_eaten;
+            *current_line = next_line;
          } else {
             /*
              * It is an error to put anything between a backslash
@@ -98,7 +106,7 @@ _purify_backslash(const char *input,
             break;
          }
       } else {
-         eaten += _purify_newline(input, out);
+         eaten += _purify_newline(input, out, current_line);
          break;
       }
    }
@@ -110,9 +118,25 @@ struct out_buf {
    char *out;
    unsigned int len;
    unsigned int capacity;
+   unsigned int current_line;
+   char *errormsg;
+   unsigned int cberrormsg;
 };
 
 
+static void
+_report_error(struct out_buf *obuf,
+              const char *msg,
+              ...)
+{
+   va_list args;
+
+   va_start(args, msg);
+   vsnprintf(obuf->errormsg, obuf->cberrormsg, msg, args);
+   va_end(args);
+}
+
+
 static int
 _out_buf_putc(struct out_buf *obuf,
               char c)
@@ -130,6 +154,7 @@ _out_buf_putc(struct out_buf *obuf,
 
       obuf->out = realloc(obuf->out, new_max);
       if (!obuf->out) {
+         _report_error(obuf, "out of memory");
          return -1;
       }
       obuf->capacity = new_max;
@@ -148,20 +173,22 @@ _purify_comment(const char *input,
    unsigned int eaten;
    char curr;
 
-   eaten = _purify_backslash(input, &curr);
+   eaten = _purify_backslash(input, &curr, &obuf->current_line);
    input += eaten;
    if (curr == '/') {
       char next;
       unsigned int next_eaten;
+      unsigned int next_line = obuf->current_line;
 
-      next_eaten = _purify_backslash(input, &next);
+      next_eaten = _purify_backslash(input, &next, &next_line);
       if (next == '/') {
          eaten += next_eaten;
          input += next_eaten;
+         obuf->current_line = next_line;
 
          /* Replace a line comment with either a newline or nil. */
          for (;;) {
-            next_eaten = _purify_backslash(input, &next);
+            next_eaten = _purify_backslash(input, &next, &obuf->current_line);
             eaten += next_eaten;
             input += next_eaten;
             if (next == '\n' || next == '\0') {
@@ -174,14 +201,15 @@ _purify_comment(const char *input,
       } else if (next == '*') {
          eaten += next_eaten;
          input += next_eaten;
+         obuf->current_line = next_line;
 
          /* Replace a block comment with a whitespace. */
          for (;;) {
-            next_eaten = _purify_backslash(input, &next);
+            next_eaten = _purify_backslash(input, &next, &obuf->current_line);
             eaten += next_eaten;
             input += next_eaten;
             while (next == '*') {
-               next_eaten = _purify_backslash(input, &next);
+               next_eaten = _purify_backslash(input, &next, &obuf->current_line);
                eaten += next_eaten;
                input += next_eaten;
                if (next == '/') {
@@ -197,6 +225,7 @@ _purify_comment(const char *input,
                }
             }
             if (next == '\0') {
+               _report_error(obuf, "expected `*/' but end of translation unit found");
                return 0;
             }
          }
@@ -212,19 +241,26 @@ _purify_comment(const char *input,
 int
 sl_pp_purify(const char *input,
              const struct sl_pp_purify_options *options,
-             char **output)
+             char **output,
+             char *errormsg,
+             unsigned int cberrormsg,
+             unsigned int *errorline)
 {
    struct out_buf obuf;
 
    obuf.out = NULL;
    obuf.len = 0;
    obuf.capacity = 0;
+   obuf.current_line = 1;
+   obuf.errormsg = errormsg;
+   obuf.cberrormsg = cberrormsg;
 
    for (;;) {
       unsigned int eaten;
 
       eaten = _purify_comment(input, &obuf);
       if (!eaten) {
+         *errorline = obuf.current_line;
          return -1;
       }
       input += eaten;
index 011b117937eb9e567e4d686062c2d98fcd0777bf..88ea9c9e7a754dd8b7f0b555ff6a9cd20504e3d1 100644 (file)
@@ -36,6 +36,9 @@ struct sl_pp_purify_options {
 int
 sl_pp_purify(const char *input,
              const struct sl_pp_purify_options *options,
-             char **output);
+             char **output,
+             char *errormsg,
+             unsigned int cberrormsg,
+             unsigned int *errorline);
 
 #endif /* SL_PP_PURIFY_H */