]> code.delx.au - gnu-emacs/blobdiff - lib-src/make-docfile.c
(last_node): Make it a global variable.
[gnu-emacs] / lib-src / make-docfile.c
index ed786b0951e2a94e6829431d0b763d6febe577fc..99da7b851864114e8f48cae92ad7c118400533f7 100644 (file)
@@ -79,7 +79,7 @@ FILE *outfile;
 /* Name this program was invoked with.  */
 char *progname;
 
-/* Print error message.  `s1' is printf control string, `s2' is arg for it. */
+/* Print error message.  `s1' is printf control string, `s2' is arg for it.  */
 
 /* VARARGS1 */
 void
@@ -198,42 +198,122 @@ scan_file (filename)
 \f
 char buf[128];
 
-/* Add CH to either outfile, if PRINTFLAG is positive, or to the buffer
-   whose end is pointed to by BUFP, if PRINTFLAG is negative.
-   If the counters pointed to by PENDING_NEWLINES and PENDING_SPACES are
-   non-zero, that many newlines and spaces are output before CH, and
-   the counters are zeroed.  */
+/* 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, printflag, bufp, pending_newlines, pending_spaces)
-     int ch, printflag;
-     char **bufp;
-     unsigned *pending_newlines, *pending_spaces;
+put_char (ch, state)
+     int ch;
+     struct rcsoc_state *state;
 {
   int out_ch;
   do
     {
-      if (*pending_newlines > 0)
+      if (state->pending_newlines > 0)
        {
-         (*pending_newlines)--;
+         state->pending_newlines--;
          out_ch = '\n';
        }
-      else if (*pending_spaces > 0)
+      else if (state->pending_spaces > 0)
        {
-         (*pending_spaces)--;
+         state->pending_spaces--;
          out_ch = ' ';
        }
       else
        out_ch = ch;
 
-      if (printflag > 0)
-       putc (out_ch, outfile);
-      else if (printflag < 0)
-       *(*bufp)++ = out_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');
+
+         /* Put back the non-whitespace 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
@@ -250,26 +330,21 @@ read_c_string_or_comment (infile, printflag, comment, saw_usage)
      int *saw_usage;
 {
   register int c;
-  unsigned pending_spaces = 0, pending_newlines = 0;
-  char *p = buf;
-  /* When this keyword occurs at the beginning of a line, we remove it,
-     and set *SAW_USAGE to true.  */
-  static char usage_keyword[] = "usage:";
-  /* The current point we've reached in an occurance of USAGE_KEYWORD in
-     the input stream.  */
-  char *cur_usage_ptr = usage_keyword;
-
+  struct rcsoc_state state;
+
+  state.in_file = infile;
+  state.buf_ptr = (printflag < 0 ? buf : 0);
+  state.out_file = (printflag > 0 ? outfile : 0);
+  state.pending_spaces = 0;
+  state.pending_newlines = 0;
+  state.keyword = (saw_usage ? "usage:" : 0);
+  state.cur_keyword_ptr = state.keyword;
+  state.saw_keyword = 0;
+
+  c = getc (infile);
   if (comment)
-    {
-      while ((c = getc (infile)) != EOF
-            && (c == '\n' || c == '\r' || c == '\t' || c == ' '))
-       ;
-    }
-  else
-    c = getc (infile);
-  
-  if (saw_usage)
-    *saw_usage = 0;
+    while (c == '\n' || c == '\r' || c == '\t' || c == ' ')
+      c = getc (infile);
 
   while (c != EOF)
     {
@@ -288,61 +363,16 @@ read_c_string_or_comment (infile, printflag, comment, saw_usage)
              if (c == 't')
                c = '\t';
            }
-         
+
          if (c == ' ')
-           pending_spaces++;
+           state.pending_spaces++;
          else if (c == '\n')
            {
-             pending_newlines++;
-             pending_spaces = 0;
+             state.pending_newlines++;
+             state.pending_spaces = 0;
            }
          else
