Starter Code for Lab 5 Plus Sample Output
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include "perry.h"

#define MAXIDENT 80
#define MAXLINE  256

typedef struct node NODE;
typedef struct line LINE;

struct line
{
   long  linenum;
   LINE *next;
};


struct node 
{
   char  *identifier;
   NODE  *left, *right;
   LINE  *front, *rear;
};


main(int argc, char *argv[])

/***************************************************************************/
/*                                                                         */
/*  This program reads a C program file as input, parses identifiers and   */
/*  places them in a binary tree.  Each tree node has an identifier,       */
/*  the usual "left" and "right" pointers to other tree nodes, and "front" */
/*  and "rear" pointers to a queue of line number nodes.  Line number      */
/*  nodes contain a line number where the identifier occurred and a, of    */
/*  course, a pointer to the next line number node.                        */
/*                                                                         */
/*  After the tree is formed, the user is prompted to see if he wants an   */
/*  alphabetized cross-reference listing (followed by the original source  */
/*  file with line numbers).  If so, such a file is created with a time    */
/*  stamp at its top.  Each line of the cross-reference shows an identi-   */
/*  fier followed by all lines where it can be found in the source file.   */
/*                                                                         */
/*  After this, the user is prompted for an identifier (until he types     */
/*  "quit program").  The program will then output all source lines (with  */
/*  line numbers in the leftmost column) containing that identifier. Thus, */
/*  the program allows interactive references to the source code.          */
/*                                                                         */
/***************************************************************************/

{
   NODE *tree = NULL;
   NODE *parse_file_into_ident_tree(FILE *infile);
   NODE *find_identifier(char *identifier, NODE *tree);
   void check_program_args(int argc, char *argv[],FILE **infile,FILE **outfile),
        printtree(NODE *tree, FILE *outfile),
        printprog(FILE *infile, FILE *outfile),
        print_time_stamp(FILE *outfile);
   FILE *infile, *outfile;

   check_program_args(argc, argv, &infile, &outfile);
   tree = parse_file_into_ident_tree(infile);
   print_time_stamp(outfile); 
   printtree(tree, outfile);   /* Prints cross-reference table. */
   printprog(infile, outfile); /* Prints input program with line numbers in
                                      left column. */
}



/***************************************************************************/
/*                                                                         */
/*  This function checks to see that a filename argument was supplied by   */
/*  the user when invoking this program.  It also makes sure that the      */
/*  filename is that of a C source file (name ends with .c) and that the   */
/*  source file exists.                                                    */
/*                                                                         */
/***************************************************************************/
void check_program_args(int argc, char *argv[], FILE **infile, FILE **outfile)
{
  int filename_len;

  if (argc > 3)
  {
       perror("Wrong number of command line arguments!");
       exit(1);
  }

  filename_len = strlen(argv[1]);
  if (argv[1][filename_len - 1] != 'c' || argv[1][filename_len - 2] != '.')
  {
     printf("C source file names must end with \".c\".  Aborting!\n\n");
     exit(1);
  }

  *infile  = Fopen(argv[1],"r");
  *outfile = Fopen(argv[2],"w");
}
/*************************************************************************/
/*                                                                       */
/*  THIS IS THE MOST IMPORTANT FUNCTION IN THE PROGRAM.  It reads the    */
/*  input file byte-by-byte.  If a byte starts a quoted string or        */
/*  comment, a function is called to read until the end of the quoted    */
/*  string or comment.  If a newline is encountered, the byte offset of  */
/*  the start of the next line is registered in the array "offsets".     */
/*  If the beginning of an identifier is found, the identifier is com-   */
/*  pleted and its name is placed in the identifier tree (if it is new). */
/*  If the identifier is already in the tree, the line number where the  */
/*  identifier was encountered is added to the line number queue which   */
/*  is attached to each node of the identifier tree.                     */
/*                                                                       */
/*************************************************************************/
NODE *parse_file_into_ident_tree(FILE *infile)
{
  long linenum = 1;
  int c, noreadflag = 0;
  char identifier[MAXIDENT], line[MAXLINE];
  NODE *tree = NULL;
  void get_ident(int *lastchar, char *ident, FILE *infile), 
       insert(char *ident, long linenum, NODE **tree);
  long find_close_comment(long linenum,  FILE *infile),
       find_close_quote(char c, long linenum, FILE *infile);

  while ( noreadflag || (c = getc(infile)) != EOF)
  {
       noreadflag = 0;
       switch (c)
       {
          case '\'':
          case '"' :
                       linenum = find_close_quote(c, linenum, infile);
                       break;
          case '/' :
                       c = getc(infile);
                       if ( c == '*') linenum = find_close_comment(linenum,
                                                                   infile);
                       else noreadflag = 1; 
                       break;
          case '\n':
                       linenum++;
                       break;
          default: 
                       if (isalpha(c) || c == '_') 
                       {
                          get_ident(&c,identifier, infile);
                          insert(identifier,linenum,&tree);
                          if (strcmp(identifier,"include") == 0)
                          {
                            fgets(line,MAXLINE,infile);/* Ignore rest of line */
                            linenum++;
                          }
                          else noreadflag = 1; /* Analyze char after ident */
                       }
        }   /* end of switch */
   }  /* end of while -- let's return and get out!! */ 
   return tree;
}  

