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"
85 "-a, --annotate Show annotated source code\n"
87 " The contents of all source code files found within the given\n"
88 " paths will be emitted to stdout. Each line will be prefixed with\n"
89 " a tab-delimited language name and semantic categorization (code,\n"
90 " comment, or blank).\n"
92 "-d, --detect Find source code files\n"
94 " Recursively find all source code files within the given paths.\n"
95 " For each source code file found, the file name will be emitted to\n"
96 " stdout prefixed with a tab-delimited language name.\n"
98 "-h, --help Display this message\n"
100 "-g, --gestalt Project Properties\n"
102 " Inspects project contents to determine what platform(s) the project\n"
103 " runs on, as well as any detected tools/IDEs used to develop it.\n"
105 "-i, --individual Count lines of code per file\n"
107 " Count lines in all source code files within the given paths, and\n"
108 " emit a report of the lines of code, comments, and blanks in each\n"
109 " language per file.\n"
113 " Displays detected licensing information contained in each source\n"
118 " Prints raw entity information to the screen (mainly for debugging).\n"
120 "-s, --summary Count lines of code (default)\n"
122 " Count lines in all source code files within the given paths, and\n"
123 " emit a report of the total number of lines of code, comments,\n"
124 " and blanks in each language. This is the default action.\n"
126 "[paths] can refer to any number of individual files or directories.\n"
127 " Directories will be probed recursively. If no path is given,\n"
128 " the current directory will be used.\n"
132 void sort_loc_list_by_language(LocList *list) {
133 LocList *iter = list->head;
136 LocList *iter2 = iter->next;
138 if (strcmp(iter2->loc->language, min->loc->language) < 0)
143 Loc *temp = iter->loc;
144 iter->loc = min->loc;
151 void individual(SourceFileList *list) {
153 SourceFileList *titer = list->head;
159 "Examining %i file(s)\n"
160 " Ohloh Line Count \n"
161 "Language Code Comment Comment %% Blank Total File\n"
162 "---------------- --------- --------- --------- --------- --------- -----------------------------------------------\n"
164 SourceFileList *iter = list->head;
166 LocList *loc_list = ohcount_sourcefile_get_loc_list(iter->sf);
167 sort_loc_list_by_language(loc_list);
168 LocList *liter = loc_list->head;
170 printf("%-16s", liter->loc->language);
171 printf(" %10d", liter->loc->code);
172 printf(" %10d", liter->loc->comments);
173 if (liter->loc->comments + liter->loc->code > 0)
175 (float)liter->loc->comments / (liter->loc->comments +
176 liter->loc->code) * 100);
179 printf(" %10d", liter->loc->blanks);
181 liter->loc->code + liter->loc->comments + liter->loc->blanks);
182 printf(" %s\n", iter->sf->filename);
189 void sort_loc_list_by_code(LocList *list) {
190 LocList *iter = list->head;
193 LocList *iter2 = iter->next;
195 if (iter2->loc->code > max->loc->code)
200 Loc *temp = iter->loc;
201 iter->loc = max->loc;
208 void summary(SourceFileList *list) {
210 SourceFileList *tmpiter = list->head;
213 tmpiter = tmpiter->next;
215 printf("Examining %i file(s)\n", count);
216 LocList *loc_list = ohcount_sourcefile_list_analyze_languages(list);
217 sort_loc_list_by_code(loc_list);
220 " Ohloh Line Count Summary \n"
222 "Language Files Code Comment Comment %% Blank Total\n"
223 "---------------- ----- --------- --------- --------- --------- ---------\n");
224 LocList *iter = loc_list->head;
226 printf("%-16s", iter->loc->language);
227 printf(" %6d", iter->loc->filecount);
228 printf(" %10d", iter->loc->code);
229 printf(" %10d", iter->loc->comments);
230 if (iter->loc->comments + iter->loc->code > 0)
232 (float)iter->loc->comments / (iter->loc->comments +
233 iter->loc->code) * 100);
236 printf(" %10d", iter->loc->blanks);
238 iter->loc->code + iter->loc->comments + iter->loc->blanks);
241 printf("---------------- ----- --------- --------- --------- --------- ---------\n");
242 int code = ohcount_loc_list_code(loc_list);
243 int comments = ohcount_loc_list_comments(loc_list);
244 int blanks = ohcount_loc_list_blanks(loc_list);
245 printf("%-16s", "Total");
246 printf(" %6d", ohcount_loc_list_filecount(loc_list));
247 printf(" %10d", code);
248 printf(" %10d", comments);
249 if (comments + code > 0)
250 printf(" %9.1f%%", (float)comments / (comments + code) * 100);
253 printf(" %10d", blanks);
254 printf(" %10d\n", code + comments + blanks);
255 ohcount_loc_list_free(loc_list);
258 int main(int argc, char *argv[]) {
261 struct OhcountOption *opt = ohcount_hash_command_from_flag(argv[1],
264 command = opt->value;
268 command = COMMAND_SUMMARY;
270 i = 2; // parameter is not a file or directory
272 SourceFileList *list = ohcount_sourcefile_list_new();
274 ohcount_sourcefile_list_add_directory(list, ".");
275 for (; i < argc; i++) {
276 DIR *dir = opendir(argv[i]);
278 ohcount_sourcefile_list_add_directory(list, argv[i]);
281 FILE *f = fopen(argv[i], "r");
283 ohcount_sourcefile_list_add_file(list, argv[i]);
285 } else printf("Bad argument: %s\n", argv[i]);
289 case COMMAND_ANNOTATE:
298 case COMMAND_GESTALT:
300 case COMMAND_INDIVIDUAL:
303 case COMMAND_LICENSES:
306 case COMMAND_RAWENTITIES:
309 case COMMAND_SUMMARY:
313 ohcount_sourcefile_list_free(list);