home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / indent / indent.c < prev    next >
C/C++ Source or Header  |  1999-05-21  |  56KB  |  2,000 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. #include "sys.h"
  21. #include "indent.h"
  22. #include <ctype.h>
  23.  
  24. #ifdef AMIGA
  25. #include <exec/types.h>
  26. #include <libraries/dos.h>
  27. #include <libraries/dosextens.h>
  28. #include <libraries/arpbase.h>
  29. #include <proto/arp.h>
  30. #include <proto/dos.h>
  31. #include <proto/exec.h>
  32.  
  33. #define MAXPATH 200
  34. #define MAXARGS 256
  35.  
  36. struct ArpBase *ArpBase;
  37.  
  38. int expand_args ();
  39. #endif /* AMIGA */
  40.  
  41. void
  42. usage ()
  43. {
  44.   fprintf (stderr, "usage: indent file [-o outfile ] [ options ]\n");
  45.   fprintf (stderr, "       indent file1 file2 ... fileN [ options ]\n");
  46.   exit (1);
  47. }
  48.  
  49.  
  50. /* Stuff that needs to be shared with the rest of indent.
  51.    Documented in indent.h.  */
  52. char *labbuf;
  53. char *s_lab;
  54. char *e_lab;
  55. char *l_lab;
  56. char *codebuf;
  57. char *s_code;
  58. char *e_code;
  59. char *l_code;
  60. char *combuf;
  61. char *s_com;
  62. char *e_com;
  63. char *l_com;
  64. struct buf save_com;
  65. char *bp_save;
  66. char *be_save;
  67. int code_lines;
  68. int line_no;
  69. struct fstate keywordf;
  70. struct fstate stringf;
  71. struct fstate boxcomf;
  72. struct fstate blkcomf;
  73. struct fstate scomf;
  74. struct fstate bodyf;
  75. int break_comma;
  76.  
  77. /* Insure that BUFSTRUC has at least REQ more chars left, if not extend it.
  78.       Note:  This may change bufstruc.ptr.  */
  79. #define need_chars(bufstruc, req) \
  80.   if ((bufstruc.end - bufstruc.ptr + (req)) >= bufstruc.size) \
  81. {\
  82.          int cur_chars = bufstruc.end - bufstruc.ptr;\
  83.          bufstruc.size *= 2;\
  84.          bufstruc.ptr = xrealloc (bufstruc.ptr,bufstruc.size);\
  85.          bufstruc.end = bufstruc.ptr + cur_chars;\
  86. }
  87.  
  88. /* True if there is an embedded comment on this code line */
  89. int embedded_comment_on_line;
  90.  
  91. int else_or_endif;
  92.  
  93. /* structure indentation levels */
  94. int *di_stack;
  95.  
  96. /* Currently allocated size of di_stack.  */
  97. int di_stack_alloc;
  98.  
  99. /* when this is positive, we have seen a ? without
  100.    the matching : in a <c>?<s>:<s> construct */
  101. int squest;
  102.  
  103. #define CHECK_CODE_SIZE \
  104.     if (e_code >= l_code) { \
  105.         register nsize = l_code-s_code+400; \
  106.         codebuf = (char *) xrealloc (codebuf, nsize); \
  107.         e_code = codebuf + (e_code-s_code) + 1; \
  108.         l_code = codebuf + nsize - 5; \
  109.         s_code = codebuf + 1; \
  110.     }
  111.  
  112. #define CHECK_LAB_SIZE \
  113.     if (e_lab >= l_lab) { \
  114.         register nsize = l_lab-s_lab+400; \
  115.         labbuf = (char *) xrealloc (labbuf, nsize); \
  116.         e_lab = labbuf + (e_lab-s_lab) + 1; \
  117.         l_lab = labbuf + nsize - 5; \
  118.         s_lab = labbuf + 1; \
  119.     }
  120.  
  121. static void
  122. indent (this_file)
  123.      struct file_buffer *this_file;
  124. {
  125.   register int i;
  126.   enum codes hd_type;
  127.   register char *t_ptr;
  128.   enum codes type_code;
  129.  
  130.   /* current indentation for declarations */
  131.   int dec_ind = 0;
  132.  
  133.   /* used when buffering up comments to remember that
  134.      a newline was passed over */
  135.   int flushed_nl = 0;        
  136.   int force_nl = 0;
  137.  
  138.   /* true when we've just see a case; determines what to do
  139.      with the following colon */
  140.   int scase = 0;
  141.  
  142.   /* true when in the expression part of if(...), while(...), etc. */
  143.   int sp_sw = 0;
  144.  
  145.   /* True if we have just encountered the end of an if (...), etc. (i.e. the
  146.      ')' of the if (...) was the last token).  The variable is set to 2 in
  147.      the middle of the main token reading loop and is decremented at the
  148.      beginning of the loop, so it will reach zero when the second token after
  149.      the ')' is read.  */
  150.   int last_token_ends_sp = 0;
  151.  
  152.   /* true iff last keyword was an else */
  153.   int last_else = 0;
  154.  
  155.  
  156.   in_prog = in_prog_pos = this_file->data;
  157.   in_prog_size = this_file->size;
  158.  
  159.   hd_type = code_eof;
  160.   dec_ind = 0;
  161.   last_token_ends_sp = false;
  162.   last_else = false;
  163.   sp_sw = force_nl = false;
  164.   scase = false;
  165.   squest = false;
  166.  
  167. #if 0
  168.   if (com_ind <= 1)
  169.     com_ind = 2;        /* dont put normal comments before column 2 */
  170. #endif
  171.  
  172.   if (troff)
  173.     {
  174.       if (bodyf.font[0] == 0)
  175.     parsefont (&bodyf, "R");
  176.       if (scomf.font[0] == 0)
  177.     parsefont (&scomf, "I");
  178.       if (blkcomf.font[0] == 0)
  179.     blkcomf = scomf, blkcomf.size += 2;
  180.       if (boxcomf.font[0] == 0)
  181.     boxcomf = blkcomf;
  182.       if (stringf.font[0] == 0)
  183.     parsefont (&stringf, "L");
  184.       if (keywordf.font[0] == 0)
  185.     parsefont (&keywordf, "B");
  186.       writefdef (&bodyf, 'B');
  187.       writefdef (&scomf, 'C');
  188.       writefdef (&blkcomf, 'L');
  189.       writefdef (&boxcomf, 'X');
  190.       writefdef (&stringf, 'S');
  191.       writefdef (&keywordf, 'K');
  192.     }
  193.   if (block_comment_max_col <= 0)
  194.     block_comment_max_col = max_col;
  195.   if (decl_com_ind <= 0)    /* if not specified by user, set this */
  196.     decl_com_ind =
  197.       ljust_decl ? (com_ind <= 10 ? 2 : com_ind - 8) : com_ind;
  198.   if (continuation_indent == 0)
  199.     continuation_indent = ind_size;
  200.   fill_buffer ();        /* get first batch of stuff into input buffer */
  201.  
  202. #if 0
  203.   parse (semicolon);
  204. #endif
  205.  
  206.   {
  207.     register char *p = buf_ptr;
  208.     register col = 1;
  209.  
  210.     while (1)
  211.       {
  212.     if (*p == ' ')
  213.       col++;
  214.     else if (*p == TAB)
  215.       col = tabsize - (col % tabsize) + 1;
  216.     else if (*p == EOL)
  217.       col = 1;
  218.     else
  219.       break;
  220.  
  221.     p++;
  222.       }
  223.  
  224. #if 0
  225.     if (col > ind_size)
  226.       parser_state_tos->ind_level = parser_state_tos->i_l_follow = col;
  227. #endif/
  228.   }
  229.  
  230.   if (troff)
  231.     {
  232.       register char *p = in_name, *beg = in_name;
  233.  
  234.       while (*p)
  235.     if (*p++ == '/')
  236.       beg = p;
  237.       fprintf (output, ".Fn \"%s\"\n", beg);
  238.     }
  239.   /* START OF MAIN LOOP */
  240.  
  241.   while (1)
  242.     {                /* this is the main loop.  it will go until
  243.                    we reach eof */
  244.       int is_procname;
  245.  
  246.       type_code = lexi ();    /* lexi reads one token.  "token" points to
  247.                    the actual characters. lexi returns a code
  248.                    indicating the type of token */
  249.  
  250.       if (last_token_ends_sp > 0)
  251.     last_token_ends_sp--;
  252.       is_procname = parser_state_tos->procname[0];
  253.  
  254.       /* The following code moves everything following an if (), while (),
  255.          else, etc. up to the start of the following stmt to a buffer. This
  256.          allows proper handling of both kinds of brace placement. */
  257.  
  258.       flushed_nl = false;
  259.       while (parser_state_tos->search_brace)
  260.     {
  261.       /* After scanning an if(), while (), etc., it might be necessary to
  262.          keep track of the text between the if() and the start of the
  263.          statement which follows.  Use save_com to do so.  */
  264.  
  265.       switch (type_code)
  266.         {
  267.         case newline:
  268.           ++line_no;
  269.           flushed_nl = true;
  270.         case form_feed:
  271.           break;        /* form feeds and newlines found here will be
  272.                    ignored */
  273.  
  274.         case lbrace:    /* this is a brace that starts the compound
  275.                    stmt */
  276.           if (save_com.end == save_com.ptr)
  277.         {
  278.           /* ignore buffering if a comment wasnt stored up */
  279.           parser_state_tos->search_brace = false;
  280.           goto check_type;
  281.         }
  282.           /* We need to put the '{' back into save_com somewhere.  */
  283.           if (btype_2)
  284.         /* Put it at the beginning, e.g. if (foo) { / * comment here *
  285.            / */
  286.  
  287.         save_com.ptr[0] = '{';
  288.  
  289.           else
  290.         {
  291.           /* Put it at the end, e.g. if (foo) / * comment here * / { */
  292.  
  293.           /* Putting in this newline causes a dump_line to occur
  294.              right after the comment, thus insuring that it will be
  295.              put in the correct column.  */
  296.           *save_com.end++ = EOL;
  297.           *save_com.end++ = '{';
  298.         }
  299.  
  300.           /* Go to common code to get out of this loop.  */
  301.           goto sw_buffer;
  302.  
  303.         case comment:    /* we have a comment, so we must copy it into
  304.                    the buffer */
  305.           if (!flushed_nl || save_com.end != save_com.ptr)
  306.         {
  307.           need_chars (save_com, 10);
  308.           if (save_com.end == save_com.ptr)
  309.             {        /* if this is the first comment, we must set
  310.                    up the buffer */
  311.               save_com.ptr[0] = save_com.ptr[1] = ' ';
  312.               save_com.end = save_com.ptr + 2;
  313.             }
  314.           else
  315.             {
  316.               *save_com.end++ = EOL;    /* add newline between
  317.                            comments */
  318.               *save_com.end++ = ' ';
  319.               --line_no;
  320.             }
  321.           *save_com.end++ = '/';    /* copy in start of comment */
  322.           *save_com.end++ = '*';
  323.  
  324.           for (;;)
  325.             {        /* loop until we get to the end of the
  326.                    comment */
  327.               /* make sure there is room for this character and
  328.                  (while we're at it) the '/' we might add at the end
  329.                  of the loop. */
  330.               need_chars (save_com, 2);
  331.               *save_com.end = *buf_ptr++;
  332.               if (buf_ptr >= buf_end)
  333.             {
  334.               fill_buffer ();
  335.               if (had_eof)
  336.                 {
  337.                   diag (1, "Unclosed comment", 0, 0);
  338.                   exit (1);
  339.                 }
  340.             }
  341.  
  342.               if (*save_com.end++ == '*' && *buf_ptr == '/')
  343.             break;    /* we are at end of comment */
  344.  
  345.             }
  346.           *save_com.end++ = '/';    /* add ending slash */
  347.           if (++buf_ptr >= buf_end)    /* get past / in buffer */
  348.             fill_buffer ();
  349.           break;
  350.         }
  351.         default:        /* it is the start of a normal statment */
  352.           if (flushed_nl)    /* if we flushed a newline, make sure it is
  353.                    put back */
  354.         force_nl = true;
  355.           if ((type_code == sp_paren && *token == 'i'
  356.            && last_else && else_if)
  357.           ||
  358.           (type_code == sp_nparen && *token == 'e'
  359.            && e_code != s_code && e_code[-1] == '}'))
  360.         force_nl = false;
  361.  
  362.           if (save_com.end == save_com.ptr)
  363.         {
  364.           /* ignore buffering if comment wasnt saved up */
  365.           parser_state_tos->search_brace = false;
  366.           goto check_type;
  367.         }
  368.           if (force_nl)
  369.         {        /* if we should insert a nl here, put it into
  370.                    the buffer */
  371.           force_nl = false;
  372.           --line_no;    /* this will be re-increased when the nl is
  373.                    read from the buffer */
  374.           need_chars (save_com, 2);
  375.           *save_com.end++ = EOL;
  376.           *save_com.end++ = ' ';
  377.           if (verbose && !flushed_nl)    /* print error msg if the
  378.                            line was not already
  379.                            broken */
  380.             diag (0, "Line broken", 0, 0);
  381.           flushed_nl = false;
  382.         }
  383.           for (t_ptr = token; t_ptr < token_end; ++t_ptr)
  384.         {
  385.           need_chars (save_com, 1);
  386.           *save_com.end++ = *t_ptr;    /* copy token into temp
  387.                            buffer */
  388.         }
  389.           parser_state_tos->procname = "\0";
  390.  
  391.         sw_buffer:
  392.           parser_state_tos->search_brace = false;    /* stop looking for
  393.                                start of stmt */
  394.           bp_save = buf_ptr;/* save current input buffer */
  395.           be_save = buf_end;
  396.           buf_ptr = save_com.ptr;    /* fix so that subsequent calls to
  397.                        lexi will take tokens out of
  398.                        save_com */
  399.           need_chars (save_com, 1);
  400.           *save_com.end++ = ' ';    /* add trailing blank, just in case */
  401.           buf_end = save_com.end;
  402.           save_com.end = save_com.ptr;    /* make save_com empty */
  403.           break;
  404.         }            /* end of switch */
  405.       /* we must make this check, just in case there was an unexpected
  406.          EOF */
  407.       if (type_code != code_eof)
  408.         type_code = lexi ();/* read another token */
  409.       /* if (parser_state_tos->search_brace)
  410.          parser_state_tos->procname[0] = 0; */
  411.       if ((is_procname = parser_state_tos->procname[0]) && flushed_nl
  412.           && !procnames_start_line && parser_state_tos->in_decl
  413.           && type_code == ident)
  414.         flushed_nl = 0;
  415.     }            /* end of while (search_brace) */
  416.       last_else = 0;
  417.  
  418.     check_type:
  419.       if (type_code == code_eof)
  420.     {            /* we got eof */
  421.       if (s_lab != e_lab || s_code != e_code
  422.           || s_com != e_com)/* must dump end of line */
  423.         dump_line ();
  424.       if (parser_state_tos->tos > 1)    /* check for balanced braces */
  425.         diag (1, "Stuff missing from end of file.", 0, 0);
  426.  
  427.       if (verbose)
  428.         {
  429.           printf ("There were %d output lines and %d comments\n",
  430.               (int) out_lines, (int) out_coms);
  431.           printf ("(Lines with comments)/(Lines with code): %6.3f\n",
  432.               (1.0 * com_lines) / code_lines);
  433.         }
  434.       fflush (output);
  435.       if (found_err)
  436.         exit (found_err);
  437.  
  438.       return;
  439.     }
  440.  
  441.       if ((type_code != comment) &&
  442.       (type_code != cplus_comment) &&
  443.       (type_code != newline) &&
  444.       (type_code != preesc) &&
  445.       (type_code != form_feed))
  446.     {
  447.       if (force_nl &&
  448.           (type_code != semicolon) &&
  449.           (type_code != lbrace || !btype_2))
  450.         {
  451.           /* we should force a broken line here */
  452.           if (verbose && !flushed_nl)
  453.         diag (0, "Line broken", 0, 0);
  454.           flushed_nl = false;
  455.           dump_line ();
  456.           parser_state_tos->want_blank = false;    /* dont insert blank at
  457.                                line start */
  458.           force_nl = false;
  459.         }
  460.       parser_state_tos->in_stmt = true;    /* turn on flag which causes
  461.                            an extra level of
  462.                            indentation. this is
  463.                            turned off by a ; or } */
  464.       if (s_com != e_com)
  465.         {            /* the turkey has embedded a comment in a
  466.                    line. Move it from the com buffer to the
  467.                    code buffer.  */
  468.           /* Do not add a space before the comment if it is the first
  469.              thing on the line.  */
  470.           if (e_code != s_code)
  471.         {
  472.           *e_code++ = ' ';
  473.         }
  474.           for (t_ptr = s_com; *t_ptr; ++t_ptr)
  475.         {
  476.           CHECK_CODE_SIZE;
  477.           *e_code++ = *t_ptr;
  478.         }
  479.           *e_code++ = ' ';
  480.           *e_code = '\0';    /* null terminate code sect */
  481.           parser_state_tos->want_blank = false;
  482.           e_com = s_com;
  483.           embedded_comment_on_line++;
  484.         }
  485.     }
  486.       else if (type_code != comment
  487.            && type_code != cplus_comment)
  488.     /* preserve force_nl thru a comment but
  489.        cancel forced newline after newline, form feed, etc */
  490.        force_nl = false;
  491.  
  492.  
  493.  
  494.       /*-----------------------------------------------------*\
  495.       |       do switch on type of token scanned              |
  496.       \*-----------------------------------------------------*/
  497.       CHECK_CODE_SIZE;
  498.       switch (type_code)
  499.     {            /* now, decide what to do with the token */
  500.  
  501.     case form_feed:    /* found a form feed in line */
  502.       parser_state_tos->use_ff = true;    /* a form feed is treated
  503.                            much like a newline */
  504.       dump_line ();
  505.       parser_state_tos->want_blank = false;
  506.       break;
  507.  
  508.     case newline:
  509.       if (parser_state_tos->last_token != comma
  510.           || parser_state_tos->p_l_follow > 0
  511.           || !leave_comma || parser_state_tos->block_init
  512.           || !break_comma || s_com != e_com
  513.           || (compute_code_target () + (e_code - s_code)
  514.           > max_col - tabsize))
  515.         {
  516.           dump_line ();
  517.           parser_state_tos->want_blank = false;
  518.         }
  519.       /* If we were on the line with a #else or a #endif, we aren't
  520.          anymore.  */
  521.       else_or_endif = false;
  522.       ++line_no;        /* keep track of input line number */
  523.       break;
  524.  
  525.     case lparen:
  526.       /* Braces in initializer lists should be put on new lines. This is
  527.          necessary so that -gnu does not cause things like char
  528.          *this_is_a_string_array[] = { "foo", "this_string_does_not_fit",
  529.          "nor_does_this_rather_long_string" } which is what happens
  530.          because we are trying to line the strings up with the
  531.          parentheses, and those that are too long are moved to the right
  532.          an ugly amount.
  533.     
  534.          However, if the current line is empty, the left brace is
  535.          already on a new line, so don't molest it.  */
  536.       if (token[0] == '{'
  537.           && (s_code != e_code || s_com != e_com || s_lab != e_lab))
  538.         {
  539.           dump_line ();
  540.           /* Do not put a space before the '{'.  */
  541.           parser_state_tos->want_blank = false;
  542.         }
  543.  
  544.       /* Count parens so we know how deep we are.  */
  545.       if (++parser_state_tos->p_l_follow
  546.           >= parser_state_tos->paren_indents_size)
  547.         {
  548.           parser_state_tos->paren_indents_size *= 2;
  549.           parser_state_tos->paren_indents = (short *)
  550.         xrealloc ((char *) parser_state_tos->paren_indents,
  551.               parser_state_tos->paren_indents_size
  552.               * sizeof (short));
  553.         }
  554.       parser_state_tos->paren_depth++;
  555.       if (parser_state_tos->want_blank && *token != '['
  556.           && (parser_state_tos->last_token != ident || proc_calls_space
  557.           || (parser_state_tos->its_a_keyword
  558.               && (!parser_state_tos->sizeof_keyword
  559.               || blank_after_sizeof))))
  560.         *e_code++ = ' ';
  561.  
  562.       if (parser_state_tos->in_decl && !parser_state_tos->block_init)
  563.         {
  564.           if (troff
  565.           && !parser_state_tos->dumped_decl_indent
  566.           && !is_procname
  567.           && parser_state_tos->last_token == decl)
  568.         {
  569.           parser_state_tos->dumped_decl_indent = 1;
  570.           sprintf (e_code, "\n.Du %dp+\200p \"%.*s\"\n",
  571.                (int) (dec_ind * 7),
  572.                token_end - token, token);
  573.           e_code += strlen (e_code);
  574.         }
  575.           else if (*token != '[')
  576.         {
  577.           while ((e_code - s_code) < dec_ind)
  578.             {
  579.               CHECK_CODE_SIZE;
  580.               *e_code++ = ' ';
  581.             }
  582.           *e_code++ = token[0];
  583.         }
  584.           else
  585.         *e_code++ = token[0];
  586.         }
  587.       else
  588.         *e_code++ = token[0];
  589.  
  590.       parser_state_tos->paren_indents[parser_state_tos->p_l_follow - 1]
  591.         = e_code - s_code;
  592.       if (sp_sw && parser_state_tos->p_l_follow == 1
  593.           && extra_expression_indent
  594.           && parser_state_tos->paren_indents[0] < 2 * ind_size)
  595.         parser_state_tos->paren_indents[0] = 2 * ind_size;
  596.       parser_state_tos->want_blank = false;
  597.  
  598.       if (parser_state_tos->in_or_st
  599.           && *token == '('
  600.           && parser_state_tos->tos <= 2)
  601.         {
  602.           /* this is a kluge to make sure that declarations will be
  603.              aligned right if proc decl has an explicit type on it, i.e.
  604.              "int a(x) {..." */
  605.           parse_lparen_in_decl ();
  606.  
  607.           /* Turn off flag for structure decl or initialization.  */
  608.           parser_state_tos->in_or_st = false;
  609.         }
  610.       if (parser_state_tos->sizeof_keyword)
  611.         parser_state_tos->sizeof_mask |= 1 << parser_state_tos->p_l_follow;
  612.  
  613.       /* The '(' that starts a cast can never be preceeded by an
  614.          indentifier or decl.  */
  615.       if (parser_state_tos->last_token == decl
  616.           || (parser_state_tos->last_token == ident
  617.           && parser_state_tos->last_rw != rw_return))
  618.         parser_state_tos->noncast_mask |=
  619.           1 << parser_state_tos->p_l_follow;
  620.       else
  621.         parser_state_tos->noncast_mask &=
  622.           ~(1 << parser_state_tos->p_l_follow);
  623.  
  624.       break;
  625.  
  626.     case rparen:
  627.       parser_state_tos->paren_depth--;
  628.       if (parser_state_tos->cast_mask
  629.           & (1 << parser_state_tos->p_l_follow)
  630.           & ~parser_state_tos->sizeof_mask)
  631.         {
  632.           parser_state_tos->last_u_d = true;
  633.           parser_state_tos->cast_mask &=
  634.         (1 << parser_state_tos->p_l_follow) - 1;
  635.           if (!parser_state_tos->cast_mask && cast_space)
  636.         parser_state_tos->want_blank = true;
  637.           else
  638.         parser_state_tos->want_blank = false;
  639.         }
  640.       else if (parser_state_tos->in_decl
  641.            && ! parser_state_tos->block_init
  642.            && parser_state_tos->paren_depth == 0)
  643.         parser_state_tos->want_blank = true;
  644.  
  645.       parser_state_tos->sizeof_mask
  646.         &= (1 << parser_state_tos->p_l_follow) - 1;
  647.       if (--parser_state_tos->p_l_follow < 0)
  648.         {
  649.           parser_state_tos->p_l_follow = 0;
  650.           diag (0, "Extra %c", (int) *token, 0);
  651.         }
  652.  
  653.       /* if the paren starts the line, then indent it */
  654.       if (e_code == s_code)
  655.         {
  656.           int level = parser_state_tos->p_l_follow;
  657.           parser_state_tos->paren_level = level;
  658.           if (level > 0)
  659.         paren_target = -parser_state_tos->paren_indents[level - 1];
  660.           else
  661.         paren_target = 0;
  662.         }
  663.       *e_code++ = token[0];
  664.  
  665. #if 0
  666.       if (!parser_state_tos->cast_mask || cast_space)
  667.         parser_state_tos->want_blank = true;
  668. #endif
  669.  
  670.       /* check for end of if (...), or some such */
  671.       if (sp_sw && (parser_state_tos->p_l_follow == 0))
  672.         {
  673.  
  674.           /* Indicate that we have just left the parenthesized expression
  675.              of a while, if, or for, unless we are getting out of the
  676.              parenthesized expression of the while of a do-while loop.
  677.              (do-while is different because a semicolon immediately
  678.              following this will not indicate a null loop body).  */
  679.           if (parser_state_tos->p_stack[parser_state_tos->tos]
  680.           != dohead)
  681.         last_token_ends_sp = 2;
  682.           sp_sw = false;
  683.           force_nl = true;    /* must force newline after if */
  684.           parser_state_tos->last_u_d = true;    /* inform lexi that a
  685.                                following operator is
  686.                                unary */
  687.           parser_state_tos->in_stmt = false;    /* dont use stmt
  688.                                continuation
  689.                                indentation */
  690.  
  691.           parse (hd_type);    /* let parser worry about if, or whatever */
  692.         }
  693.       parser_state_tos->search_brace = btype_2;    /* this should insure
  694.                                that constructs such
  695.                                as main(){...} and
  696.                                int[]{...} have their
  697.                                braces put in the
  698.                                right place */
  699.       break;
  700.  
  701.     case unary_op:        /* this could be any unary operation */
  702.       if (parser_state_tos->want_blank)
  703.         *e_code++ = ' ';
  704.  
  705.       if (troff
  706.           && !parser_state_tos->dumped_decl_indent
  707.           && parser_state_tos->in_decl && !is_procname)
  708.         {
  709.           sprintf (e_code, "\n.Du %dp+\200p \"%.*s\"\n",
  710.                (int) (dec_ind * 7),
  711.                token_end - token, token);
  712.           parser_state_tos->dumped_decl_indent = 1;
  713.           e_code += strlen (e_code);
  714.         }
  715.       else
  716.         {
  717.           char *res = token;
  718.           char *res_end = token_end;
  719.  
  720.           /* if this is a unary op in a declaration, we should
  721.          indent this token */
  722.           if (parser_state_tos->paren_depth == 0
  723.           && parser_state_tos->in_decl
  724.           && !parser_state_tos->block_init)
  725.         {
  726.           while ((e_code - s_code) < (dec_ind - (token_end - token)))
  727.             {
  728.               CHECK_CODE_SIZE;
  729.               *e_code++ = ' ';
  730.             }
  731.         }
  732.  
  733.           if (troff && token[0] == '-' && token[1] == '>')
  734.         {
  735.           static char resval[] = "\\(->";
  736.           res = resval;
  737.           res_end = res + sizeof (resval);
  738.         }
  739.  
  740.           for (t_ptr = res; t_ptr < res_end; ++t_ptr)
  741.         {
  742.           CHECK_CODE_SIZE;
  743.           *e_code++ = *t_ptr;
  744.         }
  745.         }
  746.       parser_state_tos->want_blank = false;
  747.       break;
  748.  
  749.     case binary_op:    /* any binary operation */
  750.       if (parser_state_tos->want_blank
  751.           || (e_code > s_code && *e_code != ' '))
  752.         *e_code++ = ' ';
  753.  
  754.       {
  755.         char *res = token;
  756.         char *res_end = token_end;
  757. #define set_res(str) \
  758.           {\
  759.         static char resval[] = str;\
  760.         res = resval;\
  761.         res_end = res + sizeof(resval);\
  762.           }
  763.  
  764.         if (troff)
  765.           switch (token[0])
  766.         {
  767.         case '<':
  768.           if (token[1] == '=')
  769.             set_res ("\\(<=");
  770.           break;
  771.         case '>':
  772.           if (token[1] == '=')
  773.             set_res ("\\(>=");
  774.           break;
  775.         case '!':
  776.           if (token[1] == '=')
  777.             set_res ("\\(!=");
  778.           break;
  779.         case '|':
  780.           if (token[1] == '|')
  781.             {
  782.               set_res ("\\(br\\(br");
  783.             }
  784.           else if (token[1] == 0)
  785.             set_res ("\\(br");
  786.           break;
  787.         }
  788.  
  789.         for (t_ptr = res; t_ptr < res_end; ++t_ptr)
  790.           {
  791.         CHECK_CODE_SIZE;
  792.         *e_code++ = *t_ptr;    /* move the operator */
  793.           }
  794.       }
  795.       parser_state_tos->want_blank = true;
  796.       break;
  797.  
  798.     case postop:        /* got a trailing ++ or -- */
  799.       *e_code++ = token[0];
  800.       *e_code++ = token[1];
  801.       parser_state_tos->want_blank = true;
  802.       break;
  803.  
  804.     case question:        /* got a ? */
  805.       squest++;        /* this will be used when a later colon
  806.                    appears so we can distinguish the
  807.                    <c>?<n>:<n> construct */
  808.       if (parser_state_tos->want_blank)
  809.         *e_code++ = ' ';
  810.       *e_code++ = '?';
  811.       parser_state_tos->want_blank = true;
  812.       break;
  813.  
  814.     case casestmt:        /* got word 'case' or 'default' */
  815.       scase = true;        /* so we can process the later colon
  816.                    properly */
  817.       goto copy_id;
  818.  
  819.     case colon:        /* got a ':' */
  820.       if (squest > 0)
  821.         {            /* it is part of the <c>?<n>: <n> construct */
  822.           --squest;
  823.           if (parser_state_tos->want_blank)
  824.         *e_code++ = ' ';
  825.           *e_code++ = ':';
  826.           parser_state_tos->want_blank = true;
  827.           break;
  828.         }
  829.       if (parser_state_tos->in_decl)
  830.         {
  831.           *e_code++ = ':';
  832.           parser_state_tos->want_blank = false;
  833.           break;
  834.         }
  835.       parser_state_tos->in_stmt = false;    /* seeing a label does not
  836.                            imply we are in a stmt */
  837.       for (t_ptr = s_code; *t_ptr; ++t_ptr)
  838.         *e_lab++ = *t_ptr;    /* turn everything so far into a label */
  839.       e_code = s_code;
  840.       *e_lab++ = ':';
  841.       *e_lab++ = ' ';
  842.       *e_lab = '\0';
  843.       /* parser_state_tos->pcas e will be used by dump_line to decide
  844.          how to indent the label. force_nl will force a case n: to be
  845.          on a line by itself */
  846.       force_nl = parser_state_tos->pcase = scase;
  847.       scase = false;
  848.       parser_state_tos->want_blank = false;
  849.       break;
  850.  
  851.     case semicolon:
  852.       /* we are not in an initialization or structure declaration */
  853.       parser_state_tos->in_or_st = false;
  854.       scase = false;
  855.       squest = 0;
  856.       /* The following code doesn't seem to do much good. Just because
  857.          we've found something like extern int foo();    or int (*foo)();
  858.          doesn't mean we are out of a declaration.  Now if it was serving
  859.          some purpose we'll have to address that.... if
  860.          (parser_state_tos->last_token == rparen)
  861.          parser_state_tos->in_parameter_declaration = 0; */
  862.       parser_state_tos->cast_mask = 0;
  863.       parser_state_tos->sizeof_mask = 0;
  864.       parser_state_tos->block_init = 0;
  865.       parser_state_tos->block_init_level = 0;
  866.       parser_state_tos->just_saw_decl--;
  867.  
  868.       if (parser_state_tos->in_decl
  869.           && s_code == e_code
  870.           && !parser_state_tos->block_init)
  871.         while ((e_code - s_code) < (dec_ind - 1))
  872.           {
  873.         CHECK_CODE_SIZE;
  874.         *e_code++ = ' ';
  875.           }
  876.  
  877.       /* if we were in a first level structure declaration,
  878.          we aren't any more */
  879.       parser_state_tos->in_decl = (parser_state_tos->dec_nest > 0);
  880.  
  881. #if 0    /* Changed to allow "{}" inside parens, as when
  882.        passed to a macro.  -jla */
  883.       if ((!sp_sw || hd_type != forstmt)
  884.           && parser_state_tos->p_l_follow > 0)
  885.         {
  886.  
  887.           /* This should be true iff there were unbalanced parens in the
  888.              stmt.  It is a bit complicated, because the semicolon might
  889.              be in a for stmt */
  890.           diag (1, "Unbalanced parens", 0, 0);
  891.           parser_state_tos->p_l_follow = 0;
  892.           if (sp_sw)
  893.         {        /* this is a check for a if, while, etc. with
  894.                    unbalanced parens */
  895.           sp_sw = false;
  896.           parse (hd_type);    /* dont lose the if, or whatever */
  897.         }
  898.         }
  899. #endif
  900.  
  901.       /* If we have a semicolon following an if, while, or for, and the
  902.          user wants us to, we should insert a space (to show that there
  903.          is a null statement there).  */
  904.       if (last_token_ends_sp && space_sp_semicolon)
  905.         {
  906.           *e_code++ = ' ';
  907.         }
  908.       *e_code++ = ';';
  909.       parser_state_tos->want_blank = true;
  910.       /* we are no longer in the middle of a stmt */
  911.       parser_state_tos->in_stmt = (parser_state_tos->p_l_follow > 0);
  912.  
  913.       if (!sp_sw)
  914.         {            /* if not if for (;;) */
  915.           parse (semicolon);/* let parser know about end of stmt */
  916.           force_nl = true;    /* force newline after a end of stmt */
  917.         }
  918.       break;
  919.  
  920.     case lbrace:        /* got a '{' */
  921.       parser_state_tos->in_stmt = false;    /* dont indent the {} */
  922.       if (!parser_state_tos->block_init)
  923.         force_nl = true;    /* force other stuff on same line as '{' onto
  924.                    new line */
  925.       else if (parser_state_tos->block_init_level <= 0)
  926.         parser_state_tos->block_init_level = 1;
  927.       else
  928.         parser_state_tos->block_init_level++;
  929.  
  930.       if (s_code != e_code && !parser_state_tos->block_init)
  931.         {
  932.           if (!btype_2)
  933.         {
  934.           dump_line ();
  935.           parser_state_tos->want_blank = false;
  936.         }
  937.           else
  938.         {
  939.           if (parser_state_tos->in_parameter_declaration
  940.               && !parser_state_tos->in_or_st)
  941.             {
  942.               parser_state_tos->i_l_follow = 0;
  943.               dump_line ();
  944.               parser_state_tos->want_blank = false;
  945.             }
  946.           else
  947.             parser_state_tos->want_blank = true;
  948.         }
  949.         }
  950.       if (parser_state_tos->in_parameter_declaration)
  951.         prefix_blankline_requested = 0;
  952.  
  953. #if 0    /* Changed to allow "{}" inside parens, as when
  954.        passed to a macro.  -jla */
  955.       if (parser_state_tos->p_l_follow > 0)
  956.         {            /* check for preceeding unbalanced parens */
  957.           diag (1, "Unbalanced parens", 0, 0);
  958.           parser_state_tos->p_l_follow = 0;
  959.           if (sp_sw)
  960.         {        /* check for unclosed if, for, etc. */
  961.           sp_sw = false;
  962.           parse (hd_type);
  963.           parser_state_tos->ind_level = parser_state_tos->i_l_follow;
  964.         }
  965.         }
  966. #endif
  967.       if (s_code == e_code)
  968.         parser_state_tos->ind_stmt = false;    /* dont put extra indentation
  969.                            on line with '{' */
  970.       if (parser_state_tos->in_decl && parser_state_tos->in_or_st)
  971.         {
  972.           /* This is a structure declaration.  */
  973.           if (parser_state_tos->dec_nest >= di_stack_alloc)
  974.         {
  975.           di_stack_alloc *= 2;
  976.           di_stack = (int *)
  977.             xrealloc ((char *) di_stack,
  978.                   di_stack_alloc * sizeof (*di_stack));
  979.         }
  980.           di_stack[parser_state_tos->dec_nest++] = dec_ind;
  981.           /* ?        dec_ind = 0; */
  982.         }
  983.       else
  984.         {
  985.           parser_state_tos->decl_on_line = false;    /* we cant be in the
  986.                                middle of a
  987.                                declaration, so dont
  988.                                do special
  989.                                indentation of
  990.                                comments */
  991.  
  992. #if 0                /* Doesn't work currently. */
  993.           if (blanklines_after_declarations_at_proctop
  994.           && parser_state_tos->in_parameter_declaration)
  995.         postfix_blankline_requested = 1;
  996. #endif
  997.           parser_state_tos->in_parameter_declaration = 0;
  998.         }
  999.       dec_ind = 0;
  1000.  
  1001.       /* We are no longer looking for an initializer or structure. Needed
  1002.          so that the '=' in "enum bar {a = 1" does not get interpreted as
  1003.          the start of an initializer.  */
  1004.       parser_state_tos->in_or_st = false;
  1005.  
  1006.       parse (lbrace);    /* let parser know about this */
  1007.       if (parser_state_tos->want_blank)    /* put a blank before '{' if
  1008.                            '{' is not at start of
  1009.                            line */
  1010.         *e_code++ = ' ';
  1011.       parser_state_tos->want_blank = false;
  1012.       *e_code++ = '{';
  1013.       parser_state_tos->just_saw_decl = 0;
  1014.       break;
  1015.  
  1016.     case rbrace:        /* got a '}' */
  1017.       /* semicolons can be omitted in declarations */
  1018.       if (parser_state_tos->p_stack[parser_state_tos->tos] == decl
  1019.           && !parser_state_tos->block_init)
  1020.         parse (semicolon);
  1021. #if 0    /* Changed to allow "{}" inside parens, as when
  1022.        passed to a macro.  -jla */
  1023.       if (parser_state_tos->p_l_follow)
  1024.         {            /* check for unclosed if, for, else. */
  1025.           diag (1, "Unbalanced parens", 0, 0);
  1026.           parser_state_tos->p_l_follow = 0;
  1027.           sp_sw = false;
  1028.         }
  1029. #endif
  1030.  
  1031.       parser_state_tos->just_saw_decl = 0;
  1032.       parser_state_tos->block_init_level--;
  1033.       if (s_code != e_code && !parser_state_tos->block_init)
  1034.         {            /* '}' must be first on line */
  1035.           if (verbose)
  1036.         diag (0, "Line broken", 0, 0);
  1037.           dump_line ();
  1038.         }
  1039.       *e_code++ = '}';
  1040.       parser_state_tos->want_blank = true;
  1041.       parser_state_tos->in_stmt = parser_state_tos->ind_stmt = false;
  1042.       if (parser_state_tos->dec_nest > 0)
  1043.         {            /* we are in multi-level structure
  1044.                    declaration */
  1045.           dec_ind = di_stack[--parser_state_tos->dec_nest];
  1046.           if (parser_state_tos->dec_nest == 0
  1047.           && !parser_state_tos->in_parameter_declaration)
  1048.         parser_state_tos->just_saw_decl = 2;
  1049.           parser_state_tos->in_decl = true;
  1050.         }
  1051.       prefix_blankline_requested = 0;
  1052.       parse (rbrace);    /* let parser know about this */
  1053.       parser_state_tos->search_brace
  1054.         = (cuddle_else
  1055.          && parser_state_tos->p_stack[parser_state_tos->tos] == ifhead);
  1056.  
  1057.       if ((parser_state_tos->p_stack[parser_state_tos->tos] == stmtl
  1058.            && parser_state_tos->last_rw != rw_struct_like)
  1059.           || (parser_state_tos->p_stack[parser_state_tos->tos] == ifhead)
  1060.           || (parser_state_tos->p_stack[parser_state_tos->tos] == dohead
  1061.           && !btype_2))
  1062.         force_nl = true;
  1063.       else if (parser_state_tos->tos <= 1
  1064.            && blanklines_after_procs
  1065.            && parser_state_tos->dec_nest <= 0)
  1066.         postfix_blankline_requested = 1;
  1067.  
  1068. #if 0
  1069.       parser_state_tos->search_brace
  1070.         = (cuddle_else
  1071.            && parser_state_tos->p_stack[parser_state_tos->tos] == ifhead
  1072.            && (parser_state_tos->il[parser_state_tos->tos]
  1073.            >= parser_state_tos->ind_level));
  1074. #endif
  1075.  
  1076.       break;
  1077.  
  1078.     case swstmt:        /* got keyword "switch" */
  1079.       sp_sw = true;
  1080.       hd_type = swstmt;    /* keep this for when we have seen the
  1081.                    expression */
  1082.       parser_state_tos->in_decl = false;
  1083.       goto copy_id;        /* go move the token into buffer */
  1084.  
  1085.     case sp_paren:        /* token is if, while, for */
  1086.       sp_sw = true;        /* the interesting stuff is done after the
  1087.                    expression is scanned */
  1088.       hd_type = (*token == 'i' ? ifstmt :
  1089.              (*token == 'w' ? whilestmt : forstmt));
  1090.  
  1091.       /* remember the type of header for later use by parser */
  1092.       goto copy_id;        /* copy the token into line */
  1093.  
  1094.     case sp_nparen:    /* got else, do */
  1095.       parser_state_tos->in_stmt = false;
  1096.       if (*token == 'e')
  1097.         {
  1098.           if (e_code != s_code && (!cuddle_else || e_code[-1] != '}'))
  1099.         {
  1100.           if (verbose)
  1101.             diag (0, "Line broken", 0, 0);
  1102.           dump_line ();    /* make sure this starts a line */
  1103.           parser_state_tos->want_blank = false;
  1104.         }
  1105.           force_nl = true;    /* also, following stuff must go onto new
  1106.                    line */
  1107.           last_else = 1;
  1108.           parse (elselit);
  1109.         }
  1110.       else
  1111.         {
  1112.           if (e_code != s_code)
  1113.         {        /* make sure this starts a line */
  1114.           if (verbose)
  1115.             diag (0, "Line broken", 0, 0);
  1116.           dump_line ();
  1117.           parser_state_tos->want_blank = false;
  1118.         }
  1119.           force_nl = true;    /* also, following stuff must go onto new
  1120.                    line */
  1121.           last_else = 0;
  1122.           parse (dolit);
  1123.         }
  1124.       goto copy_id;        /* move the token into line */
  1125.  
  1126.     case decl:        /* we have a declaration type (int, register,
  1127.                    etc.) */
  1128.  
  1129.       if (! parser_state_tos->sizeof_mask)
  1130.         parse (decl);
  1131.  
  1132.       if (parser_state_tos->last_token == rparen
  1133.           && parser_state_tos->tos <= 1)
  1134.         {
  1135.           parser_state_tos->in_parameter_declaration = 1;
  1136.           if (s_code != e_code)
  1137.         {
  1138.           dump_line ();
  1139.           parser_state_tos->want_blank = false;
  1140.         }
  1141.         }
  1142.       if (parser_state_tos->in_parameter_declaration
  1143.           && indent_parameters
  1144.           && parser_state_tos->dec_nest == 0
  1145.           && parser_state_tos->p_l_follow == 0)
  1146.         {
  1147.           parser_state_tos->ind_level
  1148.         = parser_state_tos->i_l_follow = indent_parameters;
  1149.           parser_state_tos->ind_stmt = 0;
  1150.         }
  1151.  
  1152.       /* in_or_st set for struct or initialization decl. Don't set it if
  1153.          we're in ansi prototype */
  1154.       if (!parser_state_tos->paren_depth)
  1155.         parser_state_tos->in_or_st = true;
  1156.  
  1157.       parser_state_tos->in_decl = parser_state_tos->decl_on_line = true;
  1158. #if 0
  1159.       if (!parser_state_tos->in_or_st && parser_state_tos->dec_nest <= 0)
  1160. #endif
  1161.         if (parser_state_tos->dec_nest <= 0)
  1162.           parser_state_tos->just_saw_decl = 2;
  1163.       if (prefix_blankline_requested
  1164.           && (parser_state_tos->block_init != 0
  1165.           || parser_state_tos->block_init_level != -1
  1166.           || parser_state_tos->last_token != rbrace
  1167.           || e_code != s_code
  1168.           || e_lab != s_lab
  1169.           || e_com != s_com))
  1170.         prefix_blankline_requested = 0;
  1171.       i = token_end - token + 1;    /* get length of token plus 1 */
  1172.  
  1173.       /* dec_ind = e_code - s_code + (parser_state_tos->decl_indent>i ?
  1174.          parser_state_tos->decl_indent : i); */
  1175.       dec_ind = decl_indent > 0 ? decl_indent : i;
  1176.       goto copy_id;
  1177.  
  1178.     case ident:        /* got an identifier or constant */
  1179.       /* If we are in a declaration, we must indent identifier. But not
  1180.          inside the parentheses of an ANSI function declaration.  */
  1181.       if (parser_state_tos->in_decl
  1182.           && parser_state_tos->p_l_follow == 0
  1183.           && parser_state_tos->last_token != rbrace)
  1184.         {
  1185.           if (parser_state_tos->want_blank)
  1186.         *e_code++ = ' ';
  1187.           parser_state_tos->want_blank = false;
  1188.           if (is_procname == 0 || !procnames_start_line)
  1189.         {
  1190.           if (!parser_state_tos->block_init)
  1191.             if (troff && !parser_state_tos->dumped_decl_indent)
  1192.               {
  1193.             sprintf (e_code, "\n.De %dp+\200p\n",
  1194.                  (int) (dec_ind * 7));
  1195.             parser_state_tos->dumped_decl_indent = 1;
  1196.             e_code += strlen (e_code);
  1197.               }
  1198.             else
  1199.               while ((e_code - s_code) < dec_ind)
  1200.             {
  1201.               CHECK_CODE_SIZE;
  1202.               *e_code++ = ' ';
  1203.             }
  1204.         }
  1205.           else
  1206.         {
  1207.           if (dec_ind && s_code != e_code)
  1208.             dump_line ();
  1209.           dec_ind = 0;
  1210.           parser_state_tos->want_blank = false;
  1211.         }
  1212.         }
  1213.       else if (sp_sw && parser_state_tos->p_l_follow == 0)
  1214.         {
  1215.           sp_sw = false;
  1216.           force_nl = true;
  1217.           parser_state_tos->last_u_d = true;
  1218.           parser_state_tos->in_stmt = false;
  1219.           parse (hd_type);
  1220.         }
  1221.     copy_id:
  1222.       if (parser_state_tos->want_blank)
  1223.         *e_code++ = ' ';
  1224.       if (troff && parser_state_tos->its_a_keyword)
  1225.         {
  1226.           e_code = chfont (&bodyf, &keywordf, e_code);
  1227.           for (t_ptr = token; t_ptr < token_end; ++t_ptr)
  1228.         {
  1229.           CHECK_CODE_SIZE;
  1230.           *e_code++ = keywordf.allcaps && islower (*t_ptr)
  1231.             ? toupper (*t_ptr) : *t_ptr;
  1232.         }
  1233.           e_code = chfont (&keywordf, &bodyf, e_code);
  1234.         }
  1235.       else
  1236.         {
  1237.           /* Troff mode requires that strings be processed specially.  */
  1238.           if (troff && (*token == '"' || *token == '\''))
  1239.         {
  1240.           char qchar;
  1241.  
  1242.           qchar = *token;
  1243.           *e_code++ = '`';
  1244.           if (qchar == '"')
  1245.             *e_code++ = '`';
  1246.           e_code = chfont (&bodyf, &stringf, e_code);
  1247.  
  1248.           t_ptr = token + 1;
  1249.           while (t_ptr < token_end)
  1250.             {
  1251.               *e_code = *t_ptr++;
  1252.               if (*e_code == '\\')
  1253.             {
  1254.               *++e_code = '\\';
  1255.               if (*t_ptr == '\\')
  1256.                 *++e_code = '\\';
  1257.               /* Copy char after backslash.  */
  1258.               *++e_code = *t_ptr++;
  1259.               /* Point after the last char we copied.  */
  1260.               e_code++;
  1261.             }
  1262.             }
  1263.           e_code = chfont (&stringf, &bodyf, e_code - 1);
  1264.           if (qchar == '"')
  1265.             *e_code++ = '\'';
  1266.         }
  1267.           else
  1268.         for (t_ptr = token; t_ptr < token_end; ++t_ptr)
  1269.           {
  1270.             CHECK_CODE_SIZE;
  1271.             *e_code++ = *t_ptr;
  1272.           }
  1273.         }
  1274.       parser_state_tos->want_blank = true;
  1275.  
  1276.       /* If the token is va_dcl, it appears without a semicolon, so we
  1277.          need to pretend that one was there.  */
  1278.       if ((token_end - token) == 6
  1279.           && strncmp (token, "va_dcl", 6) == 0)
  1280.         {
  1281.           parser_state_tos->in_or_st = false;
  1282.           parser_state_tos->just_saw_decl--;
  1283.           parser_state_tos->in_decl = 0;
  1284.           parse (semicolon);
  1285.           force_nl = true;
  1286.         }
  1287.       break;
  1288.  
  1289.     case period:        /* treat a period kind of like a binary
  1290.                    operation */
  1291.       *e_code++ = '.';    /* move the period into line */
  1292.       parser_state_tos->want_blank = false;    /* dont put a blank after a
  1293.                            period */
  1294.       break;
  1295.  
  1296.     case comma:
  1297.       /* only put blank after comma if comma does not start the line */
  1298.       parser_state_tos->want_blank = (s_code != e_code);
  1299.       if (parser_state_tos->paren_depth == 0
  1300.           && parser_state_tos->in_decl
  1301.           && is_procname == 0
  1302.           && !parser_state_tos->block_init)
  1303.         while ((e_code - s_code) < (dec_ind - 1))
  1304.           {
  1305.         CHECK_CODE_SIZE;
  1306.         *e_code++ = ' ';
  1307.           }
  1308.  
  1309.       *e_code++ = ',';
  1310.       if (parser_state_tos->p_l_follow == 0)
  1311.         {
  1312.           if (parser_state_tos->block_init_level <= 0)
  1313.         parser_state_tos->block_init = 0;
  1314.           /* If we are in a declaration, and either the user wants all
  1315.              comma'd declarations broken, or the line is getting too
  1316.              long, break the line.  */
  1317.           if (break_comma &&
  1318.           (!leave_comma
  1319.            || (compute_code_target () + (e_code - s_code)
  1320.                > max_col - tabsize)))
  1321.         force_nl = true;
  1322.         }
  1323.       break;
  1324.  
  1325.     case preesc:        /* got the character '#' */
  1326.       if ((s_com != e_com) ||
  1327.           (s_lab != e_lab) ||
  1328.           (s_code != e_code))
  1329.         dump_line ();
  1330.       {
  1331.         int in_comment = 0;
  1332.         int in_cplus_comment = 0;
  1333.         int com_start = 0;
  1334.         char quote = 0;
  1335.         int com_end = 0;
  1336.  
  1337.         /* ANSI allows spaces between '#' and preprocessor directives.
  1338.            Remove such spaces unless user has specified "-lps", in
  1339.            which case also leave any space preceeding the '#'. */
  1340.         if (leave_preproc_space)
  1341.           {
  1342.         char *p = cur_line;
  1343.         while (p < buf_ptr)
  1344.           *e_lab++ = *p++;
  1345.  
  1346.         while (*buf_ptr == ' ' || *buf_ptr == TAB)
  1347.           {
  1348.             *e_lab++ = *buf_ptr++;
  1349.             if (buf_ptr >= buf_end)
  1350.               fill_buffer ();
  1351.           }
  1352.           }
  1353.         else
  1354.           {
  1355.         *e_lab++ = '#';
  1356.         while (*buf_ptr == ' ' || *buf_ptr == TAB)
  1357.           if (++buf_ptr >= buf_end)
  1358.             fill_buffer ();
  1359.           }
  1360.  
  1361.         while (*buf_ptr != EOL || (in_comment && !had_eof))
  1362.           {
  1363.         CHECK_LAB_SIZE;
  1364.         *e_lab = *buf_ptr++;
  1365.         if (buf_ptr >= buf_end)
  1366.           fill_buffer ();
  1367.         switch (*e_lab++)
  1368.           {
  1369.           case BACKSLASH:
  1370.             if (troff)
  1371.               *e_lab++ = BACKSLASH;
  1372.             if (!in_comment && !in_cplus_comment)
  1373.               {
  1374.             *e_lab++ = *buf_ptr++;
  1375.             if (buf_ptr >= buf_end)
  1376.               fill_buffer ();
  1377.               }
  1378.             break;
  1379.           case '/':
  1380.             if ((*buf_ptr == '*' || *buf_ptr == '/')
  1381.             && !in_comment && !in_cplus_comment && !quote)
  1382.               {
  1383.             if (*buf_ptr == '/')
  1384.               in_cplus_comment = 1;
  1385.             else
  1386.               in_comment = 1;
  1387.             *e_lab++ = *buf_ptr++;
  1388.             com_start = e_lab - s_lab - 2;
  1389.               }
  1390.             break;
  1391.           case '"':
  1392.             if (quote == '"')
  1393.               quote = 0;
  1394.             break;
  1395.           case '\'':
  1396.             if (quote == '\'')
  1397.               quote = 0;
  1398.             break;
  1399.           case '*':
  1400.             if (*buf_ptr == '/' && in_comment)
  1401.               {
  1402.             in_comment = 0;
  1403.             *e_lab++ = *buf_ptr++;
  1404.             com_end = e_lab - s_lab;
  1405.               }
  1406.             break;
  1407.           }
  1408.           }
  1409.  
  1410.         while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == TAB))
  1411.           e_lab--;
  1412.  
  1413.         if (in_cplus_comment)
  1414.           {
  1415.         in_cplus_comment = 0;
  1416.         *e_lab++ = *buf_ptr++;
  1417.         com_end = e_lab - s_lab;
  1418.           }
  1419.  
  1420.         if (e_lab - s_lab == com_end && bp_save == 0)
  1421.           {            /* comment on preprocessor line */
  1422.         if (save_com.end != save_com.ptr)
  1423.           {
  1424.             need_chars (save_com, 2);
  1425.             *save_com.end++ = EOL;    /* add newline between
  1426.                            comments */
  1427.             *save_com.end++ = ' ';
  1428.             --line_no;
  1429.           }
  1430.         need_chars (save_com, com_end - com_start);
  1431.         strncpy (save_com.end, s_lab + com_start,
  1432.              com_end - com_start);
  1433.         save_com.end += com_end - com_start;
  1434.  
  1435.         e_lab = s_lab + com_start;
  1436.         while (e_lab > s_lab
  1437.                && (e_lab[-1] == ' ' || e_lab[-1] == TAB))
  1438.           e_lab--;
  1439.         bp_save = buf_ptr;    /* save current input buffer */
  1440.         be_save = buf_end;
  1441.         buf_ptr = save_com.ptr;    /* fix so that subsequent calls to
  1442.                        lexi will take tokens out of
  1443.                        save_com */
  1444.         need_chars (save_com, 1);
  1445.         *save_com.end++ = ' ';    /* add trailing blank, just in case */
  1446.         buf_end = save_com.end;
  1447.         save_com.end = save_com.ptr;    /* make save_com empty */
  1448.           }
  1449.         *e_lab = '\0';    /* null terminate line */
  1450.         parser_state_tos->pcase = false;
  1451.       }
  1452.  
  1453.       if (strncmp (s_lab + 1, "if", 2) == 0)
  1454.         {
  1455.           if (blanklines_around_conditional_compilation)
  1456.         {
  1457.           register c;
  1458.           prefix_blankline_requested++;
  1459.           while ((c = *in_prog_pos++) == EOL);
  1460.           in_prog_pos--;
  1461.         }
  1462.           {
  1463.         /* Push a copy of the parser_state onto the stack. All
  1464.            manipulations will use the copy at the top of stack, and
  1465.            then we can return to the previous state by popping the
  1466.            stack.  */
  1467.         struct parser_state *new;
  1468.  
  1469.         new = (struct parser_state *)
  1470.           xmalloc (sizeof (struct parser_state));
  1471.         memcpy (new, parser_state_tos, sizeof (struct parser_state));
  1472.  
  1473.         /* We need to copy the dynamically allocated arrays in the
  1474.            struct parser_state too.  */
  1475.         new->p_stack = (enum codes *)
  1476.           xmalloc (parser_state_tos->p_stack_size
  1477.                * sizeof (enum codes));
  1478.         memcpy (new->p_stack, parser_state_tos->p_stack,
  1479.               parser_state_tos->p_stack_size * sizeof (enum codes));
  1480.  
  1481.         new->il = (int *)
  1482.           xmalloc (parser_state_tos->p_stack_size * sizeof (int));
  1483.         memcpy (new->il, parser_state_tos->il,
  1484.             parser_state_tos->p_stack_size * sizeof (int));
  1485.  
  1486.         new->cstk = (int *)
  1487.           xmalloc (parser_state_tos->p_stack_size
  1488.                * sizeof (int));
  1489.         memcpy (new->cstk, parser_state_tos->cstk,
  1490.             parser_state_tos->p_stack_size * sizeof (int));
  1491.  
  1492.         new->paren_indents = (short *) xmalloc
  1493.           (parser_state_tos->paren_indents_size * sizeof (short));
  1494.         memcpy (new->paren_indents, parser_state_tos->paren_indents,
  1495.              parser_state_tos->paren_indents_size * sizeof (short));
  1496.  
  1497.         new->next = parser_state_tos;
  1498.         parser_state_tos = new;
  1499.           }
  1500.         }
  1501.       else if (strncmp (s_lab + 1, "else", 4) == 0)
  1502.         {
  1503.           /* When we get #else, we want to restore the parser state to
  1504.              what it was before the matching #if, so that things get
  1505.              lined up with the code before the #if.  However, we do not
  1506.              want to pop the stack; we just want to copy the second to
  1507.              top elt of the stack because when we encounter the #endif,
  1508.              it will pop the stack.  */
  1509.           else_or_endif = true;
  1510.           if (parser_state_tos->next)
  1511.         {
  1512.           /* First save the addresses of the arrays for the top of
  1513.              stack.  */
  1514.           enum codes *tos_p_stack = parser_state_tos->p_stack;
  1515.           int *tos_il = parser_state_tos->il;
  1516.           int *tos_cstk = parser_state_tos->cstk;
  1517.           short *tos_paren_indents =
  1518.           parser_state_tos->paren_indents;
  1519.           struct parser_state *second =
  1520.           parser_state_tos->next;
  1521.  
  1522.           memcpy (parser_state_tos, second,
  1523.               sizeof (struct parser_state));
  1524.           parser_state_tos->next = second;
  1525.  
  1526.           /* Now copy the arrays from the second to top of stack to
  1527.              the top of stack.  */
  1528.           /* Since the p_stack, etc. arrays only grow, never shrink,
  1529.              we know that they will be big enough to fit the array
  1530.              from the second to top of stack.  */
  1531.           parser_state_tos->p_stack = tos_p_stack;
  1532.           memcpy (parser_state_tos->p_stack,
  1533.               parser_state_tos->next->p_stack,
  1534.               parser_state_tos->p_stack_size
  1535.               * sizeof (enum codes));
  1536.  
  1537.           parser_state_tos->il = tos_il;
  1538.           memcpy (parser_state_tos->il,
  1539.               parser_state_tos->next->il,
  1540.               parser_state_tos->p_stack_size * sizeof (int));
  1541.  
  1542.           parser_state_tos->cstk = tos_cstk;
  1543.           memcpy (parser_state_tos->cstk,
  1544.               parser_state_tos->next->cstk,
  1545.               parser_state_tos->p_stack_size * sizeof (int));
  1546.  
  1547.           parser_state_tos->paren_indents = tos_paren_indents;
  1548.           memcpy (parser_state_tos->paren_indents,
  1549.               parser_state_tos->next->paren_indents,
  1550.               parser_state_tos->paren_indents_size
  1551.               * sizeof (short));
  1552.         }
  1553.           else
  1554.         diag (1, "Unmatched #else", 0, 0);
  1555.         }
  1556.       else if (strncmp (s_lab + 1, "endif", 5) == 0)
  1557.         {
  1558.           else_or_endif = true;
  1559.           /* We want to remove the second to top elt on the stack, which
  1560.              was put there by #if and was used to restore the stack at
  1561.              the #else (if there was one). We want to leave the top of
  1562.              stack unmolested so that the state which we have been using
  1563.              is unchanged.  */
  1564.           if (parser_state_tos->next)
  1565.         {
  1566.           struct parser_state *second = parser_state_tos->next;
  1567.  
  1568.           parser_state_tos->next = second->next;
  1569.           free (second->p_stack);
  1570.           free (second->il);
  1571.           free (second->cstk);
  1572.           free (second->paren_indents);
  1573.           free (second);
  1574.         }
  1575.           else
  1576.         diag (1, "Unmatched #endif", 0, 0);
  1577.           if (blanklines_around_conditional_compilation)
  1578.         {
  1579.           postfix_blankline_requested++;
  1580.           n_real_blanklines = 0;
  1581.         }
  1582.         }
  1583.  
  1584.       /* Normally, subsequent processing of the newline character
  1585.          causes the line to be printed.  The following clause handles
  1586.          a special case (comma-separated declarations separated
  1587.          by the preprocessor lines) where this doesn't happen. */
  1588.       if (parser_state_tos->last_token == comma
  1589.           && parser_state_tos->p_l_follow <= 0
  1590.           && leave_comma && !parser_state_tos->block_init
  1591.           && break_comma && s_com == e_com)
  1592.         {
  1593.           dump_line ();
  1594.           parser_state_tos->want_blank = false;
  1595.         }
  1596.       break;
  1597.  
  1598.       /* A C or C++ comment. */
  1599.     case comment:
  1600.     case cplus_comment:
  1601.       if (flushed_nl)
  1602.         {
  1603.           flushed_nl = false;
  1604.           dump_line ();
  1605.           parser_state_tos->want_blank = false;
  1606.           force_nl = false;
  1607.         }
  1608.       print_comment ();
  1609.       break;
  1610.     }            /* end of big switch stmt */
  1611.  
  1612.       *e_code = '\0';        /* make sure code section is null terminated */
  1613.       if (type_code != comment
  1614.       && type_code != cplus_comment
  1615.       && type_code != newline
  1616.       && type_code != preesc
  1617.       && type_code != form_feed)
  1618.     parser_state_tos->last_token = type_code;
  1619.  
  1620.     }                /* end of main while (1) loop */
  1621. }
  1622.  
  1623.  
  1624.  
  1625. char *set_profile ();
  1626. void set_defaults ();
  1627. int set_option ();
  1628.  
  1629. /* Points to current input file */
  1630. char *in_name = 0;
  1631.  
  1632. /* Points to the name of the output file */
  1633. char *out_name = 0;
  1634.  
  1635. /* How many input files were specified */
  1636. int input_files;
  1637.  
  1638. /* Names of all input files */
  1639. char **in_file_names;
  1640.  
  1641. /* Initial number of input filenames to allocate. */
  1642. int max_input_files = 128;
  1643.  
  1644.  
  1645. #ifdef DEBUG
  1646. int debug;
  1647. #endif
  1648.  
  1649. main (argc, argv)
  1650.      int argc;
  1651.      char **argv;
  1652. {
  1653.   register int i;
  1654.   struct file_buffer *current_input;
  1655.   char *profile_pathname = 0;
  1656.   int using_stdin = false;
  1657. #ifdef AMIGA
  1658.   int ex_err;
  1659.   int close_arp();
  1660. #endif /* AMIGA */
  1661.  
  1662. #ifdef DEBUG
  1663.   if (debug)
  1664.     debug_init ();
  1665. #endif
  1666.  
  1667. #ifdef AMIGA
  1668.   ArpBase = (struct ArpBase *) OpenLibrary("arp.library",39);
  1669.   if (ArpBase != NULL)
  1670.     if(!onexit(close_arp))
  1671.       {
  1672.         fprintf (stderr, "Couldn't initialize properly\n");
  1673.         exit (20);
  1674.       }
  1675.  
  1676.   if (argc == 2 && stricmp (argv[1],"-h") == 0)
  1677.     {
  1678.       usage ();
  1679.       exit (0);
  1680.     }
  1681.  
  1682.   if (ArpBase != NULL)
  1683.     {
  1684.       if ((ex_err = expand_args (&argc, &argv)) == 0)
  1685.         {
  1686.           fprintf (stderr, "Couldn't expand wildcards\n");
  1687.           exit (20);
  1688.         }
  1689.       if (ex_err == 2)
  1690.         {
  1691.           fprintf (stderr, "Wildcards didn't match a file\n");
  1692.           exit (5);
  1693.         }
  1694.     }
  1695. #endif /* AMIGA */
  1696.  
  1697.   init_parser ();
  1698.   initialize_backups ();
  1699.  
  1700.   output = 0;
  1701.   input_files = 0;
  1702.   in_file_names = (char **) xmalloc (max_input_files * sizeof (char *));
  1703.  
  1704.   set_defaults ();
  1705.   for (i = 1; i < argc; ++i)
  1706.     if (strcmp (argv[i], "-npro") == 0
  1707.     || strcmp (argv[i], "--ignore-profile") == 0
  1708.     || strcmp (argv[i], "+ignore-profile") == 0)
  1709.       break;
  1710.   if (i >= argc)
  1711.     profile_pathname = set_profile ();
  1712.  
  1713.   for (i = 1; i < argc; ++i)
  1714.     {
  1715.       if (argv[i][0] != '-' && argv[i][0] != '+')    /* Filename */
  1716.     {
  1717.       if (expect_output_file == true)    /* Last arg was "-o" */
  1718.         {
  1719.           if (out_name != 0)
  1720.         {
  1721.           fprintf (stderr, "indent: only one output file (2nd was %s)\n", argv[i]);
  1722.           exit (1);
  1723.         }
  1724.  
  1725.           if (input_files > 1)
  1726.         {
  1727.           fprintf (stderr, "indent: only one input file when output file is specified\n");
  1728.           exit (1);
  1729.         }
  1730.  
  1731.           out_name = argv[i];
  1732.           expect_output_file = false;
  1733.           continue;
  1734.         }
  1735.       else
  1736.         {
  1737.           if (using_stdin)
  1738.         {
  1739.           fprintf (stderr, "indent: can't have filenames when specifying standard input\n");
  1740.           exit (1);
  1741.         }
  1742.  
  1743.           input_files++;
  1744.           if (input_files > 1)
  1745.         {
  1746.           if (out_name != 0)
  1747.             {
  1748.               fprintf (stderr, "indent: only one input file when output file is specified\n");
  1749.               exit (1);
  1750.             }
  1751.  
  1752.           if (use_stdout != 0)
  1753.             {
  1754.               fprintf (stderr, "indent: only one input file when stdout is used\n");
  1755.               exit (1);
  1756.             }
  1757.  
  1758.           if (input_files > max_input_files)
  1759.             {
  1760.               max_input_files = 2 * max_input_files;
  1761.               in_file_names
  1762.             = (char **) xrealloc ((char *) in_file_names,
  1763.                           (max_input_files
  1764.                            * sizeof (char *)));
  1765.             }
  1766.         }
  1767.  
  1768.           in_file_names[input_files - 1] = argv[i];
  1769.         }
  1770.     }
  1771.       else
  1772.     {
  1773.       /* '-' as filename means stdin. */
  1774.       if (argv[i][0] == '-' && argv[i][1] == '\0')
  1775.         {
  1776.           if (input_files > 0)
  1777.         {
  1778.           fprintf (stderr, "indent: can't have filenames when specifying standard input\n");
  1779.           exit (1);
  1780.         }
  1781.  
  1782.           using_stdin = true;
  1783.         }
  1784.       else
  1785.         i += set_option (argv[i], (i < argc ? argv[i + 1] : 0), 1);
  1786.     }
  1787.     }
  1788.  
  1789.   if (verbose && profile_pathname)
  1790.     fprintf (stderr, "Read profile %s\n", profile_pathname);
  1791.  
  1792.   if (input_files > 1)
  1793.     {
  1794.       /* When multiple input files are specified, make a backup copy
  1795.      and then output the indented code into the same filename. */
  1796.  
  1797.       for (i = 0; input_files; i++, input_files--)
  1798.     {
  1799. #ifdef AMIGA
  1800.           /* Reset line- and comment-count */
  1801.           out_lines = out_coms = 0;
  1802. #endif /* AMIGA */
  1803.       current_input = read_file (in_file_names[i]);
  1804.       in_name = out_name = in_file_names[i];
  1805. #ifdef AMIGA
  1806.           if (verbose)
  1807.             printf ("\n%s:\n", out_name);
  1808. #endif /* AMIGA */
  1809.       output = fopen (out_name, "w");
  1810.       if (output == 0)
  1811.         {
  1812.           fprintf (stderr, "indent: can't create %s\n", out_name);
  1813.           exit (1);
  1814.         }
  1815.  
  1816.       make_backup (current_input);
  1817.       reset_parser ();
  1818.       indent (current_input);
  1819.       if (fclose (output) != 0)
  1820.         sys_error (out_name);
  1821.     }
  1822.     }
  1823.   else
  1824.     {
  1825.       /* One input stream -- specified file, or stdin */
  1826.  
  1827.       if (input_files == 0 || using_stdin)
  1828.     {
  1829.       input_files = 1;
  1830.       in_file_names[0] = "Standard input";
  1831.       current_input = read_stdin ();
  1832.     }
  1833.       else
  1834.     /* 1 input file */
  1835.     {
  1836.       current_input = read_file (in_file_names[0]);
  1837.       if (!out_name && !use_stdout)
  1838.         {
  1839.           out_name = in_file_names[0];
  1840. #ifdef AMIGA
  1841.               if (verbose)
  1842.                 printf ("\n%s:\n", out_name);
  1843. #endif /* AMIGA */
  1844.           make_backup (current_input);
  1845.         }
  1846.     }
  1847.       in_name = in_file_names[0];
  1848.  
  1849.       /* Uset stdout if it was specified ("-st"), or neither input
  1850.          nor output file was specified, or we're doing troff. */
  1851.       if (use_stdout || !out_name || troff)
  1852.     output = stdout;
  1853.       else
  1854.     {
  1855.       output = fopen (out_name, "w");
  1856.       if (output == 0)
  1857.         {
  1858.           fprintf (stderr, "indent: can't create %s\n", out_name);
  1859.           exit (1);
  1860.         }
  1861.     }
  1862.  
  1863.       reset_parser ();
  1864.       indent (current_input);
  1865.     }
  1866.  
  1867.   exit (0);
  1868. }
  1869.  
  1870.  
  1871. #ifdef AMIGA
  1872. char *expand_next_file (pattern)
  1873.      char *pattern;
  1874. {
  1875.   long err;
  1876.   char *pathname;
  1877.   static struct AnchorPath *an = NULL;
  1878.  
  1879.   pathname = NULL;
  1880.   if (pattern == NULL)
  1881.     err = -1;
  1882.   else
  1883.     do
  1884.       {
  1885.         if (an == NULL)
  1886.           {
  1887.             an = malloc (sizeof (struct AnchorPath) + MAXPATH);
  1888.             memset (an, 0, sizeof (struct AnchorPath) + MAXPATH);
  1889.             an->ap_BreakBits = SIGBREAKF_CTRL_C;
  1890.             an->ap_StrLen = MAXPATH;
  1891.             an->ap_Flags = APF_DoWild;
  1892.             err = FindFirst (pattern, an);
  1893.           }
  1894.         else
  1895.           err = FindNext (an);
  1896.  
  1897.         /* Expand only files */
  1898.         if (an->ap_Info.fib_DirEntryType < 0)
  1899.           pathname = an->ap_Buf;
  1900.       } while (err == 0 && pathname == NULL);
  1901.  
  1902.   if (err)
  1903.     {
  1904.       FreeAnchorChain (an);
  1905.       free (an);
  1906.       an = NULL;
  1907.       return NULL;
  1908.     }
  1909.   else
  1910.     return pathname;
  1911. }
  1912.  
  1913.  
  1914. int
  1915. in_prev_args (arg, argv, argc)
  1916.      char *arg, **argv;
  1917.      int argc;
  1918. {
  1919.   int i, is_in_args;
  1920.  
  1921.   is_in_args = 0;
  1922.   for (i = 1; i < argc - 1; i++)
  1923.     if (strcmp (arg, argv[i]) == 0)
  1924.       is_in_args = 1;
  1925.   return is_in_args;
  1926. }
  1927.  
  1928.  
  1929. int
  1930. expand_args (oargc, oargv)
  1931.      int *oargc;
  1932.      char ***oargv;
  1933. {
  1934.   int i;
  1935.   char *str, **argv, buf[MAXPATH];
  1936.   int argc, no_match_at_all, num_matches, contains_wildcards;
  1937.  
  1938.   no_match_at_all = 1;
  1939.   contains_wildcards = 0;
  1940.   argc = 0;
  1941.   argv = malloc (MAXARGS * sizeof (char *));
  1942.   if (argv == NULL)
  1943.     return 0;
  1944.  
  1945.   argv[argc++] = (*oargv)[0];
  1946.   for (i = 1; i < *oargc; i++)
  1947.     {
  1948.       if (PreParse ((*oargv)[i], buf))
  1949.         {
  1950.           contains_wildcards = 1;
  1951.           num_matches = 0;
  1952.           while (str = expand_next_file ((*oargv)[i]))
  1953.             if (argc >= MAXARGS)
  1954.               {
  1955.                 expand_next_file (NULL);
  1956.                 return 0;
  1957.               }
  1958.             else
  1959.               {
  1960.                 /* Avoid duplicate entries */
  1961.                 if (!in_prev_args (str, argv, argc))
  1962.                   {
  1963.                     argv[argc++] = strdup (str);
  1964.                     num_matches++;
  1965.                   }
  1966.               }
  1967.           if (num_matches != 0)
  1968.             no_match_at_all = 0;
  1969.         }
  1970.       else
  1971.         if (argc >= MAXARGS)
  1972.           return 0;
  1973.         else
  1974.           {
  1975.             if ((*oargv)[i][0] != '-' && (*oargv)[i][0] != '+')
  1976.               /* Found a file with no wildcards */
  1977.               no_match_at_all = 0;
  1978.             if (!in_prev_args ((*oargv)[i], argv, argc))
  1979.               argv[argc++] = (*oargv)[i];
  1980.           }
  1981.     }
  1982.   *oargc = argc;
  1983.   *oargv = argv;
  1984.   if (no_match_at_all && contains_wildcards)
  1985.     return 2;
  1986.   else
  1987.     return 1;
  1988. }
  1989.  
  1990.  
  1991. int
  1992. close_arp(i)
  1993.      int i;
  1994. {
  1995.   if (ArpBase != NULL)
  1996.     CloseLibrary ((struct Library *) ArpBase);
  1997.   return (i);
  1998. }
  1999. #endif /* AMIGA */
  2000.