home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d7xx / d702 / indent.lha / Indent / Indent.lha / indent-1.4io.c < prev    next >
C/C++ Source or Header  |  1992-06-24  |  22KB  |  929 lines

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