1 // ohcount.c written by Mitchell Foral. mitchell<att>caladbolg.net.
2 // See COPYING for license information.
8 #include "hash/option_hash.h"
9 #include "sourcefile.h"
12 void annotate_callback(const char *language, const char *entity, int start,
13 int end, void *userdata) {
14 SourceFile *sf = (SourceFile *)userdata;
15 int length = end - start;
17 strncpy(buf, (const char*)sf->contents + start, length); // field exists
19 printf("%s\t%s\t%s", language, entity, buf);
22 void annotate(SourceFileList *list) {
23 SourceFileList *iter = list->head;
25 ohcount_sourcefile_parse_with_callback(iter->sf, annotate_callback,
31 void detect(SourceFileList *list) {
32 SourceFileList *iter = list->head;
34 printf("%s\t%s\n", ohcount_sourcefile_get_language(iter->sf),
40 void licenses(SourceFileList *list) {
41 SourceFileList *iter = list->head;
43 LicenseList *liter = ohcount_sourcefile_get_license_list(iter->sf)->head;
45 printf("%s%s ", liter->lic->name, (liter->next != NULL) ? "," : "");
46 printf("%s\n", iter->sf->filename);
53 void raw_entities_callback(const char *language, const char *entity, int start,
54 int end, void *userdata) {
55 printf("%s\t%s\t%i\t%i\n", language, entity, start, end);
58 void raw_entities(SourceFileList *list) {
59 SourceFileList *iter = list->head;
61 ohcount_sourcefile_parse_entities_with_callback(iter->sf,
62 raw_entities_callback,
70 "Usage: ohcount [option] [paths...]\n"
72 "Ohloh source code line counter command line tool.\n"
73 " http://www.ohloh.net/\n"
75 "[option] can be one of the following:\n"
84 "-a, --annotate Show annotated source code\n"
86 " The contents of all source code files found within the given\n"
87 " paths will be emitted to stdout. Each line will be prefixed with\n"
88 " a tab-delimited language name and semantic categorization (code,\n"
89 " comment, or blank).\n"
91 "-d, --detect Find source code files\n"
93 " Recursively find all source code files within the given paths.\n"
94 " For each source code file found, the file name will be emitted to\n"
95 " stdout prefixed with a tab-delimited language name.\n"
97 "-h, --help Display this message\n"
99 "-i, --individual Count lines of code per file\n"
101 " Count lines in all source code files within the given paths, and\n"
102 " emit a report of the lines of code, comments, and blanks in each\n"
103 " language per file.\n"
107 " Displays detected licensing information contained in each source\n"
112 " Prints raw entity information to the screen (mainly for debugging).\n"
114 "-s, --summary Count lines of code (default)\n"
116 " Count lines in all source code files within the given paths, and\n"
117 " emit a report of the total number of lines of code, comments,\n"
118 " and blanks in each language. This is the default action.\n"
120 "[paths] can refer to any number of individual files or directories.\n"
121 " Directories will be probed recursively. If no path is given,\n"
122 " the current directory will be used.\n"
126 void sort_loc_list_by_language(LocList *list) {
127 LocList *iter = list->head;
130 LocList *iter2 = iter->next;
132 if (strcmp(iter2->loc->language, min->loc->language) < 0)
137 Loc *temp = iter->loc;
138 iter->loc = min->loc;
145 void individual(SourceFileList *list) {
147 SourceFileList *titer = list->head;
153 "Examining %i file(s)\n"
154 " Ohloh Line Count \n"
155 "Language Code Comment Comment %% Blank Total File\n"
156 "---------------- --------- --------- --------- --------- --------- -----------------------------------------------\n"
158 SourceFileList *iter = list->head;
160 LocList *loc_list = ohcount_sourcefile_get_loc_list(iter->sf);
161 sort_loc_list_by_language(loc_list);
162 LocList *liter = loc_list->head;
164 printf("%-16s", liter->loc->language);
165 printf(" %10d", liter->loc->code);
166 printf(" %10d", liter->loc->comments);
167 if (liter->loc->comments + liter->loc->code > 0)
169 (float)liter->loc->comments / (liter->loc->comments +
170 liter->loc->code) * 100);
173 printf(" %10d", liter->loc->blanks);
175 liter->loc->code + liter->loc->comments + liter->loc->blanks);
176 printf(" %s\n", iter->sf->filename);
183 void sort_loc_list_by_code(LocList *list) {
184 LocList *iter = list->head;
187 LocList *iter2 = iter->next;
189 if (iter2->loc->code > max->loc->code)
194 Loc *temp = iter->loc;
195 iter->loc = max->loc;
202 void summary(SourceFileList *list) {
204 SourceFileList *tmpiter = list->head;
207 tmpiter = tmpiter->next;
209 printf("Examining %i file(s)\n", count);
210 LocList *loc_list = ohcount_sourcefile_list_analyze_languages(list);
211 sort_loc_list_by_code(loc_list);
214 " Ohloh Line Count Summary \n"
216 "Language Files Code Comment Comment %% Blank Total\n"
217 "---------------- ----- --------- --------- --------- --------- ---------\n");
218 LocList *iter = loc_list->head;
220 printf("%-16s", iter->loc->language);
221 printf(" %6d", iter->loc->filecount);
222 printf(" %10d", iter->loc->code);
223 printf(" %10d", iter->loc->comments);
224 if (iter->loc->comments + iter->loc->code > 0)
226 (float)iter->loc->comments / (iter->loc->comments +
227 iter->loc->code) * 100);
230 printf(" %10d", iter->loc->blanks);
232 iter->loc->code + iter->loc->comments + iter->loc->blanks);
235 printf("---------------- ----- --------- --------- --------- --------- ---------\n");
236 int code = ohcount_loc_list_code(loc_list);
237 int comments = ohcount_loc_list_comments(loc_list);
238 int blanks = ohcount_loc_list_blanks(loc_list);
239 printf("%-16s", "Total");
240 printf(" %6d", ohcount_loc_list_filecount(loc_list));
241 printf(" %10d", code);
242 printf(" %10d", comments);
243 if (comments + code > 0)
244 printf(" %9.1f%%", (float)comments / (comments + code) * 100);
247 printf(" %10d", blanks);
248 printf(" %10d\n", code + comments + blanks);
249 ohcount_loc_list_free(loc_list);
252 int main(int argc, char *argv[]) {
255 struct OhcountOption *opt = ohcount_hash_command_from_flag(argv[1],
258 command = opt->value;
262 command = COMMAND_SUMMARY;
264 i = 2; // parameter is not a file or directory
266 SourceFileList *list = ohcount_sourcefile_list_new();
268 ohcount_sourcefile_list_add_directory(list, ".");
269 for (; i < argc; i++) {
270 DIR *dir = opendir(argv[i]);
272 ohcount_sourcefile_list_add_directory(list, argv[i]);
275 FILE *f = fopen(argv[i], "r");
277 ohcount_sourcefile_list_add_file(list, argv[i]);
279 } else printf("Bad argument: %s\n", argv[i]);
283 case COMMAND_ANNOTATE:
292 case COMMAND_INDIVIDUAL:
295 case COMMAND_LICENSES:
298 case COMMAND_RAWENTITIES:
301 case COMMAND_SUMMARY:
305 ohcount_sourcefile_list_free(list);