int main(int argc, char **argv) { // emit_module(); if ((argc < 2) || access(argv[1], F_OK) == -1) { printf("usage: %s <filename>\n", argv[0]); exit(-1); } printf("mksc compiler 0.01 ashley towns <*****@*****.**>\n"); char *contents = read_file(argv[1]); token_t *tokens = lex(contents); //print_tokens(tokens); annotate_source(argv[1], tokens); void *parser = ParseAlloc((void *) malloc); // ParseTrace(stdout, "* > "); mks_token_iterate(tokens, ^(token_t *token) { Parse(parser, token->type, token, NULL); });
void print_annotated_source () { Sym *sym, *line_stats, *new_line; Source_File *sf; int i, table_len; FILE *ofp; /* Find maximum line number for each source file that user is interested in: */ for (sym = symtab.base; sym < symtab.limit; ++sym) { /* Accept symbol if it's file is known, its line number is bigger than anything we have seen for that file so far and if it's in the INCL_ANNO table or there is no INCL_ANNO table and it does not appear in the EXCL_ANNO table. */ if (sym->file && sym->line_num > sym->file->num_lines && (sym_lookup (&syms[INCL_ANNO], sym->addr) || (syms[INCL_ANNO].len == 0 && !sym_lookup (&syms[EXCL_ANNO], sym->addr)))) { sym->file->num_lines = sym->line_num; } } /* Allocate line descriptors: */ for (sf = first_src_file; sf; sf = sf->next) { if (sf->num_lines > 0) { sf->line = (void **) xmalloc (sf->num_lines * sizeof (sf->line[0])); memset (sf->line, 0, sf->num_lines * sizeof (sf->line[0])); } } /* Count executions per line: */ for (sym = symtab.base; sym < symtab.limit; ++sym) { if (sym->file && sym->file->num_lines && (sym_lookup (&syms[INCL_ANNO], sym->addr) || (syms[INCL_ANNO].len == 0 && !sym_lookup (&syms[EXCL_ANNO], sym->addr)))) { sym->file->ncalls += sym->ncalls; line_stats = (Sym *) sym->file->line[sym->line_num - 1]; if (!line_stats) { /* Common case has at most one basic-block per source line: */ sym->file->line[sym->line_num - 1] = sym; } else if (!line_stats->addr) { /* sym is the 3rd .. nth basic block for this line: */ line_stats->ncalls += sym->ncalls; } else { /* sym is the second basic block for this line. */ new_line = (Sym *) xmalloc (sizeof (*new_line)); *new_line = *line_stats; new_line->addr = 0; new_line->ncalls += sym->ncalls; sym->file->line[sym->line_num - 1] = new_line; } } } /* Plod over source files, annotating them: */ for (sf = first_src_file; sf; sf = sf->next) { if (!sf->num_lines || (ignore_zeros && sf->ncalls == 0)) continue; num_executable_lines = num_lines_executed = 0; ofp = annotate_source (sf, 16, annotate_with_count, sf); if (!ofp) continue; if (bb_table_length > 0) { fprintf (ofp, _("\n\nTop %d Lines:\n\n Line Count\n\n"), bb_table_length); /* Abuse line arrays---it's not needed anymore: */ qsort (sf->line, sf->num_lines, sizeof (sf->line[0]), cmp_ncalls); table_len = bb_table_length; if (table_len > sf->num_lines) table_len = sf->num_lines; for (i = 0; i < table_len; ++i) { sym = (Sym *) sf->line[i]; if (!sym || sym->ncalls == 0) break; fprintf (ofp, "%9d %10lu\n", sym->line_num, sym->ncalls); } } free (sf->line); sf->line = 0; fprintf (ofp, _("\nExecution Summary:\n\n")); fprintf (ofp, _("%9ld Executable lines in this file\n"), num_executable_lines); fprintf (ofp, _("%9ld Lines executed\n"), num_lines_executed); fprintf (ofp, _("%9.2f Percent of the file executed\n"), num_executable_lines ? 100.0 * num_lines_executed / (double) num_executable_lines : 100.0); fprintf (ofp, _("\n%9lu Total number of line executions\n"), sf->ncalls); fprintf (ofp, _("%9.2f Average executions per line\n"), num_executable_lines ? (double) sf->ncalls / (double) num_executable_lines : 0.0); if (ofp != stdout) fclose (ofp); } }