-           {
-             if (saw_usage
-                 && *cur_usage_ptr == c
-                 && (cur_usage_ptr > usage_keyword || pending_newlines > 0))
-               /* We might be looking at USAGE_KEYWORD at some point.
-                  Keep looking until we know for sure.  */
-               {
-                 if (*++cur_usage_ptr == '\0')
-                   /* Saw the whole keyword.  Set *SAW_USAGE to true.  */
-                   {
-                     *saw_usage = 1;
-
-                     /* Reset the scanning pointer.  */
-                     cur_usage_ptr = usage_keyword;
-
-                     /* Canonicalize whitespace preceding a usage string. */
-                     pending_newlines = 2;
-                     pending_spaces = 0;
-
-                     /* Skip any whitespace between the keyword and the
-                        usage string.  */
-                     do
-                       c = getc (infile);
-                     while (c == ' ' || c == '\n');
-
-                     continue; /* This just skips the getc at end-of-loop. */
-                   }
-               }
-             else
-               {
-                 if (cur_usage_ptr > usage_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 = usage_keyword; p < cur_usage_ptr; p++)
-                       put_char (*p, printflag, &p,
-                                 &pending_newlines, &pending_spaces);
-                     cur_usage_ptr = usage_keyword;
-                   }
-
-                 put_char (c, printflag, &p,
-                           &pending_newlines, &pending_spaces);
-               }
-           }
+           scan_keyword_or_put_char (c, &state);
 
          c = getc (infile);
        }
@@ -357,21 +387,24 @@ read_c_string_or_comment (infile, printflag, comment, saw_usage)
              c = getc (infile);
              break;
            }
-         
-         put_char ('*', printflag, &p, &pending_newlines, &pending_spaces);
+
+         scan_keyword_or_put_char ('*', &state);
        }
       else
        {
          if (c != '"')
            break;
-      
+
          /* If we had a "", concatenate the two strings.  */
          c = getc (infile);
        }
     }
-  
+
   if (printflag < 0)
-    *p = 0;
+    *state.buf_ptr = 0;
+
+  if (saw_usage)
+    *saw_usage = state.saw_keyword;
 
   return c;
 }
@@ -493,7 +526,7 @@ scan_c_file (filename, mode)
       return 0;
     }
 
-  /* Reset extension to be able to detect duplicate files. */
+  /* Reset extension to be able to detect duplicate files.  */
   filename[strlen (filename) - 1] = extension;
 
   c = '\n';
@@ -611,10 +644,10 @@ scan_c_file (filename, mode)
 
       while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
        c = getc (infile);
-      
+
       if (c == '"')
        c = read_c_string_or_comment (infile, 0, 0, 0);
-      
+
       while (c != EOF && c != ',' && c != '/')
        c = getc (infile);
       if (c == ',')
@@ -641,7 +674,7 @@ scan_c_file (filename, mode)
        {
          int comment = c != '"';
          int saw_usage;
-         
+
          putc (037, outfile);
          putc (defvarflag ? 'V' : 'F', outfile);
          fprintf (outfile, "%s\n", buf);
@@ -671,7 +704,7 @@ scan_c_file (filename, mode)
                      goto eof;
                    c = getc (infile);
                  }
-             
+
              /* Skip into arguments.  */
              while (c != '(')
                {
@@ -715,14 +748,14 @@ scan_c_file (filename, mode)
  When we find that, we save it for the following defining-form,
  and we use that instead of reading a doc string within that defining-form.
 
- For defvar, defconst, and fset we skip to the docstring with a kludgy 
+ For defvar, defconst, and fset we skip to the docstring with a kludgy
  formatting convention: all docstrings must appear on the same line as the
- initial open-paren (the one in column zero) and must contain a backslash 
+ initial open-paren (the one in column zero) and must contain a backslash
  and a newline immediately after the initial double-quote.  No newlines
  must appear between the beginning of the form and the first double-quote.
  For defun, defmacro, and autoload, we know how to skip over the
  arglist, but the doc string must still have a backslash and newline
- immediately after the double quote. 
+ immediately after the double quote.
  The only source files that must follow this convention are preloaded
  uncompiled ones like loaddefs.el and bindings.el; aside
  from that, it is always the .elc file that we look at, and they are no
@@ -768,7 +801,7 @@ read_lisp_symbol (infile, buffer)
 
   if (! buffer[0])
     fprintf (stderr, "## expected a symbol, got '%c'\n", c);
-  
+
   skip_white (infile);
 }
 
@@ -912,7 +945,7 @@ scan_lisp_file (filename, mode)
                  c1 = c;
                  c = getc (infile);
                }
-         
+
              /* If two previous characters were " and \,
                 this is a doc string.  Otherwise, there is none.  */
              if (c2 != '"' || c1 != '\\')
@@ -971,7 +1004,7 @@ scan_lisp_file (filename, mode)
                  c1 = c;
                  c = getc (infile);
                }
-         
+
              /* If two previous characters were " and \,
                 this is a doc string.  Otherwise, there is none.  */
              if (c2 != '"' || c1 != '\\')
@@ -1028,7 +1061,7 @@ scan_lisp_file (filename, mode)
                  c1 = c;
                  c = getc (infile);
                }
-         
+
              /* If two previous characters were " and \,
                 this is a doc string.  Otherwise, there is none.  */
              if (c2 != '"' || c1 != '\\')