/****************************************************************/
/*                                                              */
/*   Prints input program with line numbers in left column.     */
/*                                                              */
/****************************************************************/
void printprog(FILE *infile, FILE *outfile)
{
   int linecount = 0;
   char line[MAXLINE];

   rewind(infile);
   fprintf(outfile,"\v");
   while ( fgets(line,MAXLINE,infile) != NULL)
   {
       fprintf(outfile,"%-6d: %s",++linecount,line); 
   }
   Fclose(outfile);
}



Cross reference listing made at:  Mon Nov 29 15:19:30 2004


FILE                19   20   21   22   32   55   90   
MAXCITIES           5    18   
MAXLINE             6    58   60   
NULL                40   46   71   
argc                16   20   24   32   34   
argv                16   24   
char                10   16   20   32   58   71   
checkArgs           20   24   32   
city                58   62   63   71   76   
count               12   21   22   25   26   57   63   66   67   
                    68   70   76   80   81   85   90   94   96   
define              5    6    
else                66   78   
exit                37   43   49   74   
fgets               60   
fin                 19   20   21   22   24   25   32   40   55   
                    60   
first               57   65   
float               96   
fopen               40   46   
for                 94   
fout                19   20   24   26   32   46   90   95   
fprintf             95   
highTemp            57   62   67   80   
highTemps           18   21   25   26   55   63   67   68   70   
                    76   80   81   90   95   96   
hightemps           22   
i                   92   94   95   96   
if                  34   40   46   63   65   70   
include             1    2    3    4    
infile              20   32   40   
int                 11   12   16   20   21   22   32   55   57   
                    90   92   
line                58   60   62   
main                16   
malloc              71   
outfile             20   32   46   
perror              42   48   73   
printf              36   
readIntoWeatherStructs21   25   55   
return              85   
sscanf              62   
statecity           10   63   70   76   95   
strcmp              63   
strcpy              76   
strlen              71   
struct              8    18   21   22   55   90   
tempsum             11   67   80   96   
void                20   22   32   90   
weather             8    18   21   22   55   90   
while               60   
writeAveragesToOutput22   26   90   

1     : #include <stdio.h>
2     : #include <stdlib.h>
3     : #include <string.h>
4     : #include <ctype.h>
5     : #define MAXCITIES 100
6     : #define MAXLINE    80
7     : 
8     : struct weather
9     : {
10    :     char *statecity;
11    :     int   tempsum;
12    :     int   count;
13    : };
14    : 
15    : 
16    : int main(int argc, char **argv)
17    : {
18    :     struct weather highTemps[MAXCITIES] = {{"", 0, 0}};
19    :     FILE *fin, *fout;
20    :     void checkArgs(int argc,char *infile,char *outfile,FILE **fin,FILE **fout);
21    :     int readIntoWeatherStructs(struct weather *highTemps, FILE *fin), count;
22    :     void writeAveragesToOutput(struct weather *hightemps, int count, FILE *fin);
23    :     
24    :     checkArgs(argc, argv[1], argv[2], &fin, &fout);
25    :     count = readIntoWeatherStructs(highTemps, fin);
26    :     writeAveragesToOutput(highTemps, count, fout);
27    : }
28    : 
29    : 
30    : 
31    : 
32    : void checkArgs(int argc, char *infile, char *outfile, FILE **fin, FILE **fout)
33    : {
34    :     if (argc != 3)
35    :     {
36    :         printf("Wrong number of arguments on command line!\n");
37    :         exit(1);
38    :     }
39    : 
40    :     if ((*fin = fopen(infile, "r")) == NULL)
41    :     {
42    :         perror("Cannot open input file");
43    :         exit(1);
44    :     }
45    : 
46    :     if ((*fout = fopen(outfile, "w")) == NULL)
47    :     {
48    :         perror("Cannot open output file");
49    :         exit(1);
50    :     }
51    : } 
52    :     
53    : 
54    :      
55    : int readIntoWeatherStructs(struct weather *highTemps, FILE *fin)
56    : {
57    :     int count = 0, first = 1, highTemp;
58    :     char city[MAXLINE], line[MAXLINE];
59    :    
60    :     while (fgets(line, MAXLINE, fin))
61    :     {
62    :          sscanf(line, "%s %d", city, &highTemp);
63    :          if (strcmp(city, highTemps[count].statecity) != 0)
64    :          {
65    :               if (first) first = 0;
66    :               else count++;
67    :               highTemps[count].tempsum = highTemp; 
68    :               highTemps[count].count = 1;
69    : 
70    :               if ((highTemps[count].statecity = 
71    :                    (char *) malloc(strlen(city) + 1)) == NULL)
72    :               {
73    :                   perror("Malloc error!");
74    :                   exit(1);
75    :               }
76    :               strcpy(highTemps[count].statecity, city);                
77    :          }
78    :          else
79    :          {
80    :               highTemps[count].tempsum += highTemp;
81    :               highTemps[count].count++;
82    :          } 
83    :     }
84    : 
85    :     return count;
86    : }
87    : 
88    : 
89    : 
90    : void writeAveragesToOutput(struct weather *highTemps, int count, FILE *fout)
91    : {
92    :      int i;
93    : 
94    :      for (i = 0; i <= count; i++) 
95    :         fprintf(fout, "%s %-5.1f\n", highTemps[i].statecity,
96    :                  (float) highTemps[i].tempsum/highTemps[i].count);
97    : }