}
-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,
unsigned int *errorline)
{
struct out_buf obuf;
+ struct sl_pp_purify_state state;
obuf.out = NULL;
obuf.len = 0;
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;
}
}