home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Archive / OS2_Archive_CD-ROM_Walnut_Creek_May_1992.iso / novell / progrmng / indent.zoo / io.c < prev    next >
C/C++ Source or Header  |  1989-10-22  |  16KB  |  652 lines

  1. /*
  2.  * Copyright (c) 1985 Sun Microsystems, Inc. Copyright (c) 1980 The Regents
  3.  * of the University of California. Copyright (c) 1976 Board of Trustees of
  4.  * the University of Illinois. All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms are permitted provided that
  7.  * the above copyright notice and this paragraph are duplicated in all such
  8.  * forms and that any documentation, advertising materials, and other
  9.  * materials related to such distribution and use acknowledge that the
  10.  * software was developed by the University of California, Berkeley, the
  11.  * University of Illinois, Urbana, and Sun Microsystems, Inc.  The name of
  12.  * either University or Sun Microsystems may not be used to endorse or
  13.  * promote products derived from this software without specific prior written
  14.  * permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
  16.  * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17.  */
  18.  
  19. #ifndef lint
  20. static char     sccsid[] = "@(#)io.c    5.10 (Berkeley) 9/15/88";
  21.  
  22. #endif                                    /* not lint */
  23.  
  24. #include "globs.h"
  25. #include <ctype.h>
  26. #include <memory.h>
  27.  
  28.  
  29. int             comment_open;
  30. static          paren_target;
  31.  
  32. dump_line()
  33. {                                        /* dump_line is the routine that
  34.                                          * actually effects the printing of
  35.                                          * the new source. It prints the
  36.                                          * label section, followed by the
  37.                                          * code section with the appropriate
  38.                                          * nesting level, followed by any
  39.                                          * comments */
  40.     register int    cur_col,
  41.                     target_col;
  42.     static          not_first_line;
  43.  
  44.     if (ps.procname[0])
  45.     {
  46.         if (troff)
  47.         {
  48.             if (comment_open)
  49.             {
  50.                 comment_open = 0;
  51.                 fprintf(output, ".*/\n");
  52.             }
  53.             fprintf(output, ".Pr \"%s\"\n", ps.procname);
  54.         }
  55.         ps.ind_level = 0;
  56.         ps.procname[0] = 0;
  57.     }
  58.     if (s_code == e_code && s_lab == e_lab && s_com == e_com)
  59.     {
  60.         if (suppress_bl > 0)
  61.             suppress_bl--;
  62.         else
  63.         {
  64.             ps.bl_line = true;
  65.             n_real_bl++;
  66.         }
  67.     }
  68.     else if (!inhibit_formatting)
  69.     {
  70.         suppress_bl = 0;
  71.         ps.bl_line = false;
  72.         if (prefix_bl_requested && not_first_line)
  73.             if (swallow_optional_bl)
  74.             {
  75.                 if (n_real_bl == 1)
  76.                     n_real_bl = 0;
  77.             }
  78.             else
  79.             {
  80.                 if (n_real_bl == 0)
  81.                     n_real_bl = 1;
  82.             }
  83.         while (--n_real_bl >= 0)
  84.             putc('\n', output);
  85.         n_real_bl = 0;
  86.         if (ps.ind_level == 0)
  87.             ps.ind_stmt = 0;            /* this is a class A kludge. dont do
  88.                                          * additional statement indentation
  89.                                          * if we are at bracket level 0 */
  90.  
  91.         if (e_lab != s_lab || e_code != s_code)
  92.             ++code_lines;                /* keep count of lines with code */
  93.  
  94.  
  95.         if (e_lab != s_lab)
  96.         {                                /* print lab, if any */
  97.             if (comment_open)
  98.             {
  99.                 comment_open = 0;
  100.                 fprintf(output, ".*/\n");
  101.             }
  102.             while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  103.                 e_lab--;
  104.             cur_col = pad_output(1, compute_label_target());
  105.             fprintf(output, "%.*s", e_lab - s_lab, s_lab);
  106.             cur_col = count_spaces(cur_col, s_lab);
  107.         }
  108.         else
  109.             cur_col = 1;                /* there is no label section */
  110.  
  111.         ps.pcase = false;
  112.  
  113.         if (s_code != e_code)
  114.         {                                /* print code section, if any */
  115.             register char  *p;
  116.  
  117.             if (comment_open)
  118.             {
  119.                 comment_open = 0;
  120.                 fprintf(output, ".*/\n");
  121.             }
  122.             target_col = compute_code_target();
  123.             {
  124.                 register        i;
  125.  
  126.                 for (i = 0; i < ps.p_l_follow; i++)
  127.                     if (ps.paren_indents[i] >= 0)
  128.                         ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
  129.             }
  130.             cur_col = pad_output(cur_col, target_col);
  131.             for (p = s_code; p < e_code; p++)
  132.                 if (*p == (char) 0200)
  133.                     fprintf(output, "%d", target_col * 7);
  134.                 else
  135.                     putc(*p, output);
  136.             cur_col = count_spaces(cur_col, s_code);
  137.         }
  138.         if (s_com != e_com)
  139.             if (troff)
  140.             {
  141.                 int             all_here = 0;
  142.                 register char  *p;
  143.  
  144.                 if (e_com[-1] == '/' && e_com[-2] == '*')
  145.                     e_com -= 2, all_here++;
  146.                 while (e_com > s_com && e_com[-1] == ' ')
  147.                     e_com--;
  148.                 *e_com = 0;
  149.                 p = s_com;
  150.                 while (*p == ' ')
  151.                     p++;
  152.                 if (p[0] == '/' && p[1] == '*')
  153.                     p += 2, all_here++;
  154.                 else if (p[0] == '*')
  155.                     p += p[1] == '/' ? 2 : 1;
  156.                 while (*p == ' ')
  157.                     p++;
  158.                 if (*p == 0)
  159.                     goto inhibit_newline;
  160.                 if (comment_open < 2 && ps.box_com)
  161.                 {
  162.                     comment_open = 0;
  163.                     fprintf(output, ".*/\n");
  164.                 }
  165.                 if (comment_open == 0)
  166.                 {
  167.                     if ('a' <= *p && *p <= 'z')
  168.                         *p = *p + 'A' - 'a';
  169.                     if (e_com - p < 50 && all_here == 2)
  170.                     {
  171.                         register char  *follow = p;
  172.  
  173.                         fprintf(output, "\n.nr C! \\w\1");
  174.                         while (follow < e_com)
  175.                         {
  176.                             switch (*follow)
  177.                             {
  178.                             case '\n':
  179.                                 putc(' ', output);
  180.                             case 1:
  181.                                 break;
  182.                             case '\\':
  183.                                 putc('\\', output);
  184.                             default:
  185.                                 putc(*follow, output);
  186.                             }
  187.                             follow++;
  188.                         }
  189.                         putc(1, output);
  190.                     }
  191.                     fprintf(output, "\n./* %dp %d %dp\n",
  192.                             ps.com_col * 7,
  193.                           (s_code != e_code || s_lab != e_lab) - ps.box_com,
  194.                             target_col * 7);
  195.                 }
  196.                 comment_open = 1 + ps.box_com;
  197.                 while (*p)
  198.                 {
  199.                     if (*p == BACKSLASH)
  200.                         putc(BACKSLASH, output);
  201.                     putc(*p++, output);
  202.                 }
  203.             }
  204.             else
  205.             {                            /* print comment, if any */
  206.                 register        target = ps.com_col;
  207.                 register char  *com_st = s_com;
  208.  
  209.                 target += ps.comment_delta;
  210.                 while (*com_st == '\t')
  211.                     /*** com_st++, target += 8; ***/        /* ? */
  212.                     com_st++, target += tabsize;  /* JHT 10/22/89 */
  213.  
  214.                 while (target <= 0)
  215.                     if (*com_st == ' ')
  216.                         target++, com_st++;
  217.                     else if (*com_st == '\t') {
  218.                         /*** target = ((target - 1) & ~7) + 9, com_st++; ***/
  219.                         target += (tabsize - ((target - 1) % tabsize)); /* JHT 10/22/89 */
  220.                         com_st++;
  221.                     }
  222.                     else
  223.                         target = 1;
  224.                 if (cur_col > target)
  225.                 {                        /* if comment cant fit on this line,
  226.                                          * put it on next line */
  227.                     putc('\n', output);
  228.                     cur_col = 1;
  229.                     ++ps.out_lines;
  230.                 }
  231.                 while (e_com > com_st && isspace(e_com[-1]))
  232.                     e_com--;
  233.                 cur_col = pad_output(cur_col, target);
  234.                 if (!ps.box_com)
  235.                 {
  236.                     if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1))
  237.                         if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1)
  238.                             com_st[1] = '*';
  239.                         else
  240.                             fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output);
  241.                 }
  242.                 fwrite(com_st, e_com - com_st, 1, output);
  243.                 ps.comment_delta = ps.n_comment_delta;
  244.                 cur_col = count_spaces(cur_col, com_st);
  245.                 ++ps.com_lines;            /* count lines with comments */
  246.             }
  247.         if (ps.use_ff)
  248.             putc('\014', output);
  249.         else
  250.             putc('\n', output);
  251. inhibit_newline:
  252.         ++ps.out_lines;
  253.         if (ps.just_saw_decl == 1 && bl_after_dcl)
  254.         {
  255.             prefix_bl_requested = 1;
  256.             ps.just_saw_decl = 0;
  257.         }
  258.         else
  259.             prefix_bl_requested = postfix_bl_requested;
  260.         postfix_bl_requested = 0;
  261.     }
  262.     ps.decl_on_line = ps.in_decl;        /* if we are in the middle of a
  263.                                          * declaration, remember that fact
  264.                                          * for proper comment indentation */
  265.     ps.ind_stmt = ps.in_stmt & ~ps.in_decl;        /* next line should be
  266.                                                  * indented if we have not
  267.                                                  * completed this stmt and if
  268.                                                  * we are not in the middle
  269.                                                  * of a declaration */
  270.     ps.use_ff = false;
  271.     ps.dumped_decl_indent = 0;
  272.     *(e_lab = s_lab) = '\0';            /* reset buffers */
  273.     *(e_code = s_code) = '\0';
  274.     *(e_com = s_com) = '\0';
  275.     ps.ind_level = ps.i_l_follow;
  276.     ps.paren_level = ps.p_l_follow;
  277.     paren_target = -ps.paren_indents[ps.paren_level - 1];
  278.     not_first_line = 1;
  279.     return;
  280. };
  281.  
  282. compute_code_target()
  283. {
  284.     register        target_col = ps.ind_size * ps.ind_level + 1;
  285.  
  286.     if (ps.paren_level)
  287.         if (!lineup_to_parens)
  288.             target_col += continuation_indent * ps.paren_level;
  289.         else
  290.         {
  291.             register        w;
  292.             register        t = paren_target;
  293.  
  294.             if ((w = count_spaces(t, s_code) - max_col) > 0
  295.                 && count_spaces(target_col, s_code) <= max_col)
  296.             {
  297.                 t -= w + 1;
  298.                 if (t > target_col)
  299.                     target_col = t;
  300.             }
  301.             else
  302.                 target_col = t;
  303.         }
  304.     else if (ps.ind_stmt)
  305.         target_col += continuation_indent;
  306.     return target_col;
  307. }
  308.  
  309. compute_label_target()
  310. {
  311.     return
  312.       ps.pcase ? (int) (case_ind * ps.ind_size) + 1
  313.       : *s_lab == '#' ? 1
  314.       : ps.ind_size * (ps.ind_level - label_offset) + 1;
  315. }
  316.  
  317.  
  318. /*
  319.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  320.  * 
  321.  * All rights reserved
  322.  * 
  323.  * 
  324.  * NAME: fill_buffer
  325.  * 
  326.  * FUNCTION: Reads one block of input into input_buffer
  327.  * 
  328.  * HISTORY: initial coding     November 1976    D A Willcox of CAC 1/7/77 A
  329.  * Willcox of CAC    Added check for switch back to partly full input buffer
  330.  * from temporary buffer
  331.  * 
  332.  */
  333. int fill_buffer()
  334.  
  335. {                                        /* this routine reads stuff from the
  336.                                          * input */
  337.     register char  *p;
  338.     register int    i;
  339.     register FILE  *f = input;
  340.  
  341.     if (bp_save != 0)
  342.     {                                    /* there is a partly filled input
  343.                                          * buffer left */
  344.         buf_ptr = bp_save;                /* dont read anything, just switch
  345.                                          * buffers */
  346.         buf_end = be_save;
  347.         bp_save = be_save = 0;
  348.         if (buf_ptr < buf_end)
  349.             return;                        /* only return if there is really
  350.                                          * something in this buffer */
  351.     }
  352.     for (p = buf_ptr = in_buffer;;)
  353.     {
  354.         if ((i = getc(f)) == EOF)
  355.         {
  356.             *p++ = ' ';
  357.             *p++ = '\n';
  358.             had_eof = true;
  359.             break;
  360.         }
  361.         *p++ = i;
  362.         if (i == '\n')
  363.             break;
  364.     }
  365.     buf_end = p;
  366.     if (p[-2] == '/' && p[-3] == '*')
  367.     {
  368.         if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
  369.             fill_buffer();                /* flush indent error message */
  370.         else
  371.         {
  372.             int             com = 0;
  373.  
  374.             p = in_buffer;
  375.             while (*p == ' ' || *p == '\t')
  376.                 p++;
  377.             if (*p == '/' && p[1] == '*')
  378.             {
  379.                 p += 2;
  380.                 while (*p == ' ' || *p == '\t')
  381.                     p++;
  382.                 if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
  383.                     && p[4] == 'N' && p[5] == 'T')
  384.                 {
  385.                     p += 6;
  386.                     while (*p == ' ' || *p == '\t')
  387.                         p++;
  388.                     if (*p == '*')
  389.                         com = 1;
  390.                     else if (*p == 'O')
  391.                         if (*++p == 'N')
  392.                             p++, com = 1;
  393.                         else if (*p == 'F' && *++p == 'F')
  394.                             p++, com = 2;
  395.                     while (*p == ' ' || *p == '\t')
  396.                         p++;
  397.                     if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com)
  398.                     {
  399.                         if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  400.                             dump_line();
  401.                         if (!(inhibit_formatting = com - 1))
  402.                         {
  403.                             n_real_bl = 0;
  404.                             postfix_bl_requested = 0;
  405.                             prefix_bl_requested = 0;
  406.                             suppress_bl = 1;
  407.                         }
  408.                     }
  409.                 }
  410.             }
  411.         }
  412.     }
  413.     if (inhibit_formatting)
  414.     {
  415.         p = in_buffer;
  416.         do
  417.             putc(*p, output);
  418.         while (*p++ != '\n');
  419.     }
  420.     return;
  421. };
  422.  
  423. /*
  424.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  425.  * 
  426.  * All rights reserved
  427.  * 
  428.  * 
  429.  * NAME: pad_output
  430.  * 
  431.  * FUNCTION: Writes tabs and spaces to move the current column up to the desired
  432.  * position.
  433.  * 
  434.  * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
  435.  * 
  436.  * PARAMETERS: current        integer        The current column target integer
  437.  * e desired column
  438.  * 
  439.  * RETURNS: Integer value of the new column.  (If current >= target, no action
  440.  * is taken, and current is returned.
  441.  * 
  442.  * GLOBALS: None
  443.  * 
  444.  * CALLS: write (sys)
  445.  * 
  446.  * CALLED BY: dump_line
  447.  * 
  448.  * HISTORY: initial coding     November 1976    D A Willcox of CAC
  449.  * 
  450.  */
  451. pad_output(current, target)                /* writes tabs and blanks (if
  452.                                          * necessary) to get the current
  453.                                          * output position up to the target
  454.                                          * column */
  455. int             current;                /* the current column value */
  456. int             target;                    /* position we want it at */
  457. {
  458.     register int    tstop;                /* Current tab stop being visited */
  459.  
  460.     if (troff)
  461.         fprintf(output, "\\h'|%dp'", (target - 1) * 7);
  462.     else
  463.     {
  464.         if (current >= target)
  465.             return (current);            /* line is already long enough */
  466.  
  467.         /* Compute where next tab stop lies: */
  468.  
  469.         tstop = current + tabsize - ((current - 1) % tabsize);
  470.  
  471.         for (; tstop <= target; tstop += tabsize)
  472.             putc('\t', output);            /* Tab to each tabstop */
  473.  
  474.         tstop -= tabsize;                /* Account for overshoot */
  475.  
  476.         while (tstop++ < target)
  477.             putc(' ', output);            /* Space over to where we want to be */
  478.     }
  479.  
  480.     return (target);
  481. };
  482.  
  483. /*
  484.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  485.  * 
  486.  * All rights reserved
  487.  * 
  488.  * 
  489.  * NAME: count_spaces
  490.  * 
  491.  * FUNCTION: Find out where printing of a given string will leave the current
  492.  * character position on output.
  493.  * 
  494.  * ALGORITHM: Run thru input string and add appropriate values to current
  495.  * position.
  496.  * 
  497.  * RETURNS: Integer value of position after printing "buffer" starting in column
  498.  * "current".
  499.  * 
  500.  * HISTORY: initial coding     November 1976    D A Willcox of CAC
  501.  * 
  502.  */
  503. int
  504.                 count_spaces(current, buffer)
  505.  
  506. /*
  507.  * this routine figures out where the character position will be after
  508.  * printing the text in buffer starting at column "current"
  509.  */
  510. int             current;
  511. char           *buffer;
  512. {
  513.     register char  *buf;                /* used to look thru buffer */
  514.     register int    cur;                /* current character counter */
  515.  
  516.     cur = current;
  517.  
  518.     for (buf = buffer; *buf != '\0'; ++buf)
  519.     {
  520.         switch (*buf)
  521.         {
  522.  
  523.         case '\n':
  524.         case 014:                        /* form feed */
  525.             cur = 1;
  526.             break;
  527.  
  528.         case '\t':
  529.             cur = cur + (tabsize - ((cur - 1) % tabsize));
  530.             break;
  531.  
  532.         case '':                        /* this is a backspace */
  533.             --cur;
  534.             break;
  535.  
  536.         default:
  537.             ++cur;
  538.             break;
  539.         }                                /* end of switch */
  540.     }                                    /* end of for loop */
  541.     return (cur);
  542. };
  543.  
  544. int             found_err;
  545.  
  546. diag(level, msg, a, b)
  547. char           *msg;
  548. {
  549.     if (level)
  550.         found_err = 1;
  551.     if (output == stdout)
  552.     {
  553.         fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  554.         fprintf(stdout, msg, a, b);
  555.         fprintf(stdout, " */\n");
  556.     }
  557.     else
  558.     {
  559.         fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  560.         fprintf(stderr, msg, a, b);
  561.         fprintf(stderr, "\n");
  562.     }
  563. }
  564.  
  565. writefdef(f, nm)
  566. register struct fstate *f;
  567. {
  568.     fprintf(output, ".ds f%c %s\n.nr s%c %d\n",
  569.             nm, f->font, nm, f->size);
  570. }
  571.  
  572. char           *
  573.                 chfont(of, nf, s)
  574. register struct fstate *of,
  575.                *nf;
  576. char           *s;
  577. {
  578.     if (of->font[0] != nf->font[0]
  579.         || of->font[1] != nf->font[1])
  580.     {
  581.         *s++ = '\\';
  582.         *s++ = 'f';
  583.         if (nf->font[1])
  584.         {
  585.             *s++ = '(';
  586.             *s++ = nf->font[0];
  587.             *s++ = nf->font[1];
  588.         }
  589.         else
  590.             *s++ = nf->font[0];
  591.     }
  592.     if (nf->size != of->size)
  593.     {
  594.         *s++ = '\\';
  595.         *s++ = 's';
  596.         if (nf->size < of->size)
  597.         {
  598.             *s++ = '-';
  599.             *s++ = '0' + of->size - nf->size;
  600.         }
  601.         else
  602.         {
  603.             *s++ = '+';
  604.             *s++ = '0' + nf->size - of->size;
  605.         }
  606.     }
  607.     return s;
  608. }
  609.  
  610.  
  611. parsefont(f, s0)
  612. register struct fstate *f;
  613. char           *s0;
  614. {
  615.     register char  *s = s0;
  616.     int             sizedelta = 0;
  617.  
  618.     memset(f, 0, sizeof(*f));
  619.     while (*s)
  620.     {
  621.         if (isdigit(*s))
  622.             f->size = f->size * 10 + *s - '0';
  623.         else if (isupper(*s))
  624.             if (f->font[0])
  625.                 f->font[1] = *s;
  626.             else
  627.                 f->font[0] = *s;
  628.         else if (*s == 'c')
  629.             f->allcaps = 1;
  630.         else if (*s == '+')
  631.             sizedelta++;
  632.         else if (*s == '-')
  633.             sizedelta--;
  634.         else
  635.         {
  636.             fprintf(stderr, "indent: bad font specification: %s\n", s0);
  637.             exit(1);
  638.         }
  639.         s++;
  640.     }
  641.     if (f->font[0] == 0)
  642.         f->font[0] = 'R';
  643.     if (bodyf.size == 0)
  644.         bodyf.size = 11;
  645.     if (f->size == 0)
  646.         f->size = bodyf.size + sizedelta;
  647.     else if (sizedelta > 0)
  648.         f->size += bodyf.size;
  649.     else
  650.         f->size = bodyf.size - f->size;
  651. }
  652.