glsl/pp: Add sl_pp_purify_getc().
authorMichal Krol <michal@vmware.com>
Tue, 10 Nov 2009 19:49:45 +0000 (20:49 +0100)
committerMichal Krol <michal@vmware.com>
Tue, 10 Nov 2009 19:49:45 +0000 (20:49 +0100)
src/glsl/pp/sl_pp_purify.c
src/glsl/pp/sl_pp_purify.h

index 272da1e6ea96c5385c411bba3adb46a1c2fd855f..b50f8192517c9784f711632876ac79914cec6b9b 100644 (file)
@@ -114,130 +114,150 @@ _purify_backslash(const char *input,
 }
 
 
-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,
+_report_error(char *buf,
+              unsigned int cbbuf,
               const char *msg,
               ...)
 {
    va_list args;
 
    va_start(args, msg);
-   vsnprintf(obuf->errormsg, obuf->cberrormsg, msg, args);
+   vsnprintf(buf, cbbuf, msg, args);
    va_end(args);
 }
 
 
-static int
-_out_buf_putc(struct out_buf *obuf,
-              char c)
+void
+sl_pp_purify_state_init(struct sl_pp_purify_state *state,
+                        const char *input,
+                        const struct sl_pp_purify_options *options)
 {
-   if (obuf->len >= obuf->capacity) {
-      unsigned int new_max = obuf->capacity;
+   state->options = *options;
+   state->input = input;
+   state->current_line = 1;
+   state->inside_c_comment = 0;
+}
 
-      if (new_max < 0x100) {
-         new_max = 0x100;
-      } else if (new_max < 0x10000) {
-         new_max *= 2;
-      } else {
-         new_max += 0x10000;
-      }
 
-      obuf->out = realloc(obuf->out, new_max);
-      if (!obuf->out) {
-         _report_error(obuf, "out of memory");
-         return -1;
+unsigned int
+_purify_comment(struct sl_pp_purify_state *state,
+                char *output,
+                unsigned int *current_line,
+                char *errormsg,
+                unsigned int cberrormsg)
+{
+   for (;;) {
+      unsigned int eaten;
+      char next;
+
+      eaten = _purify_backslash(state->input, &next, current_line);
+      state->input += eaten;
+      while (next == '*') {
+         eaten = _purify_backslash(state->input, &next, current_line);
+         state->input += eaten;
+         if (next == '/') {
+            *output = ' ';
+            state->inside_c_comment = 0;
+            return 1;
+         }
+      }
+      if (next == '\n') {
+         *output = '\n';
+         state->inside_c_comment = 1;
+         return 1;
+      }
+      if (next == '\0') {
+         _report_error(errormsg, cberrormsg, "expected `*/' but end of translation unit found");
+         return 0;
       }
-      obuf->capacity = new_max;
    }
-
-   obuf->out[obuf->len++] = c;
-
-   return 0;
 }
 
 
-static unsigned int
-_purify_comment(const char *input,
-                struct out_buf *obuf)
+unsigned int
+sl_pp_purify_getc(struct sl_pp_purify_state *state,
+                  char *output,
+                  unsigned int *current_line,
+                  char *errormsg,
+                  unsigned int cberrormsg)
 {
    unsigned int eaten;
-   char curr;
 
-   eaten = _purify_backslash(input, &curr, &obuf->current_line);
-   input += eaten;
-   if (curr == '/') {
+   if (state->inside_c_comment) {
+      return _purify_comment(state, output, current_line, errormsg, cberrormsg);
+   }
+
+   eaten = _purify_backslash(state->input, output, current_line);
+   state->input += eaten;
+   if (*output == '/') {
       char next;
-      unsigned int next_eaten;
-      unsigned int next_line = obuf->current_line;
+      unsigned int next_line = *current_line;
 
-      next_eaten = _purify_backslash(input, &next, &next_line);
+      eaten = _purify_backslash(state->input, &next, &next_line);
       if (next == '/') {
-         eaten += next_eaten;
-         input += next_eaten;
-         obuf->current_line = next_line;
+         state->input += eaten;
+         *current_line = next_line;
 
          /* Replace a line comment with either a newline or nil. */
          for (;;) {
-            next_eaten = _purify_backslash(input, &next, &obuf->current_line);
-            eaten += next_eaten;
-            input += next_eaten;
+            eaten = _purify_backslash(state->input, &next, current_line);
+            state->input += eaten;
             if (next == '\n' || next == '\0') {
-               if (_out_buf_putc(obuf, next)) {
-                  return 0;
-               }
+               *output = next;
                return eaten;
             }
          }
       } else if (next == '*') {
-         eaten += next_eaten;
-         input += next_eaten;
-         obuf->current_line = next_line;
+         state->input += eaten;
+         *current_line = next_line;
 
-         /* Replace a block comment with a whitespace. */
-         for (;;) {
-            next_eaten = _purify_backslash(input, &next, &obuf->current_line);
-            eaten += next_eaten;
-            input += next_eaten;
-            while (next == '*') {
-               next_eaten = _purify_backslash(input, &next, &obuf->current_line);
-               eaten += next_eaten;
-               input += next_eaten;
-               if (next == '/') {
-                  if (_out_buf_putc(obuf, ' ')) {
-                     return 0;
-                  }
-                  return eaten;
-               }
-            }
-            if (next == '\n') {
-               if (_out_buf_putc(obuf, '\n')) {
-                  return 0;
-               }
-            }
-            if (next == '\0') {
-               _report_error(obuf, "expected `*/' but end of translation unit found");
-               return 0;
-            }
-         }
+         return _purify_comment(state, output, current_line, errormsg, cberrormsg);
       }
    }
-   if (_out_buf_putc(obuf, curr)) {
-      return 0;
-   }
    return eaten;
 }
 
 
+struct out_buf {
+   char *out;
+   unsigned int len;
+   unsigned int capacity;
+   unsigned int current_line;
+   char *errormsg;
+   unsigned int cberrormsg;
+};
+
+
+static int
+_out_buf_putc(struct out_buf *obuf,
+              char c)
+{
+   if (obuf->len >= obuf->capacity) {
+      unsigned int new_max = obuf->capacity;
+
+      if (new_max < 0x100) {
+         new_max = 0x100;
+      } else if (new_max < 0x10000) {
+         new_max *= 2;
+      } else {
+         new_max += 0x10000;
+      }
+
+      obuf->out = realloc(obuf->out, new_max);
+      if (!obuf->out) {
+         _report_error(obuf->errormsg, obuf->cberrormsg, "out of memory");
+         return -1;
+      }
+      obuf->capacity = new_max;
+   }
+
+   obuf->out[obuf->len++] = c;
+
+   return 0;
+}
+
+
 int
 sl_pp_purify(const char *input,
              const struct sl_pp_purify_options *options,
@@ -247,6 +267,7 @@ sl_pp_purify(const char *input,
              unsigned int *errorline)
 {
    struct out_buf obuf;
+   struct sl_pp_purify_state state;
 
    obuf.out = NULL;
    obuf.len = 0;
@@ -255,17 +276,23 @@ sl_pp_purify(const char *input,
    obuf.errormsg = errormsg;
    obuf.cberrormsg = cberrormsg;
 
+   sl_pp_purify_state_init(&state, input, options);
+
    for (;;) {
       unsigned int eaten;
+      char c;
 
-      eaten = _purify_comment(input, &obuf);
+      eaten = sl_pp_purify_getc(&state, &c, &obuf.current_line, errormsg, cberrormsg);
       if (!eaten) {
          *errorline = obuf.current_line;
          return -1;
       }
-      input += eaten;
+      if (_out_buf_putc(&obuf, c)) {
+         *errorline = obuf.current_line;
+         return -1;
+      }
 
-      if (obuf.out[obuf.len - 1] == '\0') {
+      if (c == '\0') {
          break;
       }
    }
index 88ea9c9e7a754dd8b7f0b555ff6a9cd20504e3d1..c0f55cbfd89d34f789b95adef525ebbf3e6e5e15 100644 (file)
@@ -41,4 +41,23 @@ sl_pp_purify(const char *input,
              unsigned int cberrormsg,
              unsigned int *errorline);
 
+struct sl_pp_purify_state {
+   struct sl_pp_purify_options options;
+   const char *input;
+   unsigned int current_line;
+   unsigned int inside_c_comment:1;
+};
+
+void
+sl_pp_purify_state_init(struct sl_pp_purify_state *state,
+                        const char *input,
+                        const struct sl_pp_purify_options *options);
+
+unsigned int
+sl_pp_purify_getc(struct sl_pp_purify_state *state,
+                  char *output,
+                  unsigned int *current_line,
+                  char *errormsg,
+                  unsigned int cberrormsg);
+
 #endif /* SL_PP_PURIFY_H */