home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / INDENTSR.ZIP / IO.C < prev    next >
C/C++ Source or Header  |  1992-08-27  |  18KB  |  715 lines

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