1 --------------------------------------------------------------------------------
3 --------------------------------------------------------------------------------
4 Invocation: ../cg_annotate concord.cgout
5 Command: ./concord ../cg_main.c
12 --------------------------------------------------------------------------------
14 --------------------------------------------------------------------------------
17 8,195,056 (100.0%) PROGRAM TOTALS
19 --------------------------------------------------------------------------------
20 -- File:function summary
21 --------------------------------------------------------------------------------
22 Ir______________________ file:function
24 < 3,078,746 (37.6%, 37.6%) /home/njn/grind/ws1/cachegrind/docs/concord.c:
25 1,630,232 (19.9%) get_word
28 130,560 (1.6%) add_existing
29 91,014 (1.1%) init_hash_table
31 46,676 (0.6%) new_word_node
33 < 1,746,038 (21.3%, 58.9%) ./malloc/./malloc/malloc.c:
34 1,285,938 (15.7%) _int_malloc
37 < 1,107,550 (13.5%, 72.4%) ./libio/./libio/getc.c:getc
39 < 551,071 (6.7%, 79.1%) ./string/../sysdeps/x86_64/multiarch/strcmp-avx2.S:__strcmp_avx2
41 < 521,228 (6.4%, 85.5%) ./ctype/../include/ctype.h:
42 260,616 (3.2%) __ctype_tolower_loc
43 260,612 (3.2%) __ctype_b_loc
45 < 468,163 (5.7%, 91.2%) ???:
48 < 456,071 (5.6%, 96.8%) /usr/include/ctype.h:get_word
50 < 48,344 (0.6%, 97.3%) ./string/../sysdeps/x86_64/multiarch/strcpy-avx2.S:__strcpy_avx2
52 < 40,776 (0.5%, 97.8%) ./elf/./elf/dl-lookup.c:
53 25,623 (0.3%) do_lookup_x
54 9,515 (0.1%) _dl_lookup_symbol_x
56 < 37,412 (0.5%, 98.3%) ./elf/./elf/dl-tunables.c:
57 36,500 (0.4%) __GI___tunables_init
59 < 23,366 (0.3%, 98.6%) ./string/../sysdeps/x86_64/multiarch/strlen-avx2.S:__strlen_avx2
61 < 22,107 (0.3%, 98.9%) ./malloc/./malloc/arena.c:
64 < 16,539 (0.2%, 99.1%) ./elf/./elf/dl-reloc.c:_dl_relocate_object
66 < 9,160 (0.1%, 99.2%) ./elf/../sysdeps/generic/dl-new-hash.h:_dl_lookup_symbol_x
68 < 8,535 (0.1%, 99.3%) ./string/../sysdeps/x86_64/multiarch/../multiarch/strcmp-sse2.S:
71 --------------------------------------------------------------------------------
72 -- Function:file summary
73 --------------------------------------------------------------------------------
74 Ir______________________ function:file
76 > 2,086,303 (25.5%, 25.5%) get_word:
77 1,630,232 (19.9%) /home/njn/grind/ws1/cachegrind/docs/concord.c
78 456,071 (5.6%) /usr/include/ctype.h
80 > 1,285,938 (15.7%, 41.1%) _int_malloc:./malloc/./malloc/malloc.c
82 > 1,107,550 (13.5%, 54.7%) getc:./libio/./libio/getc.c
84 > 630,918 (7.7%, 62.4%) hash:/home/njn/grind/ws1/cachegrind/docs/concord.c
86 > 551,071 (6.7%, 69.1%) __strcmp_avx2:./string/../sysdeps/x86_64/multiarch/strcmp-avx2.S
88 > 480,248 (5.9%, 74.9%) malloc:
89 458,225 (5.6%) ./malloc/./malloc/malloc.c
90 22,023 (0.3%) ./malloc/./malloc/arena.c
92 > 468,151 (5.7%, 80.7%) ???:???
94 > 461,095 (5.6%, 86.3%) insert:/home/njn/grind/ws1/cachegrind/docs/concord.c
96 > 260,616 (3.2%, 89.5%) __ctype_tolower_loc:./ctype/../include/ctype.h
98 > 260,612 (3.2%, 92.6%) __ctype_b_loc:./ctype/../include/ctype.h
100 > 130,560 (1.6%, 94.2%) add_existing:/home/njn/grind/ws1/cachegrind/docs/concord.c
102 > 91,014 (1.1%, 95.4%) init_hash_table:/home/njn/grind/ws1/cachegrind/docs/concord.c
104 > 88,056 (1.1%, 96.4%) create:/home/njn/grind/ws1/cachegrind/docs/concord.c
106 > 50,010 (0.6%, 97.0%) new_word_node:
107 46,676 (0.6%) /home/njn/grind/ws1/cachegrind/docs/concord.c
109 > 48,344 (0.6%, 97.6%) __strcpy_avx2:./string/../sysdeps/x86_64/multiarch/strcpy-avx2.S
111 > 42,906 (0.5%, 98.1%) __GI___tunables_init:
112 36,500 (0.4%) ./elf/./elf/dl-tunables.c
114 > 26,514 (0.3%, 98.5%) do_lookup_x:
115 25,623 (0.3%) ./elf/./elf/dl-lookup.c
117 > 25,642 (0.3%, 98.8%) _dl_relocate_object:
118 16,539 (0.2%) ./elf/./elf/dl-reloc.c
120 > 23,366 (0.3%, 99.1%) __strlen_avx2:./string/../sysdeps/x86_64/multiarch/strlen-avx2.S
122 > 18,675 (0.2%, 99.3%) _dl_lookup_symbol_x:
123 9,515 (0.1%) ./elf/./elf/dl-lookup.c
124 9,160 (0.1%) ./elf/../sysdeps/generic/dl-new-hash.h
126 > 8,547 (0.1%, 99.4%) strcmp:
127 8,503 (0.1%) ./string/../sysdeps/x86_64/multiarch/../multiarch/strcmp-sse2.S
129 --------------------------------------------------------------------------------
130 -- Annotated source file: ./ctype/../include/ctype.h
131 --------------------------------------------------------------------------------
132 Unannotated because one or more of these original files are unreadable:
133 - ./ctype/../include/ctype.h
135 --------------------------------------------------------------------------------
136 -- Annotated source file: ./elf/../sysdeps/generic/dl-new-hash.h
137 --------------------------------------------------------------------------------
138 Unannotated because one or more of these original files are unreadable:
139 - ./elf/../sysdeps/generic/dl-new-hash.h
141 --------------------------------------------------------------------------------
142 -- Annotated source file: ./elf/./elf/dl-lookup.c
143 --------------------------------------------------------------------------------
144 Unannotated because one or more of these original files are unreadable:
145 - ./elf/./elf/dl-lookup.c
147 --------------------------------------------------------------------------------
148 -- Annotated source file: ./elf/./elf/dl-reloc.c
149 --------------------------------------------------------------------------------
150 Unannotated because one or more of these original files are unreadable:
151 - ./elf/./elf/dl-reloc.c
153 --------------------------------------------------------------------------------
154 -- Annotated source file: ./elf/./elf/dl-tunables.c
155 --------------------------------------------------------------------------------
156 Unannotated because one or more of these original files are unreadable:
157 - ./elf/./elf/dl-tunables.c
159 --------------------------------------------------------------------------------
160 -- Annotated source file: ./libio/./libio/getc.c
161 --------------------------------------------------------------------------------
162 Unannotated because one or more of these original files are unreadable:
163 - ./libio/./libio/getc.c
165 --------------------------------------------------------------------------------
166 -- Annotated source file: ./malloc/./malloc/arena.c
167 --------------------------------------------------------------------------------
168 Unannotated because one or more of these original files are unreadable:
169 - ./malloc/./malloc/arena.c
171 --------------------------------------------------------------------------------
172 -- Annotated source file: ./malloc/./malloc/malloc.c
173 --------------------------------------------------------------------------------
174 Unannotated because one or more of these original files are unreadable:
175 - ./malloc/./malloc/malloc.c
177 --------------------------------------------------------------------------------
178 -- Annotated source file: ./string/../sysdeps/x86_64/multiarch/../multiarch/strcmp-sse2.S
179 --------------------------------------------------------------------------------
180 Unannotated because one or more of these original files are unreadable:
181 - ./string/../sysdeps/x86_64/multiarch/../multiarch/strcmp-sse2.S
183 --------------------------------------------------------------------------------
184 -- Annotated source file: ./string/../sysdeps/x86_64/multiarch/strcmp-avx2.S
185 --------------------------------------------------------------------------------
186 Unannotated because one or more of these original files are unreadable:
187 - ./string/../sysdeps/x86_64/multiarch/strcmp-avx2.S
189 --------------------------------------------------------------------------------
190 -- Annotated source file: ./string/../sysdeps/x86_64/multiarch/strcpy-avx2.S
191 --------------------------------------------------------------------------------
192 Unannotated because one or more of these original files are unreadable:
193 - ./string/../sysdeps/x86_64/multiarch/strcpy-avx2.S
195 --------------------------------------------------------------------------------
196 -- Annotated source file: ./string/../sysdeps/x86_64/multiarch/strlen-avx2.S
197 --------------------------------------------------------------------------------
198 Unannotated because one or more of these original files are unreadable:
199 - ./string/../sysdeps/x86_64/multiarch/strlen-avx2.S
201 --------------------------------------------------------------------------------
202 -- Annotated source file: /home/njn/grind/ws1/cachegrind/docs/concord.c
203 --------------------------------------------------------------------------------
206 -- line 81 ----------------------------------------
207 . Arg_Node *append(char *word, Arg_Node *head);
208 . void count(Arg_Node *head, Word_Node *table[]);
209 . void list_lines(Arg_Node *head, Word_Node *table[]);
210 . void intersection(Arg_Node *head);
211 . void intersect_array(int master[], int size, Arg_Node *arg_head);
212 . void kill_arg_list(Arg_Node *head);
214 . int main(int argc, char *argv[])
216 . /* The actual hash table, a fixed-size array of pointers to word nodes */
217 . Word_Node *table[TABLE_SIZE];
219 . /* Checking command line input for one file name */
220 2 (0.0%) if (argc != ARGS_NUMBER + 1) {
221 . fprintf(stderr, "%s requires %d argument\n", argv[0], ARGS_NUMBER);
222 . exit(EXIT_FAILURE);
225 4 (0.0%) init_hash_table(argv[1], table);
226 2 (0.0%) interact(table);
228 . /* Nb: I am not freeing the dynamic memory in the hash table, having been
229 . ** told this is not necessary. */
233 . /* General dynamic allocation function that allocates and then checks. */
234 . void *create(int mem_size)
238 22,014 (0.3%) dyn_block = malloc(mem_size);
239 22,014 (0.3%) if (!(dyn_block)) {
240 . fprintf(stderr, "Couldn't allocate enough memory to continue.\n");
241 . exit(EXIT_FAILURE);
247 . /* Function returns a hash value on a word. Almost identical to the hash
248 . ** function presented in Sedgewick.
250 . int hash(char *word)
252 7,908 (0.1%) int hash_value = 0;
254 161,292 (2.0%) for ( ; *word; word++)
255 453,810 (5.5%) hash_value = (HASH_CONSTANT * hash_value + *word) % TABLE_SIZE;
260 . /* Function builds the hash table from the given file. */
261 . void init_hash_table(char *file_name, Word_Node *table[])
265 2 (0.0%) int line = 1, i;
267 . /* Structure used when reading in words and line numbers. */
268 3 (0.0%) data = (Word_Info *) create(sizeof(Word_Info));
270 . /* Initialise entire table to NULL. */
271 2,993 (0.0%) for (i = 0; i < TABLE_SIZE; i++)
272 997 (0.0%) table[i] = NULL;
274 . /* Open file, check it. */
275 4 (0.0%) file_ptr = fopen(file_name, "r");
276 2 (0.0%) if (!(file_ptr)) {
277 . fprintf(stderr, "Couldn't open '%s'.\n", file_name);
278 . exit(EXIT_FAILURE);
281 . /* 'Get' the words and lines one at a time from the file, and insert them
282 . ** into the table one at a time. */
283 55,363 (0.7%) while ((line = get_word(data, line, file_ptr)) != EOF)
284 31,632 (0.4%) insert(data->word, data->line, table);
287 2 (0.0%) fclose(file_ptr);
290 . /* Function reads the next word, and it's line number, and places them in the
291 . ** structure 'data', via a pointer.
293 . int get_word(Word_Info *data, int line, FILE *file_ptr)
295 15,818 (0.2%) int index = 0, pos = BEFORE_WORD;
297 . /* Only alphabetic characters are read, apostrophes are ignored, and other
298 . ** characters are considered separators. 'pos' helps keep track whether
299 . ** the current file position is inside a word or between words.
301 529,133 (6.5%) while ((data->word[index] = tolower(fgetc(file_ptr))) != EOF) {
302 . if (data->word[index] == '\n')
303 260,608 (3.2%) line++;
304 390,912 (4.8%) if (islower(data->word[index])) {
305 64,830 (0.8%) if (pos == BEFORE_WORD) {
306 15,816 (0.2%) pos = IN_WORD;
307 7,908 (0.1%) data->line = line;
309 32,415 (0.4%) index++;
311 146,702 (1.8%) else if ((pos == IN_WORD) && (data->word[index] != '\'')) {
315 . /* Signals end of file has been reached. */
316 . if (data->word[index] == EOF)
319 . /* Adding the null character. */
320 15,818 (0.2%) data->word[index] = '\0';
325 . /* Function inserts a word and it's line number into the hash table. */
326 . void insert(char *inword, int in_line, Word_Node *table[])
328 7,908 (0.1%) int position = hash(inword);
329 . Word_Node *curr, *prev = NULL;
330 7,908 (0.1%) char dummy_word[DUMMY_WORD_LENGTH] = "A";
332 . /* The case where that hash position hasn't been used before; a new word
333 . ** node is created.
335 31,632 (0.4%) if (table[position] == NULL)
336 3,185 (0.0%) table[position] = new_word_node(dummy_word, 0);
337 7,908 (0.1%) curr = table[position];
339 . /* Traverses that position's list of words until the current word is found
340 . ** (i.e. it's come up before) or the list end is reached (i.e. it's the
341 . ** first occurrence of the word).
343 118,384 (1.4%) while ((curr != NULL) && (strcmp(inword, curr->word) > 0)) {
345 28,366 (0.3%) curr = curr->next_word;
348 . /* If the word hasn't appeared before, it's inserted alphabetically into
351 35,410 (0.4%) if ((curr == NULL) || (strcmp(curr->word, inword) != 0)) {
352 4,120 (0.1%) prev->next_word = new_word_node(inword, in_line);
353 1,030 (0.0%) prev->next_word->next_word = curr;
355 . /* Otherwise, the word count is incremented, and the line number is added
356 . ** to the existing list.
359 6,878 (0.1%) (curr->number)++;
360 27,512 (0.3%) curr->last_line = add_existing(curr->last_line, in_line);
364 . /* Function creates a new node for when a word is inserted for the first time.
366 . Word_Node *new_word_node(char *inword, int in_line)
370 5,001 (0.1%) new = (Word_Node *) create(sizeof(Word_Node));
371 8,335 (0.1%) new->word = (char *) create(sizeof(char) * (strlen(inword) + 1));
372 1,667 (0.0%) new->word = strcpy(new->word, inword);
373 . /* The word count is set to 1, as this is the first occurrence! */
374 1,667 (0.0%) new->number = 1;
375 1,667 (0.0%) new->next_word = NULL;
376 . /* One line number node is added. */
377 5,001 (0.1%) new->line_list = (Line_Node *) create(sizeof(Line_Node));
378 1,667 (0.0%) new->line_list->line = in_line;
379 1,667 (0.0%) new->line_list->next_line = NULL;
380 1,667 (0.0%) new->last_line = new->line_list;
385 . /* Function adds a line number to the line number list of a word that has
386 . ** already been inserted at least once. The pointer 'last_line', part of
387 . ** the word node structure, allows easy appending to the list.
389 . Line_Node *add_existing(Line_Node *last_line, int in_line)
391 . /* Check to see if that line has already occurred - multiple occurrences on
392 . ** the one line are only recorded once. (Nb: They are counted twice, but
393 . ** only listed once.)
395 13,756 (0.2%) if (last_line->line != in_line) {
396 18,009 (0.2%) last_line->next_line = (Line_Node *) create(sizeof(Line_Node));
397 12,006 (0.1%) last_line = last_line->next_line;
398 6,003 (0.1%) last_line->line = in_line;
399 6,003 (0.1%) last_line->next_line = NULL;
405 . /* Function controls the interactive command line part of the program. */
406 . void interact(Word_Node *table[])
408 . char args[MAX_WORD_LENGTH]; /* Array to hold command line */
409 . Arg_Node *arg_list = NULL; /* List that holds processed arguments */
410 . int not_quitted = TRUE; /* Quit flag */
412 . /* The prompt (?) is displayed. Commands are read into an array, and then
413 . ** individual arguments are placed into a linked list for easy use.
414 . ** The first argument (actually the command) is looked at to determine
415 . ** what action should be performed. 'arg_list->next_arg' is passed to
416 . ** count() and list_lines(), because the actual 'c' or 'l' is not needed
417 . ** by them. Lastly, the argument linked list is freed, by 'kill_arg_list'.
421 . fgets(args, MAX_WORD_LENGTH - 1, stdin);
422 3 (0.0%) arg_list = place_args_in_list(args);
423 2 (0.0%) if (arg_list) {
424 7 (0.0%) if (strcmp(arg_list->word, "c") == 0)
425 . count(arg_list->next_arg, table);
426 6 (0.0%) else if (strcmp(arg_list->word, "l") == 0)
427 . list_lines(arg_list->next_arg, table);
428 8 (0.0%) else if (strcmp(arg_list->word, "q") == 0) {
429 . printf("Quitting concord\n");
430 1 (0.0%) not_quitted = FALSE;
433 . printf("Not a valid command.\n");
434 2 (0.0%) kill_arg_list(arg_list);
436 2 (0.0%) } while (not_quitted); /* Quits on flag */
439 . /* Function takes an array containing a command line, and parses it, placing
440 . ** actual word into a linked list.
442 . Arg_Node *place_args_in_list(char command[])
444 2 (0.0%) int index1 = 0, index2 = 0, pos = BEFORE_WORD;
445 . char token[MAX_WORD_LENGTH], c;
446 1 (0.0%) Arg_Node *head = NULL;
448 . /* Non alphabetic characters are discarded. Alphabetic characters are
449 . ** copied into the array 'token'. Once the current word has been copied
450 . ** into 'token', 'append' is called, copying 'token' to a new node in the
453 12 (0.0%) while (command[index1] != '\0') {
454 8 (0.0%) c = tolower(command[index1++]);
455 11 (0.0%) if (islower(c)) {
456 3 (0.0%) token[index2++] = c;
457 4 (0.0%) pos = IN_WORD;
459 2 (0.0%) else if (c == '\'')
461 2 (0.0%) else if (pos == IN_WORD) {
462 1 (0.0%) pos = BEFORE_WORD;
463 2 (0.0%) token[index2] = '\0';
464 4 (0.0%) head = append(token, head);
472 . /* Function takes a word, and appends a new node containing that word to the
475 . Arg_Node *append(char *word, Arg_Node *head)
477 . Arg_Node *curr = head,
478 3 (0.0%) *new = (Arg_Node *) create(sizeof(Arg_Node));
480 6 (0.0%) new->word = (char *) create(sizeof(char) * (strlen(word) + 1));
481 . strcpy(new->word, word);
482 1 (0.0%) new->line_list = NULL;
483 1 (0.0%) new->next_arg = NULL;
485 2 (0.0%) if (head == NULL)
488 . while (curr->next_arg != NULL)
489 . curr = curr->next_arg;
490 . curr->next_arg = new;
496 . /* Function displays the number of times a word has occurred. */
497 . void count(Arg_Node *arg_list, Word_Node *table[])
499 . int hash_pos = 0; /* Only initialised to avoid gnuc warnings */
500 . Word_Node *curr_word = NULL;
502 -- line 375 ----------------------------------------
503 -- line 514 ----------------------------------------
504 . *(master + index) = 0;
506 . arg_head = arg_head->next_arg;
510 . /* Function to free dynamic memory used by the arguments linked list. */
511 . void kill_arg_list(Arg_Node *head)
515 4 (0.0%) while (head != NULL) {
517 2 (0.0%) head = head->next_arg;
518 2 (0.0%) free(temp->word);
524 --------------------------------------------------------------------------------
525 -- Annotated source file: /usr/include/ctype.h
526 --------------------------------------------------------------------------------
529 -- line 201 ----------------------------------------
530 . # define isblank(c) __isctype((c), _ISblank)
534 . # ifdef __USE_EXTERN_INLINES
535 . __extern_inline int
536 . __NTH (tolower (int __c))
538 456,071 (5.6%) return __c >= -128 && __c < 256 ? (*__ctype_tolower_loc ())[__c] : __c;
541 . __extern_inline int
542 . __NTH (toupper (int __c))
544 . return __c >= -128 && __c < 256 ? (*__ctype_toupper_loc ())[__c] : __c;
547 -- line 217 ----------------------------------------
549 --------------------------------------------------------------------------------
550 -- Annotation summary
551 --------------------------------------------------------------------------------
554 3,534,817 (43.1%) annotated: files known & above threshold & readable, line numbers known
555 0 annotated: files known & above threshold & readable, line numbers unknown
556 0 unannotated: files known & above threshold & two or more non-identical
557 4,132,126 (50.4%) unannotated: files known & above threshold & unreadable
558 59,950 (0.7%) unannotated: files known & below threshold
559 468,163 (5.7%) unannotated: files unknown