home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / indent-1.9.1-base.tgz / indent-1.9.1-base.tar / fsf / indent / io.c < prev    next >
C/C++ Source or Header  |  1994-01-29  |  22KB  |  942 lines

  1. /* Copyright (c) 1994, Joseph Arceneaux.  All rights reserved.
  2.  
  3.    Copyright (c) 1992, Free Software Foundation, Inc.  All rights reserved.
  4.  
  5.    Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
  6.    of the University of California. Copyright (c) 1976 Board of Trustees of
  7.    the University of Illinois. All rights reserved.
  8.  
  9.    Redistribution and use in source and binary forms are permitted
  10.    provided that
  11.    the above copyright notice and this paragraph are duplicated in all such
  12.    forms and that any documentation, advertising materials, and other
  13.    materials related to such distribution and use acknowledge that the
  14.    software was developed by the University of California, Berkeley, the
  15.    University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
  16.    either University or Sun Microsystems may not be used to endorse or
  17.    promote products derived from this software without specific prior written
  18.    permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
  20.    OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
  21.  
  22.  
  23. #include "sys.h"
  24. #include "indent.h"
  25. #include <ctype.h>
  26.  
  27. #ifdef VMS
  28. #   include <file.h>
  29. #   include <types.h>
  30. #   include <stat.h>
  31. #else  /* not VMS */
  32.  
  33. /* POSIX says that <fcntl.h> should exist.  Some systems might need to use
  34.    <sys/fcntl.h> or <sys/file.h> instead.  */
  35. #include <fcntl.h>
  36.  
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #endif /* not VMS */
  40.  
  41. /* number of levels a label is placed to left of code */
  42. #define LABEL_OFFSET 2
  43.  
  44.  
  45. /* Stuff that needs to be shared with the rest of indent. Documented in
  46.    indent.h.  */
  47. char *in_prog;
  48. char *in_prog_pos;
  49. char *cur_line;
  50. unsigned long in_prog_size;
  51. FILE *output;
  52. char *buf_ptr;
  53. char *buf_end;
  54. int had_eof;
  55. int out_lines;
  56. int com_lines;
  57.  
  58. int suppress_blanklines = 0;
  59. static int comment_open;
  60.  
  61. int paren_target;
  62.  
  63. /* Use `perror' to print the system error message
  64.    caused by OFFENDER, then exit. */
  65.  
  66. void
  67. sys_error (offender)
  68.      char *offender;
  69. {
  70.   int buffer_size;
  71.   char *errbuf;
  72.  
  73.   /* Grab extra space to handle random unix lossage */
  74.   errbuf = (char *) xmalloc (strlen (offender) + 10);
  75.  
  76.   sprintf (errbuf, "indent: %s", offender);
  77.   perror (errbuf);
  78.   exit (1);
  79. }
  80.  
  81. #ifdef VMS
  82. /* Folks say VMS requires its own read routine.  Then again, some folks
  83.    say it doesn't.  Different folks have also sent me conflicting versions
  84.    of this function.  Who's right?
  85.  
  86.    Anyway, this version was sent by MEHRDAD@glum.dev.cf.ac.uk */
  87.  
  88. int
  89. vms_read (int file_desc, char *buffer, int nbytes)
  90. {
  91.     register char *bufp;
  92.     register int nread, nleft;
  93.  
  94.     bufp  = buffer;
  95.     nread = 0;
  96.     nleft = nbytes;
  97.  
  98.     nread = read (file_desc, bufp, nleft);
  99.     while (nread > 0)
  100.       {
  101.         bufp += nread;
  102.         nleft -= nread;
  103.         if (nleft < 0)
  104.       sys_error ("Internal buffering error");
  105.     nread = read (file_desc, bufp, nleft);
  106.       }
  107.  
  108.     return nbytes - nleft;
  109. }
  110. #endif /* VMS */
  111.  
  112. INLINE int
  113. count_columns (column, bp)
  114.      int column;
  115.      char *bp;
  116. {
  117.   while (*bp != '\0')
  118.     {
  119.       switch (*bp++)
  120.     {
  121.     case EOL:
  122.     case 014:        /* form feed */
  123.       column = 1;
  124.       break;
  125.     case TAB:
  126.       column += tabsize - (column - 1) % tabsize;
  127.       break;
  128.     case 010:        /* backspace */
  129.       --column;
  130.       break;
  131.     default:
  132.       ++column;
  133.       break;
  134.     }
  135.     }
  136.  
  137.   return column;
  138. }
  139.  
  140. /* Return the column we are at in the input line. */
  141.  
  142. INLINE int
  143. current_column ()
  144. {
  145.   char *p;
  146.   int column = 1;
  147.  
  148.   if (buf_ptr >= save_com.ptr && buf_ptr <= save_com.end)
  149.     p = save_com.ptr;
  150.   else
  151.     p = cur_line;
  152.  
  153. #if 0
  154.   /* Paranoia -- Turning this on breaks stuff, but I haven't yet
  155.      investigated. */
  156.   if (! (buf_ptr >= cur_line && buf_ptr < in_prog_pos))
  157.     abort ();
  158. #endif
  159.  
  160.   column = 1;
  161.   while (p < buf_ptr)
  162.     switch (*p++)
  163.       {
  164.       case EOL:
  165.       case 014:            /* form feed */
  166.     column = 1;
  167.     break;
  168.       case TAB:
  169.     column += tabsize - (column - 1) % tabsize;
  170.     break;
  171.       case '\b':        /* backspace */
  172.     column--;
  173.     break;
  174.       default:
  175.     column++;
  176.     break;
  177.       }
  178.  
  179.   return column;
  180. }
  181.  
  182. void
  183. dump_line ()
  184. {                /* dump_line is the routine that actually
  185.                    effects the printing of the new source. It
  186.                    prints the label section, followed by the
  187.                    code section with the appropriate nesting
  188.                    level, followed by any comments */
  189.   register int cur_col;
  190.   register int target_col = 0;
  191.   static not_first_line;
  192.  
  193.   if (parser_state_tos->procname[0])
  194.     {
  195.       if (troff)
  196.     {
  197.       if (comment_open)
  198.         {
  199.           comment_open = 0;
  200.           fprintf (output, ".*/\n");
  201.         }
  202.       fprintf (output, ".Pr \"%.*s\"\n",
  203.            parser_state_tos->procname_end - parser_state_tos->procname,
  204.            parser_state_tos->procname);
  205.     }
  206.       parser_state_tos->ind_level = 0;
  207.       parser_state_tos->procname = "\0";
  208.     }
  209.  
  210.   /* A blank line */
  211.   if (s_code == e_code && s_lab == e_lab && s_com == e_com)
  212.     {
  213.       /* If we have a formfeed on a blank line, we should just output it,
  214.          rather than treat it as a normal blank line.  */
  215.       if (parser_state_tos->use_ff)
  216.     {
  217.       putc ('\014', output);
  218.       parser_state_tos->use_ff = false;
  219.     }
  220.       else
  221.     {
  222.       if (suppress_blanklines > 0)
  223.         suppress_blanklines--;
  224.       else
  225.         {
  226.           parser_state_tos->bl_line = true;
  227.           n_real_blanklines++;
  228.         }
  229.     }
  230.     }
  231.   else
  232.     {
  233.       suppress_blanklines = 0;
  234.       parser_state_tos->bl_line = false;
  235.       if (prefix_blankline_requested
  236.       && not_first_line
  237.       && n_real_blanklines == 0)
  238.     n_real_blanklines = 1;
  239.       else if (swallow_optional_blanklines && n_real_blanklines > 1)
  240.     n_real_blanklines = 1;
  241.  
  242.       while (--n_real_blanklines >= 0)
  243.     putc (EOL, output);
  244.       n_real_blanklines = 0;
  245.       if (parser_state_tos->ind_level == 0)
  246.     parser_state_tos->ind_stmt = 0;    /* this is a class A kludge. dont do
  247.                        additional statement indentation
  248.                        if we are at bracket level 0 */
  249.  
  250.       if (e_lab != s_lab || e_code != s_code)
  251.     ++code_lines;        /* keep count of lines with code */
  252.  
  253.  
  254.       if (e_lab != s_lab)
  255.     {            /* print lab, if any */
  256.       if (comment_open)
  257.         {
  258.           comment_open = 0;
  259.           fprintf (output, ".*/\n");
  260.         }
  261.       while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == TAB))
  262.         e_lab--;
  263.       cur_col = pad_output (1, compute_label_target ());
  264.       if (s_lab[0] == '#' && (strncmp (s_lab, "#else", 5) == 0
  265.                   || strncmp (s_lab, "#endif", 6) == 0))
  266.         {
  267.           /* Treat #else and #endif as a special case because any text
  268.              after #else or #endif should be converted to a comment.  */
  269.           register char *s = s_lab;
  270.           if (e_lab[-1] == EOL)
  271.         e_lab--;
  272.           do
  273.         putc (*s++, output);
  274.           while (s < e_lab && 'a' <= *s && *s <= 'z');
  275.           while ((*s == ' ' || *s == TAB) && s < e_lab)
  276.         s++;
  277.           if (s < e_lab)
  278.         {
  279.           if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
  280.             fprintf (output, (tabsize > 1 ? "\t%.*s" : "  %.*s"),
  281.                  e_lab - s, s);
  282.           else
  283.             fprintf (output, (tabsize > 1
  284.                       ? "\t/* %.*s */"
  285.                       : "  /* %.*s */"),
  286.                  e_lab - s, s);
  287.         }
  288.         }
  289.       else
  290.         fprintf (output, "%.*s", e_lab - s_lab, s_lab);
  291.       cur_col = count_columns (cur_col, s_lab);
  292.     }
  293.       else
  294.     cur_col = 1;        /* there is no label section */
  295.  
  296.       parser_state_tos->pcase = false;
  297.  
  298.       if (s_code != e_code)
  299.     {            /* print code section, if any */
  300.       register char *p;
  301.       register i;
  302.  
  303.       if (comment_open)
  304.         {
  305.           comment_open = 0;
  306.           fprintf (output, ".*/\n");
  307.         }
  308.  
  309.       /* If a comment begins this line, then indent it to the right
  310.          column for comments, otherwise the line starts with code,
  311.          so indent it for code. */
  312.       if (embedded_comment_on_line == 1)
  313.         target_col = parser_state_tos->com_col;
  314.       else
  315.         target_col = compute_code_target ();
  316.  
  317.       /* If a line ends in an lparen character, the following line should
  318.          not line up with the parenthesis, but should be indented by the
  319.          usual amount.  */
  320.       if (parser_state_tos->last_token == lparen)
  321.         {
  322.           parser_state_tos->paren_indents[parser_state_tos->p_l_follow - 1]
  323.         += ind_size - 1;
  324.         }
  325.  
  326.       for (i = 0; i < parser_state_tos->p_l_follow; i++)
  327.         if (parser_state_tos->paren_indents[i] >= 0)
  328.           parser_state_tos->paren_indents[i]
  329.         = -(parser_state_tos->paren_indents[i] + target_col);
  330.  
  331.       cur_col = pad_output (cur_col, target_col);
  332.       for (p = s_code; p < e_code; p++)
  333.         putc (*p, output);
  334.       cur_col = count_columns (cur_col, s_code);
  335.     }
  336.  
  337.       if (s_com != e_com)
  338.     {
  339.       if (troff)
  340.         {
  341.           int all_here = 0;
  342.           register char *p;
  343.  
  344.           if (e_com[-1] == '/' && e_com[-2] == '*')
  345.         e_com -= 2, all_here++;
  346.           while (e_com > s_com && e_com[-1] == ' ')
  347.         e_com--;
  348.           *e_com = 0;
  349.           p = s_com;
  350.           while (*p == ' ')
  351.         p++;
  352.           if (p[0] == '/' && p[1] == '*')
  353.         p += 2, all_here++;
  354.           else if (p[0] == '*')
  355.         p += p[1] == '/' ? 2 : 1;
  356.           while (*p == ' ')
  357.         p++;
  358.           if (*p == 0)
  359.         goto inhibit_newline;
  360.           if (comment_open < 2 && parser_state_tos->box_com)
  361.         {
  362.           comment_open = 0;
  363.           fprintf (output, ".*/\n");
  364.         }
  365.           if (comment_open == 0)
  366.         {
  367.           if ('a' <= *p && *p <= 'z')
  368.             *p = *p + 'A' - 'a';
  369.           if (e_com - p < 50 && all_here == 2)
  370.             {
  371.               register char *follow = p;
  372.               fprintf (output, "\n.nr C! \\w\1");
  373.               while (follow < e_com)
  374.             {
  375.               switch (*follow)
  376.                 {
  377.                 case EOL:
  378.                   putc (' ', output);
  379.                 case 1:
  380.                   break;
  381.                 case '\\':
  382.                   putc ('\\', output);
  383.                 default:
  384.                   putc (*follow, output);
  385.                 }
  386.               follow++;
  387.             }
  388.               putc (1, output);
  389.             }
  390.           fprintf (output, "\n./* %dp %d %dp\n",
  391.                (int) (parser_state_tos->com_col * 7),
  392.                (int) ((s_code != e_code || s_lab != e_lab)
  393.                   - parser_state_tos->box_com),
  394.                (int) (target_col * 7));
  395.         }
  396.           comment_open = 1 + parser_state_tos->box_com;
  397.           while (*p)
  398.         {
  399.           if (*p == BACKSLASH)
  400.             putc (BACKSLASH, output);
  401.           putc (*p++, output);
  402.         }
  403.         }
  404.       else
  405.         {
  406.           /* Here for comment printing.  This code is new as of
  407.              version 1.8 */
  408.           register target = parser_state_tos->com_col;
  409.           register char *com_st = s_com;
  410.  
  411.           if (cur_col > target)
  412.         {
  413.           putc (EOL, output);
  414.           cur_col = 1;
  415.           ++out_lines;
  416.         }
  417.  
  418.           cur_col = pad_output (cur_col, target);
  419.           fwrite (com_st, e_com - com_st, 1, output);
  420.           cur_col += e_com - com_st;
  421.           com_lines++;
  422.         }
  423.     }
  424.       else if (embedded_comment_on_line)
  425.     com_lines++;
  426.       embedded_comment_on_line = 0;
  427.  
  428.       if (parser_state_tos->use_ff)
  429.     {
  430.       putc ('\014', output);
  431.       parser_state_tos->use_ff = false;
  432.     }
  433.       else
  434.     putc (EOL, output);
  435.  
  436.     inhibit_newline:
  437.       ++out_lines;
  438.       if (parser_state_tos->just_saw_decl == 1
  439.       && blanklines_after_declarations)
  440.     {
  441.       prefix_blankline_requested = 1;
  442.       parser_state_tos->just_saw_decl = 0;
  443.     }
  444.       else
  445.     prefix_blankline_requested = postfix_blankline_requested;
  446.       postfix_blankline_requested = 0;
  447.     }
  448.  
  449.   /* if we are in the middle of a declaration, remember that fact
  450.      for proper comment indentation */
  451.   parser_state_tos->decl_on_line = parser_state_tos->in_decl;
  452.  
  453.   /* next line should be indented if we have not completed this
  454.      stmt and if we are not in the middle of a declaration */
  455.   parser_state_tos->ind_stmt = (parser_state_tos->in_stmt
  456.                 & ~parser_state_tos->in_decl);
  457.  
  458.   parser_state_tos->dumped_decl_indent = 0;
  459.   *(e_lab  = s_lab) = '\0';    /* reset buffers */
  460.   *(e_code = s_code) = '\0';
  461.   *(e_com  = s_com) = '\0';
  462.   parser_state_tos->ind_level = parser_state_tos->i_l_follow;
  463.   parser_state_tos->paren_level = parser_state_tos->p_l_follow;
  464.   if (parser_state_tos->paren_level > 0)
  465.     paren_target
  466.       = -parser_state_tos->paren_indents[parser_state_tos->paren_level - 1];
  467.   else
  468.     paren_target = 0;
  469.   not_first_line = 1;
  470.  
  471.   return;
  472. }
  473.  
  474. /* Return the column in which we should place the code about to be output. */
  475.  
  476. INLINE int
  477. compute_code_target ()
  478. {
  479.   register target_col = parser_state_tos->ind_level + 1;
  480.   register w, t;
  481.  
  482.   if (! parser_state_tos->paren_level)
  483.     {
  484.       if (parser_state_tos->ind_stmt)
  485.     target_col += continuation_indent;
  486.       return target_col;
  487.     }
  488.  
  489.   if (!lineup_to_parens)
  490.     return target_col + (continuation_indent * parser_state_tos->paren_level);
  491.  
  492.   t = paren_target;
  493.   if ((w = count_columns (t, s_code) - max_col) > 0
  494.       && count_columns (target_col, s_code) <= max_col)
  495.     {
  496.       t -= w + 1;
  497.       if (t > target_col)
  498.     target_col = t;
  499.     }
  500.   else
  501.     target_col = t;
  502.  
  503.   return target_col;
  504. }
  505.  
  506. INLINE int
  507. compute_label_target ()
  508. {
  509.   return
  510.   parser_state_tos->pcase ? case_ind + 1
  511.   : *s_lab == '#' ? 1
  512.   : parser_state_tos->ind_level - LABEL_OFFSET + 1;
  513. }
  514.  
  515. /* VMS defines it's own read routine, `vms_read' */
  516. #ifndef SYS_READ
  517. #define SYS_READ read
  518. #endif
  519.  
  520. /* Read file FILENAME into a `fileptr' structure, and return a pointer to
  521.    that structure. */
  522.  
  523. static struct file_buffer fileptr;
  524.  
  525. struct file_buffer *
  526. read_file (filename)
  527.      char *filename;
  528. {
  529.   int fd, size;
  530.   struct stat file_stats;
  531.   int namelen = strlen (filename);
  532.  
  533.   fd = open (filename, O_RDONLY, 0777);
  534.   if (fd < 0)
  535.     sys_error (filename);
  536.  
  537.   if (fstat (fd, &file_stats) < 0)
  538.     sys_error (filename);
  539.  
  540.   if (file_stats.st_size <= 0)
  541.     diag (1, "Warning: Zero-length file %s", filename);
  542.  
  543.   fileptr.size = file_stats.st_size;
  544.   if (fileptr.data != 0)
  545.     fileptr.data = (char *) xrealloc (fileptr.data, file_stats.st_size + 1);
  546.   else
  547.     fileptr.data = (char *) xmalloc (file_stats.st_size + 1);
  548.  
  549.   size = SYS_READ (fd, fileptr.data, fileptr.size);
  550.   if (size < 0)
  551.     sys_error (filename);
  552.   if (close (fd) < 0)
  553.     sys_error (filename);
  554.  
  555.   /* Apparently, the DOS stores files using CR-LF for newlines, but
  556.      then the DOS `read' changes them into '\n'.  Thus, the size of the
  557.      file on disc is larger than what is read into memory.  Thanks, Bill. */
  558.   if (size < fileptr.size)
  559.     fileptr.size = size;
  560.  
  561.   if (fileptr.name != 0)
  562.     fileptr.name = (char *) xrealloc (fileptr.name, namelen + 1);
  563.   else
  564.     fileptr.name = (char *) xmalloc (namelen + 1);
  565.   memcpy (fileptr.name, filename, namelen);
  566.   fileptr.name[namelen] = '\0';
  567.  
  568.   fileptr.data[fileptr.size] = '\0';
  569.  
  570.   return &fileptr;
  571. }
  572.  
  573. /* This should come from stdio.h and be some system-optimal number */
  574. #ifndef BUFSIZ
  575. #define BUFSIZ 1024
  576. #endif
  577.  
  578. /* Suck the standard input into a file_buffer structure, and
  579.    return a pointer to that structure. */
  580.  
  581. struct file_buffer stdinptr;
  582.  
  583. struct file_buffer *
  584. read_stdin ()
  585. {
  586.   unsigned int size = 15 * BUFSIZ;
  587.   int ch;
  588.   register char *p;
  589.  
  590.   if (stdinptr.data != 0)
  591.     free (stdinptr.data);
  592.  
  593.   stdinptr.data = (char *) xmalloc (size + 1);
  594.   stdinptr.size = 0;
  595.   p = stdinptr.data;
  596.   do
  597.     {
  598.       while (stdinptr.size < size)
  599.     {
  600.       ch = getc (stdin);
  601.       if (ch == EOF)
  602.         break;
  603.  
  604.       *p++ = ch;
  605.       stdinptr.size++;
  606.     }
  607.  
  608.       if (ch != EOF)
  609.     {
  610.       size += (2 * BUFSIZ);
  611.       stdinptr.data = xrealloc (stdinptr.data, size);
  612.       p = stdinptr.data + stdinptr.size;
  613.     }
  614.     }
  615.   while (ch != EOF);
  616.  
  617.   stdinptr.name = "Standard Input";
  618.  
  619.   stdinptr.data[stdinptr.size] = '\0';
  620.  
  621.   return &stdinptr;
  622. }
  623.  
  624. /* Points to the current input buffer */
  625. extern struct file_buffer *current_input;
  626.  
  627. /* Advance `buf_ptr' so that it points to the next line of input.
  628.  
  629.    If the next input line contains an indent control comment turning
  630.    off formatting (a comment, C or C++, beginning with *INDENT-OFF*),
  631.    then simply print out input lines without formatting until we find
  632.    a corresponding comment containing *INDENT-0N* which re-enables
  633.    formatting.
  634.  
  635.    Note that if this is a C comment we do not look for the closing
  636.    delimiter.  Note also that older version of this program also
  637.    skipped lines containing *INDENT** which represented errors
  638.    generated by indent in some previous formatting.  This version does
  639.    not recognize such lines. */
  640.  
  641. INLINE void
  642. fill_buffer ()
  643. {
  644.   register char *p;
  645.   int finished_a_line;
  646.  
  647.   /* indent() may be saving the text between "if (...)" and the following
  648.      statement.  To do so, it uses another buffer (`save_com').  Switch
  649.      back to the previous buffer here. */
  650.   if (bp_save != 0)
  651.     {
  652.       buf_ptr = bp_save;
  653.       buf_end = be_save;
  654.       bp_save = be_save = 0;
  655.  
  656.       /* only return if there is really something in this buffer */
  657.       if (buf_ptr < buf_end)
  658.     return;
  659.     }
  660.  
  661.   if (*in_prog_pos == '\0')
  662.     {
  663.       cur_line = buf_ptr = in_prog_pos;
  664.       had_eof = true;
  665.       return;
  666.     }
  667.  
  668.   /* Here if we know there are chars to read. */
  669.   p = cur_line = in_prog_pos;
  670.   finished_a_line = 0;
  671.   do
  672.     {
  673.       while (*p == ' ' || *p == TAB)
  674.     p++;
  675.       if (*p == '/' && (*(p + 1) == '*' || *(p + 1) == '/'))
  676.     {
  677.       p += 2;
  678.       while (*p == ' ' || *p == TAB)
  679.         p++;
  680.       if (! strncmp (p, "*INDENT-OFF*", 12))
  681.         {
  682.           char *q = cur_line;
  683.           int inhibited = 1;
  684.  
  685.           if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  686.         dump_line ();
  687.           while (q < p)
  688.         putc (*q++, output);
  689.           do
  690.         {
  691.           while (*p != '\0' && *p != EOL)
  692.             putc (*p++, output);
  693.           if (*p == '\0'
  694.               && (p - current_input->data) == current_input->size)
  695.             {
  696.               buf_ptr = buf_end = in_prog_pos = p;
  697.               had_eof = 1;
  698.               return;
  699.             }
  700.  
  701.           if (*p == EOL)
  702.             cur_line = p + 1;
  703.           putc (*p++, output);
  704.           while (*p == ' ' || *p == TAB)
  705.             putc (*p++, output);
  706.           if (*p == '/' && (*(p + 1) == '*' || *(p + 1) == '/'))
  707.             {
  708.               /* We've hit a comment.  See if turns formatting
  709.              back on. */
  710.               putc (*p++, output);
  711.               putc (*p++, output);
  712.               while (*p == ' ' || *p == TAB)
  713.             putc (*p++, output);
  714.               if (! strncmp (p, "*INDENT-ON*", 11))
  715.             {
  716.               do
  717.                 {
  718.                   while (*p != '\0' && *p != EOL)
  719.                 putc (*p++, output);
  720.                   if (*p == '\0' && ((p - current_input->data)
  721.                          == current_input->size))
  722.                 {
  723.                   buf_ptr = buf_end = in_prog_pos = p;
  724.                   had_eof = 1;
  725.                   return;
  726.                 }
  727.                   else
  728.                 {
  729.                   if (*p == EOL)
  730.                     {
  731.                       inhibited = 0;
  732.                       cur_line = p + 1;
  733.                     }
  734.                   putc (*p++, output);
  735.                 }
  736.                 }
  737.               while (inhibited);
  738.             }
  739.             }
  740.         }
  741.           while (inhibited);
  742.         }
  743.     }
  744.  
  745.       while (*p != '\0' && *p != EOL)
  746.     p++;
  747.  
  748.       /* Here for newline -- return unless formatting is off. */
  749.       if (*p == EOL)
  750.     {
  751.       finished_a_line = 1;
  752.       in_prog_pos = p + 1;
  753.     }
  754.       /* Here for embedded NULLs */
  755.       else if ((p - current_input->data) < current_input->size)
  756.     {
  757.       diag (0, "Warning: File %s contains NULL-characters\n",
  758.         current_input->name);
  759.       p++;
  760.     }
  761.       /* Here for EOF with no terminating newline char. */
  762.       else
  763.     {
  764.       in_prog_pos = p;
  765.       finished_a_line = 1;
  766.     }
  767.     }
  768.   while (!finished_a_line);
  769.  
  770.   buf_ptr = cur_line;
  771.   buf_end = in_prog_pos;
  772. }
  773.  
  774. /* Fill the output line with whitespace up to TARGET_COLUMN, given that
  775.    the line is currently in column CURRENT_COLUMN.  Returns the ending
  776.    column. */
  777.  
  778. INLINE int
  779. pad_output (current_column, target_column)
  780.   register int current_column;
  781.   register int target_column;
  782. {
  783.   if (troff)
  784.     {
  785.       fprintf (output, "\\h'|%dp'", (int) ((target_column - 1) * 7));
  786.       return 0;
  787.     }
  788.  
  789.   if (current_column >= target_column)
  790.     return current_column;
  791.  
  792.   if (tabsize > 1)
  793.     {
  794.       register int offset;
  795.  
  796.       offset = tabsize - (current_column - 1) % tabsize;
  797.       while (current_column + offset <= target_column)
  798.     {
  799.       putc (TAB, output);
  800.       current_column += offset;
  801.       offset = tabsize;
  802.     }
  803.     }
  804.  
  805.   while (current_column < target_column)
  806.     {
  807.       putc (' ', output);
  808.       current_column++;
  809.     }
  810.  
  811.   return current_column;
  812. }
  813.  
  814. /* Nonzero if we have found an error (not a warning).  */
  815. int found_err;
  816.  
  817. /* Signal an error.  LEVEL is nonzero if it is an error (as opposed to a
  818.    warning.  MSG is a printf-style format string.  Additional arguments are
  819.    additional arguments for printf.  */
  820. /* VARARGS2 */
  821. diag (level, msg, a, b)
  822.      int level;
  823.      unsigned int a, b;
  824.      char *msg;
  825. {
  826.   if (level)
  827.     found_err = 1;
  828.  
  829.   fprintf (stderr, "indent:%s:%d: %s: ", in_name, (int) line_no,
  830.        level == 0 ? "Warning" : "Error");
  831.  
  832.   if (msg)
  833.     fprintf (stderr, msg, a, b);
  834.  
  835.   fprintf (stderr, "\n");
  836. }
  837.  
  838. writefdef (f, nm)
  839.      register struct fstate *f;
  840.      unsigned int nm;
  841. {
  842.   fprintf (output, ".ds f%c %s\n.nr s%c %d\n",
  843.        (int) nm, f->font, nm, (int) f->size);
  844. }
  845.  
  846. /* Write characters starting at S to change the font from OF to NF.  Return a
  847.    pointer to the character after the last character written. For troff mode
  848.    only.  */
  849. char *
  850. chfont (of, nf, s)
  851.      register struct fstate *of, *nf;
  852.      char *s;
  853. {
  854.   if (of->font[0] != nf->font[0]
  855.       || of->font[1] != nf->font[1])
  856.     {
  857.       *s++ = '\\';
  858.       *s++ = 'f';
  859.       if (nf->font[1])
  860.     {
  861.       *s++ = '(';
  862.       *s++ = nf->font[0];
  863.       *s++ = nf->font[1];
  864.     }
  865.       else
  866.     *s++ = nf->font[0];
  867.     }
  868.   if (nf->size != of->size)
  869.     {
  870.       *s++ = '\\';
  871.       *s++ = 's';
  872.       if (nf->size < of->size)
  873.     {
  874.       *s++ = '-';
  875.       *s++ = '0' + of->size - nf->size;
  876.     }
  877.       else
  878.     {
  879.       *s++ = '+';
  880.       *s++ = '0' + nf->size - of->size;
  881.     }
  882.     }
  883.   return s;
  884. }
  885.  
  886. void
  887. parsefont (f, s0)
  888.      register struct fstate *f;
  889.      char *s0;
  890. {
  891.   register char *s = s0;
  892.   int sizedelta = 0;
  893.   int i;
  894.  
  895.   f->size = 0;
  896.   f->allcaps = 1;
  897.   for (i = 0; i < 4; i++)
  898.     f->font[i] = 0;
  899.  
  900.   while (*s)
  901.     {
  902.       if (isdigit (*s))
  903.     f->size = f->size * 10 + *s - '0';
  904.       else if (isupper (*s))
  905.     if (f->font[0])
  906.       f->font[1] = *s;
  907.     else
  908.       f->font[0] = *s;
  909.       else if (*s == 'c')
  910.     f->allcaps = 1;
  911.       else if (*s == '+')
  912.     sizedelta++;
  913.       else if (*s == '-')
  914.     sizedelta--;
  915.       else
  916.     {
  917.       fprintf (stderr, "indent: bad font specification: %s\n", s0);
  918.       exit (1);
  919.     }
  920.       s++;
  921.     }
  922.   if (f->font[0] == 0)
  923.     f->font[0] = 'R';
  924.   if (bodyf.size == 0)
  925.     bodyf.size = 11;
  926.   if (f->size == 0)
  927.     f->size = bodyf.size + sizedelta;
  928.   else if (sizedelta > 0)
  929.     f->size += bodyf.size;
  930.   else
  931.     f->size = bodyf.size - f->size;
  932. }
  933.  
  934. #ifdef DEBUG
  935. void
  936. dump_debug_line ()
  937. {
  938.   fprintf (output, "\n*** Debug output marker line ***\n");
  939. }
  940.  
  941. #endif
  942.