home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 345_01 / tlpprocf.c < prev    next >
C/C++ Source or Header  |  1989-07-10  |  17KB  |  656 lines

  1. /* TLPPROCF.C - "The Last Cross-referencer" - TLP Process Files routines*/
  2. /*    Last Modified:    07/02/89                                            */
  3.  
  4. /*
  5. ---------------------------------------------------------------------
  6. Copyright (c) 1987-1989, Eduard Schwan Programs [esp] - All rights reserved
  7. TLC (The Last C-Cross-Referencer) and TLP (same, but for Pascal) are
  8. Cross-Reference Generators crafted and shot into the Public Domain by
  9. Eduard Schwan.  The source code and executable program may be freely
  10. distributed as long as the copyright/author notices remain intact, and
  11. it is not used in part or whole as the basis of a commercial product.
  12. Any comments, bug-fixes, or enhancements are welcome.
  13. Also, if you find TLC and it's source code useful, a contribution of
  14. $20 (check/money order) is encouraged!  Hopefully we will all see more
  15. source code distributed!
  16.     Eduard Schwan, 1112 Oceanic Drive, Encinitas, Calif. 92024
  17. ---------------------------------------------------------------------
  18. */
  19.  
  20. /*
  21. HEADER:        The Last Cross-Referencer;
  22. TITLE:        TLC/TLP - The Last Cross-Referencer;
  23. VERSION:    1.01;
  24.  
  25. DESCRIPTION: "TLC/TLP.
  26.             TLP Process Files routines";
  27.  
  28. KEYWORDS:    Utility, Cross-reference, C, Pascal, Apple, Macintosh, APW, Aztec;
  29. SYSTEM:        Macintosh MPW, v3.0;
  30. FILENAME:    TLPPROCF.C;
  31. WARNINGS:    "Has not yet been ported to MS-DOS.
  32.             Shareware, $20 Check/Money Order suggested.";
  33.  
  34. SEE-ALSO:    README.TLC,TLCHELP.DOC,TLPHELP.DOC;
  35. AUTHORS:    Eduard Schwan;
  36. COMPILERS:    AZTEC C65 v3.2b, APPLEIIGS APW C v1.0, APPLE MACINTOSH MPW C v3.0;
  37. */
  38.  
  39. /*------------------------ include files -------------------------*/
  40.  
  41. #include    <stdio.h>
  42. #include    <errno.h>
  43. #include    "tlc.h"
  44.  
  45.  
  46. /*------------------------- definitions -------------------------*/
  47.  
  48. #define     PAGE_TITLE        "List"
  49.  
  50.  
  51. /*--------------------- external declarations --------------------*/
  52.  
  53. #include    "tlc.ext"
  54.  
  55. extern FILE *    open_text_file();
  56. extern VOID     close_text_file(),
  57.                 do_emphasis(),
  58.                 undo_emphasis(),
  59.                 do_form_feed(),
  60.                 indent(),
  61.                 check_user_abort(),
  62.                 new_page();
  63. extern boolean    is_resword();
  64. extern long        get_freemem();
  65.  
  66.  
  67. /*------------------------ static variables -----------------------*/
  68.  
  69. static    pos_int            out_line_number;
  70. static    pos_int            block_level;
  71. static    boolean         saw_id;
  72. static    pos_int            prev_ref_kind;/* messy way to do it..*/
  73.  
  74.  
  75. /*===============[ setup_listing_stuff ]================*/
  76.  
  77. static VOID setup_listing_stuff()
  78.  
  79.     { /* setup_listing_stuff() */
  80. debug(puts("setup_listing_stuff:");)
  81.     } /* setup_listing_stuff() */
  82.  
  83.  
  84.  
  85. /*===============[ print_listing_line ]================*/
  86.  
  87. static VOID print_listing_line()
  88.  
  89.     { /* print_listing_line() */
  90.  
  91.     if (out_line_number >= parm_rec.bot_line || out_line_number == 0)
  92.         new_page(parm_rec.do_listing, PAGE_TITLE, &out_page_number,
  93.                 &out_line_number, file_rec.curr_file->file_name);
  94.     if (ok_to_print())
  95.         {
  96. debug(printf("prntLstLn():outLn#=%d botLn=%d pg#=%d\n",\
  97. out_line_number,parm_rec.bot_line, out_page_number);)
  98.         indent();
  99.         fprintf(out_file,"%4d | %s", file_rec.curr_file->num_lines, curr_line);
  100.         fputc('\n', out_file);
  101.         }
  102.     out_line_number++;
  103.     } /* print_listing_line() */
  104.  
  105.  
  106.  
  107. /*===============[ finish_listing_stuff ]================*/
  108.  
  109. static VOID finish_listing_stuff()
  110.  
  111.     { /* finish_listing_stuff() */
  112.     if (ok_to_print() && !parm_rec.do_xref)
  113.         {
  114.         do_form_feed(out_file, out_line_number);
  115.         }
  116.     } /* finish_listing_stuff() */
  117.  
  118.  
  119.  
  120. /*==================[ expand_tabs ]=====================*/
  121.  
  122. static VOID expand_tabs()
  123.  
  124.     { /* expand_tabs() */
  125.     short         count;
  126.     short         index,
  127.                 tab_fill;
  128.     char *        line_ptr;
  129. /*
  130. debug(puts("expand_tabs:");)
  131. */
  132.     index = 0;
  133.     line_ptr = curr_line;
  134.     while (*line_ptr)
  135.         {
  136.         if (*line_ptr == '\t')    /* horizontal tab (HT)? */
  137.             {
  138.             /* calc. # of spaces to replace tab with */
  139.             tab_fill = parm_rec.tab_width - (index % parm_rec.tab_width);
  140.  
  141.             /* if more than 1 space needed for tab, move the string */
  142.             /* and trailing null (\0) over                            */
  143.             if (tab_fill > 1)
  144.                 {
  145. /****************MOVE(line_ptr+tab_fill-1, line, strlen(line_ptr)+1); -- below is less risky */
  146.                 for (count=strlen(line_ptr); count>=0; count--)
  147.                     line_ptr[count-1+tab_fill] = line_ptr[count];
  148.                 }
  149.  
  150.             /* pad with spaces (& cover up tab as last char) */
  151. /***********FILL(line_ptr, tab_fill, ' '); -- below is less risky */
  152.             for (count=0; count<tab_fill; count++)
  153.                 line_ptr[count] = ' ';
  154.  
  155.             /* point to next char. after tab expansion */
  156.             line_ptr    += tab_fill;
  157.             index        += tab_fill;
  158.             }
  159.         else
  160.             {
  161.             /* no conversion, skip this character */
  162.             line_ptr++;
  163.             index++;
  164.             }
  165.         } /* while */
  166.     } /* expand_tabs() */
  167.  
  168.  
  169.  
  170. /*=================[ do_directives ]====================*/
  171.  
  172. static boolean do_directives()
  173.  
  174.     { /* do_directives() */
  175.  
  176. debug(puts("do_directives:");)
  177.  
  178. return(FALSE); /* DEBUG..*/
  179.     } /* do_directives() */
  180.  
  181.  
  182.  
  183. /*==================[ fill_ref_recs ]===================*/
  184.  
  185. static VOID fill_ref_recs(sym_ptr, line_ptr, ref_kind)
  186. sym_list_type*    sym_ptr;
  187. line_list_type* line_ptr;
  188. pos_int         ref_kind;
  189.  
  190.     { /* fill_ref_recs() */
  191.  
  192.     /* fill symbol record */
  193.  
  194.     /* NOTE: the symbol's name is VERY temporarily stored in token.tok_string*/
  195.     /* and is "malloc'ed" & copied into heap later by add_sym_rec() if needed*/
  196.     sym_ptr->sym_name        = token.tok_string;
  197.     sym_ptr->sym_type        = token.tok_type;
  198.  
  199.     /* fill line record */
  200.  
  201.     line_ptr->line_number    = file_rec.curr_file->num_lines;
  202.     line_ptr->file_ptr        = file_rec.curr_file;
  203.     line_ptr->reference_type= ref_kind;
  204.     } /* fill_ref_recs() */
  205.  
  206.  
  207.  
  208. /*===================[ add_sym_rec ]====================*/
  209.  
  210. static sym_list_type* add_sym_rec(sym_ptr)
  211. sym_list_type*    sym_ptr;
  212.  
  213.     { /* add_sym_rec() */
  214.     sym_list_type*    new_sym_ptr;
  215.     char*            new_sym_name;
  216. /*
  217. debug(puts("add_sym_rec:");)
  218. */
  219.     /* create a new symbol record & move info into it */
  220.     new_sym_ptr = (sym_list_type*)malloc(sizeof(sym_list_type));
  221.  
  222. debug(printf("add_sym_rec:malloc(new_sym_ptr)-$%06lx[$%x]\n",\
  223. (long)new_sym_ptr,sizeof(sym_list_type));)
  224.  
  225.     if (new_sym_ptr==NULL)
  226.         {
  227.         fprintf(stderr,"Error! out of memory on line #%u in file '%s'\n",
  228.                 file_rec.curr_file->num_lines+1, file_rec.curr_file->file_name);
  229.         }
  230.     else
  231.         {
  232. #ifdef STRUCT_ASSIGN
  233.         *new_sym_ptr = *sym_ptr;
  234. #else
  235.         MOVEBYTE(sym_ptr, new_sym_ptr, sizeof(sym_list_type));
  236. #endif
  237.         new_sym_ptr->line_list    = NULL;
  238.         new_sym_ptr->line_tail    = NULL;
  239.         new_sym_ptr->left        = NULL;
  240.         new_sym_ptr->right        = NULL;
  241.         }
  242.  
  243.     /* create a place for the symbol name & move from temp area */
  244.  
  245.     if (new_sym_ptr!=NULL)
  246.         {
  247.         new_sym_name = malloc(strlen(new_sym_ptr->sym_name)+1);
  248.  
  249. debug(printf("add_line_rec:malloc(new_sym_name)-$%06lx[$%x]\n",\
  250. (long)new_sym_name,strlen(new_sym_ptr->sym_name)+1);)
  251.  
  252.         if (new_sym_name==NULL)
  253.             {
  254.             fprintf(stderr,"Error! out of memory on line #%u in file '%s'\n",
  255.                     file_rec.curr_file->num_lines+1, file_rec.curr_file->file_name);
  256.             }
  257.         else
  258.             {
  259.             strcpy(new_sym_name, sym_ptr->sym_name);
  260.             new_sym_ptr->sym_name = new_sym_name;
  261.             }
  262.         }
  263.  
  264.     /* return the pointer to the new record, or NULL if out of mem */
  265.  
  266.     return(new_sym_ptr);
  267.  
  268.     } /* add_sym_rec() */
  269.  
  270.  
  271. /*==================[ add_line_rec ]====================*/
  272.  
  273. static int add_line_rec(sym_ptr, line_ptr)
  274. sym_list_type*    sym_ptr;
  275. line_list_type* line_ptr;
  276.  
  277.     { /* add_line_rec() */
  278.     line_list_type* new_line_ptr;
  279.  
  280. debug(puts("add_line_rec:");)
  281.  
  282.     /* create new line ref. record on heap */
  283.     new_line_ptr = (line_list_type*)malloc(sizeof(line_list_type));
  284.  
  285. debug(printf("add_line_rec:malloc(new_line_ptr)-$%06lx[$%x]\n",\
  286. (long)new_line_ptr,sizeof(line_list_type));)
  287.  
  288.     if (new_line_ptr==NULL)
  289.         {
  290.         fprintf(stderr,"Error! out of memory on line #%u in file '%s'\n",
  291.                 file_rec.curr_file->num_lines+1, file_rec.curr_file->file_name);
  292.         return(BAD_EXIT);
  293.         }
  294. #ifdef STRUCT_ASSIGN
  295.     *new_line_ptr = *line_ptr;
  296. #else
  297.     MOVEBYTE(line_ptr, new_line_ptr, sizeof(line_list_type));
  298. #endif
  299.  
  300.     /* add line ref. record to symbol's list */
  301.     new_line_ptr->next = NULL;
  302.     if (sym_ptr->line_list == NULL)
  303.         { /* first on list */
  304. debug(puts("  1st linerec on list");)
  305.         sym_ptr->line_list = new_line_ptr;
  306.         sym_ptr->line_tail = new_line_ptr;
  307.         }
  308.     else
  309.         {
  310. debug(puts("  next linerec on list");)
  311.         sym_ptr->line_tail->next = new_line_ptr;
  312.         sym_ptr->line_tail = new_line_ptr;
  313.         }
  314.  
  315.     /* all ok */
  316.     return(GOOD_EXIT);
  317.  
  318.     } /* add_line_rec() */
  319.  
  320.  
  321.  
  322. /*==================[ add_reference ]===================*/
  323.  
  324. static int add_reference(sym_ptr, line_ptr)
  325. sym_list_type*    sym_ptr;
  326. line_list_type* line_ptr;
  327.  
  328.     { /* add_reference() */
  329.     boolean         found;
  330.     int                direction;
  331.     sym_list_type*    search_ptr;
  332.     sym_list_type*    trail_ptr;
  333.  
  334.     /* search for symbol or place to add symbol in symbol table */
  335.  
  336. /*debug(puts("add_ref:");)*/
  337.  
  338.     search_ptr = symbol_table.symbol_list;
  339.     found = FALSE;
  340.     trail_ptr = NULL; /* this will always point one above search_ptr(parent)*/
  341.     while (!found && search_ptr!=NULL)
  342.         {
  343.         trail_ptr = search_ptr;
  344.         direction = strncmp(search_ptr->sym_name, sym_ptr->sym_name,
  345.                             parm_rec.symbol_size);
  346.         if (direction < 0)
  347.             direction = -1;
  348.         else if (direction > 0)
  349.             direction = 1;
  350. /*
  351. debug(printf("add_ref:strncmp'%s'<%d>'%s'\n",\
  352. search_ptr->sym_name,direction,sym_ptr->sym_name);)
  353. */
  354.         switch (direction)
  355.             {
  356.             case  1: /* too big, descend left */
  357.                     search_ptr = search_ptr->left;
  358.                     break;
  359.             case  0: /* equal! got it. */
  360.                     found = TRUE;
  361.                     break;
  362.             case -1: /* too small, descend right */
  363.             default:
  364.                     search_ptr = search_ptr->right;
  365.                     break;
  366.             } /*switch*/
  367.         } /*while*/
  368.  
  369.     /* if not found, add new symbol record at trail_ptr */
  370.  
  371.     if (!found)
  372.         {
  373.         search_ptr = add_sym_rec(sym_ptr);
  374.         if (search_ptr==NULL)
  375.             return(BAD_EXIT); /* out of memory */
  376.         if (trail_ptr==NULL)
  377.             { /* first on the list */
  378. /*debug(puts(" 1st symrec on list");)*/
  379.             symbol_table.symbol_list = search_ptr;
  380.             }
  381.         else
  382.             { /* add to existing list */
  383. /*debug(puts(" next symrec on list");)     */
  384.             if (direction==1)
  385.                 trail_ptr->left = search_ptr; /* add as left node */
  386.             else
  387.                 trail_ptr->right= search_ptr; /* add as left node */
  388.             }
  389.         }
  390.  
  391.     /* now add line ref record to this symbol record */
  392.  
  393.     return( add_line_rec(search_ptr, line_ptr) );
  394.  
  395.     } /* add_reference() */
  396.  
  397.  
  398.  
  399. /*====================[ parse_line ]====================*/
  400.  
  401. static VOID parse_line(found_include)
  402. boolean * found_include; /* NOTE: not used yet - not doing includes */
  403.  
  404.     { /* parse_line */
  405.     int             error;
  406.     pos_int            ref_kind;
  407.     sym_list_type    temp_sym_rec;
  408.     line_list_type    temp_line_rec;
  409.  
  410.     do    {
  411.         error = get_token();
  412.         if (error)
  413.             { /* handle bad token or Eoln */
  414.             if (error != TERR_EOLN)
  415.                 { /* bad stuff in text file.. */
  416. debug(puts("UNKNOWN TOKEN");)
  417.                 }
  418.             }
  419.         else
  420.             { /* handle next valid token */
  421. /*
  422. debug(printf("parseLine():token=%d'%s'\n",\
  423. token.tok_type,token.tok_string);)
  424. */
  425.             switch (token.tok_type)
  426.                 {
  427.                 case TOK_ID:
  428.                         if (is_resword(token.tok_string))
  429.                             { /* handle reserved words.. */
  430.                             if (strcmp(token.tok_string, "function") == 0)
  431.                                 prev_ref_kind = REF_FUNCHEAD;
  432.                             else
  433.                             if (strcmp(token.tok_string, "procedure") == 0)
  434.                                 prev_ref_kind = REF_PROCHEAD;
  435.                             else
  436.                             if (strcmp(token.tok_string, "unit") == 0)
  437.                                 prev_ref_kind = REF_UNITHEAD;
  438.                             else
  439.                                 prev_ref_kind = REF_BLANK;
  440.                             }
  441.                         else
  442.                             { /* not reserved, add ref. to sym. table */
  443.                             fill_ref_recs(&temp_sym_rec,
  444.                                           &temp_line_rec,
  445.                                           prev_ref_kind);
  446.                             error = add_reference(&temp_sym_rec,
  447.                                                  &temp_line_rec);
  448.                             prev_ref_kind = REF_BLANK;
  449.                             }
  450.                         break;
  451.  
  452.                 case TOK_NCONST:
  453.                         if (parm_rec.xref_nums)
  454.                             {
  455.                             ref_kind = REF_BLANK;
  456.                             fill_ref_recs(&temp_sym_rec,
  457.                                           &temp_line_rec,
  458.                                           ref_kind);
  459.                             error = add_reference(&temp_sym_rec,
  460.                                                  &temp_line_rec);
  461.                             }
  462.                         prev_ref_kind = REF_BLANK;
  463.                         break;
  464.  
  465.                 case TOK_CCONST:
  466.                 case TOK_SCONST:
  467.                         if (parm_rec.xref_strings)
  468.                             {
  469.                             ref_kind = REF_BLANK;
  470.                             fill_ref_recs(&temp_sym_rec,
  471.                                           &temp_line_rec,
  472.                                           ref_kind);
  473.                             error = add_reference(&temp_sym_rec,
  474.                                                  &temp_line_rec);
  475.                             }
  476.                         prev_ref_kind = REF_BLANK;
  477.                         break;
  478.  
  479.                 default: /* ignore anything else.. */
  480.                     prev_ref_kind = REF_BLANK;
  481.                     break;
  482.  
  483.                 } /*switch*/
  484.             } /*else valid token*/
  485.         } while (token.tok_type != TERR_EOLN && !error);
  486.     } /* parse_line */
  487.  
  488.  
  489.  
  490. /*=================[ process_a_file ]===================*/
  491.  
  492. static boolean process_a_file()
  493.  
  494.     { /* process_a_file() */
  495.     int     error;
  496.     boolean found_include;
  497.     FILE *    fp;
  498.  
  499.     if (verbose)
  500.         {
  501.         putc('\n', stderr);
  502.         fprintf(stderr, memdispFmt, get_freemem());
  503.         fprintf(stderr, "Processing file '%s'\n", file_rec.curr_file->file_name);
  504.         fflush(stderr);
  505.         }
  506.  
  507.     block_level     = 0;
  508.     saw_id            = FALSE;
  509.     prev_ref_kind    = REF_BLANK;
  510.  
  511.     fp = open_text_file(file_rec.curr_file->file_name, "r", &error);
  512.     if (error)
  513.         {
  514.         fprintf(out_file, "Error %d/$%x opening file '%s'\n",
  515.                 error, error, file_rec.curr_file->file_name);
  516.         fprintf(stderr, "Error %d/$%x opening file '%s'\n",
  517.                 error, error, file_rec.curr_file->file_name);
  518.         fflush(stderr);
  519.         return(TRUE);
  520.         }
  521.     else
  522.         { /*opened ok*/
  523.         file_rec.curr_file->num_lines = 0;
  524.         found_include = FALSE;
  525.         while (!feof(fp) && !error)
  526.             {
  527.             /* check for user abort.. */
  528.             check_user_abort();
  529.  
  530.             /* read next line in file */
  531.             errno = 0;
  532.             if (fgets(curr_line, LINE_SIZE, fp) != NULL)
  533.                 {
  534.                 if (curr_line[strlen(curr_line)-1] == '\n')
  535.                     curr_line[strlen(curr_line)-1] = 0; /* remove trailing \n */
  536.                 file_rec.curr_file->num_lines++;
  537.                 expand_tabs();
  538.  
  539. debug(printf("process_a_file:<%d>'%s'\n",file_rec.curr_file->num_lines,curr_line););
  540.  
  541.                 /* if noisy, list file's current line number to screen */
  542.                 if (verbose > 1)
  543.                     {
  544.                     if (file_rec.curr_file->num_lines % 10 == 1)
  545.                         {
  546.                         if (file_rec.curr_file->num_lines % 100 == 1)
  547.                             {
  548.                             putc('\n', stderr);
  549.                             fprintf(stderr, memdispFmt, get_freemem());
  550.                             }
  551.                         fprintf(stderr,"%5d",file_rec.curr_file->num_lines-1);
  552.                         fflush(stderr);
  553.                         }
  554.                     }
  555.  
  556. /* don't parse if just listing (but need to later!) DEBUG */
  557.                 if (parm_rec.do_xref)
  558.                     parse_line(&found_include);
  559.  
  560.                 /* if we are listing, print this line */
  561. /*
  562. debug(printf("process_a_file:if(%d) then print'%s'\n",parm_rec.do_listing,curr_line););
  563. */
  564.                 if (parm_rec.do_listing)
  565.                     print_listing_line();
  566.  
  567.                 /* see if this line contains a NewPage command string */
  568.                 if (parm_rec.paging_string != NULL)
  569.                     if (strcmp(parm_rec.paging_string, curr_line)==0)
  570.                         new_page(parm_rec.do_listing,
  571.                                 PAGE_TITLE,
  572.                                 &out_page_number,
  573.                                 &out_line_number,
  574.                                 file_rec.curr_file->file_name);
  575.  
  576.                 /* handle include file */
  577.                 if (found_include && parm_rec.do_includes)
  578.                     { /* push current file & enter include file */
  579. /*----------------- later ---------------
  580.                     found_include = FALSE;
  581.                     push-current-file()
  582.                     open-include-file()
  583.                     include-level++
  584.                     init file stuff
  585.                     if (!top-of-page)
  586.                         new-page()
  587. ----------------------------------------*/
  588.                     }
  589.                 } /*if fgets()*/
  590.             else
  591.                 { /* error or eof */
  592.                 if (!feof(fp))
  593.                     {
  594.                     error = errno;
  595.                     fprintf(out_file,
  596.                             "Error %d/$%x reading line #%u in file '%s'\n",
  597.                             error, error, file_rec.curr_file->num_lines+1,
  598.                             file_rec.curr_file->file_name);
  599.                     fprintf(stderr,
  600.                             "Error %d/$%x reading line #%u in file '%s'\n",
  601.                             error, error, file_rec.curr_file->num_lines+1,
  602.                             file_rec.curr_file->file_name);
  603.                     fflush(stderr);
  604.                     return(TRUE);
  605.                     }
  606.                 } /* else error or eof */
  607. /*----------------- later ---------------
  608.             if (eof(fp) && !error)
  609.                 {
  610.                 if include-level > 0
  611.                     {
  612.                     pop-previous-file()
  613.                     seek back to it's next line
  614.                     }
  615.                 }
  616. ----------------------------------------*/
  617.             } /*while*/
  618.         close_text_file(fp, file_rec.curr_file->file_name);
  619.         } /*opened ok*/
  620.         
  621.         if (verbose)
  622.             putc('\n', stderr);
  623.             
  624.     return(FALSE); /* no abort */
  625.     } /* process_a_file() */
  626.  
  627.  
  628.  
  629. /*=================[ process_files ]===================*/
  630. VOID process_files()
  631.  
  632.     { /* process_files() */
  633.     boolean abort;
  634.  
  635. debug(puts("process_files:");)
  636.  
  637.     init_scanner(parm_rec.do_case_sens, parm_rec.do_underscores, FALSE);
  638.     file_rec.curr_file = file_rec.file_list;
  639.     abort             = FALSE;
  640.     out_page_number  = 0;
  641.     if (parm_rec.do_listing)
  642.         setup_listing_stuff();
  643.     while (file_rec.curr_file!=NULL && !abort)
  644.         {
  645.         out_line_number = 0;
  646.         abort = process_a_file();
  647.  
  648. /*IGNORE MISSING FILES FOR NOW..DEBUG*/ abort=FALSE;
  649.         file_rec.curr_file = file_rec.curr_file->next;
  650.         }
  651.         
  652.     if (parm_rec.do_listing)
  653.         finish_listing_stuff();
  654.         
  655.     } /* process_files() */
  656.