+/* Some state during the execution of `read_c_string_or_comment'. */
+struct rcsoc_state
+{
+ /* A count of spaces and newlines that have been read, but not output. */
+ unsigned pending_spaces, pending_newlines;
+
+ /* Where we're reading from. */
+ FILE *in_file;
+
+ /* If non-zero, a buffer into which to copy characters. */
+ char *buf_ptr;
+ /* If non-zero, a file into which to copy characters. */
+ FILE *out_file;
+
+ /* A keyword we look for at the beginning of lines. If found, it is
+ not copied, and SAW_KEYWORD is set to true. */
+ char *keyword;
+ /* The current point we've reached in an occurance of KEYWORD in
+ the input stream. */
+ char *cur_keyword_ptr;
+ /* Set to true if we saw an occurance of KEYWORD. */
+ int saw_keyword;
+};
+
+/* Output CH to the file or buffer in STATE. Any pending newlines or
+ spaces are output first. */
+
+static INLINE void
+put_char (ch, state)
+ int ch;
+ struct rcsoc_state *state;
+{
+ int out_ch;
+ do
+ {
+ if (state->pending_newlines > 0)
+ {
+ state->pending_newlines--;
+ out_ch = '\n';
+ }
+ else if (state->pending_spaces > 0)
+ {
+ state->pending_spaces--;
+ out_ch = ' ';
+ }
+ else
+ out_ch = ch;
+
+ if (state->out_file)
+ putc (out_ch, state->out_file);
+ if (state->buf_ptr)
+ *state->buf_ptr++ = out_ch;
+ }
+ while (out_ch != ch);
+}
+
+/* If in the middle of scanning a keyword, continue scanning with
+ character CH, otherwise output CH to the file or buffer in STATE.
+ Any pending newlines or spaces are output first, as well as any
+ previously scanned characters that were thought to be part of a
+ keyword, but were in fact not. */
+
+static void
+scan_keyword_or_put_char (ch, state)
+ int ch;
+ struct rcsoc_state *state;
+{
+ if (state->keyword
+ && *state->cur_keyword_ptr == ch
+ && (state->cur_keyword_ptr > state->keyword
+ || state->pending_newlines > 0))
+ /* We might be looking at STATE->keyword at some point.
+ Keep looking until we know for sure. */
+ {
+ if (*++state->cur_keyword_ptr == '\0')
+ /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
+ {
+ state->saw_keyword = 1;
+
+ /* Reset the scanning pointer. */
+ state->cur_keyword_ptr = state->keyword;
+
+ /* Canonicalize whitespace preceding a usage string. */
+ state->pending_newlines = 2;
+ state->pending_spaces = 0;
+
+ /* Skip any whitespace between the keyword and the
+ usage string. */
+ do
+ ch = getc (state->in_file);
+ while (ch == ' ' || ch == '\n');
+
+ /* Output the open-paren we just read. */
+ put_char (ch, state);
+
+ /* Skip the function name and replace it with `fn'. */
+ do
+ ch = getc (state->in_file);
+ while (ch != ' ' && ch != ')');
+ put_char ('f', state);
+ put_char ('n', state);
+
+ /* Put back the last character. */
+ ungetc (ch, state->in_file);
+ }
+ }
+ else
+ {
+ if (state->keyword && state->cur_keyword_ptr > state->keyword)
+ /* We scanned the beginning of a potential usage
+ keyword, but it was a false alarm. Output the
+ part we scanned. */
+ {
+ char *p;
+
+ for (p = state->keyword; p < state->cur_keyword_ptr; p++)
+ put_char (*p, state);
+
+ state->cur_keyword_ptr = state->keyword;
+ }
+
+ put_char (ch, state);
+ }
+}
+
+
+/* Skip a C string or C-style comment from INFILE, and return the
+ character that follows. COMMENT non-zero means skip a comment. If
+ PRINTFLAG is positive, output string contents to outfile. If it is
+ negative, store contents in buf. Convert escape sequences \n and
+ \t to newline and tab; discard \ followed by newline.
+ If SAW_USAGE is non-zero, then any occurances of the string `usage:'
+ at the beginning of a line will be removed, and *SAW_USAGE set to
+ true if any were encountered. */