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