glsl/pp: Add sl_pp_purify_getc().

This commit is contained in:
Michal Krol
2009-11-10 20:49:45 +01:00
parent 4703d7d3f8
commit d44cebd1ee
2 changed files with 135 additions and 89 deletions

View File

@@ -114,6 +114,111 @@ _purify_backslash(const char *input,
} }
static void
_report_error(char *buf,
unsigned int cbbuf,
const char *msg,
...)
{
va_list args;
va_start(args, msg);
vsnprintf(buf, cbbuf, msg, args);
va_end(args);
}
void
sl_pp_purify_state_init(struct sl_pp_purify_state *state,
const char *input,
const struct sl_pp_purify_options *options)
{
state->options = *options;
state->input = input;
state->current_line = 1;
state->inside_c_comment = 0;
}
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;
}
}
}
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;
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_line = *current_line;
eaten = _purify_backslash(state->input, &next, &next_line);
if (next == '/') {
state->input += eaten;
*current_line = next_line;
/* Replace a line comment with either a newline or nil. */
for (;;) {
eaten = _purify_backslash(state->input, &next, current_line);
state->input += eaten;
if (next == '\n' || next == '\0') {
*output = next;
return eaten;
}
}
} else if (next == '*') {
state->input += eaten;
*current_line = next_line;
return _purify_comment(state, output, current_line, errormsg, cberrormsg);
}
}
return eaten;
}
struct out_buf { struct out_buf {
char *out; char *out;
unsigned int len; unsigned int len;
@@ -124,19 +229,6 @@ struct out_buf {
}; };
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 static int
_out_buf_putc(struct out_buf *obuf, _out_buf_putc(struct out_buf *obuf,
char c) char c)
@@ -154,7 +246,7 @@ _out_buf_putc(struct out_buf *obuf,
obuf->out = realloc(obuf->out, new_max); obuf->out = realloc(obuf->out, new_max);
if (!obuf->out) { if (!obuf->out) {
_report_error(obuf, "out of memory"); _report_error(obuf->errormsg, obuf->cberrormsg, "out of memory");
return -1; return -1;
} }
obuf->capacity = new_max; obuf->capacity = new_max;
@@ -166,78 +258,6 @@ _out_buf_putc(struct out_buf *obuf,
} }
static unsigned int
_purify_comment(const char *input,
struct out_buf *obuf)
{
unsigned int eaten;
char 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_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, &obuf->current_line);
eaten += next_eaten;
input += next_eaten;
if (next == '\n' || next == '\0') {
if (_out_buf_putc(obuf, next)) {
return 0;
}
return eaten;
}
}
} 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, &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;
}
}
}
}
if (_out_buf_putc(obuf, curr)) {
return 0;
}
return eaten;
}
int int
sl_pp_purify(const char *input, sl_pp_purify(const char *input,
const struct sl_pp_purify_options *options, const struct sl_pp_purify_options *options,
@@ -247,6 +267,7 @@ sl_pp_purify(const char *input,
unsigned int *errorline) unsigned int *errorline)
{ {
struct out_buf obuf; struct out_buf obuf;
struct sl_pp_purify_state state;
obuf.out = NULL; obuf.out = NULL;
obuf.len = 0; obuf.len = 0;
@@ -255,17 +276,23 @@ sl_pp_purify(const char *input,
obuf.errormsg = errormsg; obuf.errormsg = errormsg;
obuf.cberrormsg = cberrormsg; obuf.cberrormsg = cberrormsg;
sl_pp_purify_state_init(&state, input, options);
for (;;) { for (;;) {
unsigned int eaten; unsigned int eaten;
char c;
eaten = _purify_comment(input, &obuf); eaten = sl_pp_purify_getc(&state, &c, &obuf.current_line, errormsg, cberrormsg);
if (!eaten) { if (!eaten) {
*errorline = obuf.current_line; *errorline = obuf.current_line;
return -1; 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; break;
} }
} }

View File

@@ -41,4 +41,23 @@ sl_pp_purify(const char *input,
unsigned int cberrormsg, unsigned int cberrormsg,
unsigned int *errorline); 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 */ #endif /* SL_PP_PURIFY_H */