/*****************************************************************************/ /* C-c[o]d[e]c[ou]nt.c Count of lines of code. Count of lines of comment. BUILD DETAILS ------------- $ @BUILD_CCDCNT BUILD !compile+link $ @BUILD_CCDCNT LINK !link-only COPYRIGHT --------- Copyright (C) 2015 Mark G.Daniel This program, comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version. http://www.gnu.org/licenses/gpl.txt VERSION HISTORY --------------- 21-JAN-2015 MGD v1.0.0, initial (q&d) development */ /*****************************************************************************/ #define SOFTWAREVN "1.0.0" #define SOFTWARENM "CCDCNT" #ifdef __ALPHA # define SOFTWAREID SOFTWARENM " AXP-" SOFTWAREVN #endif #ifdef __ia64 # define SOFTWAREID SOFTWARENM " IA64-" SOFTWAREVN #endif #ifdef __VAX # define SOFTWAREID SOFTWARENM " VAX-" SOFTWAREVN #endif /* standard C header files */ #include #include #include #include #include #include #include /* VMS header files */ #include #include #include #include #include /* macros */ #define FI_LI __FILE__, __LINE__ #define ODS_MAX_FILE_NAME_LENGTH 1024 #define ODS2_MAX_FILE_NAME_LENGTH 255 #define VMSnok(x) (!((x) & STS$M_SUCCESS)) #define VMSok(x) ((x) & STS$M_SUCCESS) #define USHORTPTR __unaligned unsigned short* #define SAME2(ptr,val) (*(USHORTPTR)(ptr) == val) #define SLASHESC(ptr) (*ptr == '\\' && *(ptr+1)) int Debug = 0; char Utility [] = "CCDCNT"; /*****************************************************************************/ /* */ main (int argc, char** argv) { static char Dash80 [] = "-----------------------------------------\ -------------------------------------"; int cnt, size, status, BothCharCount, BothLineCount, CodeCharCount, CodeLineCount, CommentCharCount, CommentLineCount, CommentCount, DoOverAll = 0, ExpFileNameLength, FileCharCount, FileLineCount, PrevCodeCharCount, PrevCommentCharCount, ResFileNameLength, TotalBothCharCount = 0, TotalBothLineCount = 0, TotalCharCount = 0, TotalCodeCharCount = 0, TotalCodeLineCount = 0, TotalCommentCharCount = 0, TotalCommentLineCount = 0, TotalCommentCount = 0, TotalFileCount = 0, TotalLineCount = 0; char ExpFileName [ODS_MAX_FILE_NAME_LENGTH+1], ResFileName [ODS_MAX_FILE_NAME_LENGTH+1]; char *aptr, *cptr, *fsptr, *sptr, *zptr; stat_t statBuf; FILE *fptr; struct FAB SearchFab; struct NAM SearchNam; #ifdef ODS_EXTENDED struct NAML SearchNaml; #endif /* ODS_EXTENDED */ /*********/ /* begin */ /*********/ fsptr = "*.C;0"; for (cnt = 1; cnt < argc; cnt++) { if (argv[cnt][0] == '/') { if (!strcasecmp(argv[cnt],"/overall") || !strcasecmp(argv[cnt],"/brief")) DoOverAll = 1; } else fsptr = argv[cnt]; } SearchFab = cc$rms_fab; SearchFab.fab$l_dna = "*.*;0"; SearchFab.fab$b_dns = 5; #ifdef ODS_EXTENDED SearchFab.fab$l_fna = (char*)-1; SearchFab.fab$b_fns = 0; SearchFab.fab$l_nam = (struct namdef*)&SearchNaml; ENAMEL_RMS_NAML(SearchNaml) SearchNaml.naml$l_long_filename = fsptr; SearchNaml.naml$l_long_filename_size = strlen(fsptr); SearchNaml.naml$l_long_expand = ExpFileName; SearchNaml.naml$l_long_expand_alloc = sizeof(ExpFileName)-1; SearchNaml.naml$l_long_result = ResFileName; SearchNaml.naml$l_long_result_alloc = sizeof(ResFileName)-1; #else /* ODS_EXTENDED */ SearchFab.fab$l_fna = fsptr; SearchFab.fab$b_fns = strlen(fsptr); SearchFab.fab$l_nam = &SearchNam; SearchNam = cc$rms_nam; SearchNam.nam$l_esa = ExpFileName; SearchNam.nam$b_ess = ODS2_MAX_FILE_NAME_LENGTH; SearchNam.nam$l_rsa = ResFileName; SearchNam.nam$b_rss = ODS2_MAX_FILE_NAME_LENGTH; #endif /* ODS_EXTENDED */ if (VMSnok (status = sys$parse (&SearchFab, 0, 0))) return (status); #ifdef ODS_EXTENDED SearchNaml.naml$l_long_ver[SearchNaml.naml$l_long_ver_size] = '\0'; ExpFileNameLength = (SearchNaml.naml$l_long_ver - ExpFileName) + SearchNaml.naml$l_long_ver_size; #else /* ODS_EXTENDED */ SearchNam.nam$l_ver[SearchNam.nam$b_ver] = '\0'; ExpFileNameLength = (SearchNam.nam$l_ver - ExpFileName) + SearchNam.nam$b_ver; #endif /* ODS_EXTENDED */ if (Debug) fprintf (stdout, "ExpFileName %d |%s|\n", ExpFileNameLength, ExpFileName); /*****************/ /* for each file */ /*****************/ while (VMSok (status = sys$search (&SearchFab, 0, 0))) { #ifdef ODS_EXTENDED SearchNaml.naml$l_long_ver[SearchNaml.naml$l_long_ver_size] = '\0'; ResFileNameLength = (SearchNaml.naml$l_long_ver - ResFileName) + SearchNaml.naml$l_long_ver_size; #else /* ODS_EXTENDED */ SearchNam.nam$l_ver[SearchNam.nam$b_ver] = '\0'; ResFileNameLength = (SearchNam.nam$l_ver - ResFileName) + SearchNam.nam$b_ver; #endif /* ODS_EXTENDED */ if (Debug) fprintf (stdout, "ResFileName %d |%s|\n", ResFileNameLength, ResFileName); if (stat (ResFileName, &statBuf) < 0) { fprintf (stdout, "%s-E-ACCESS, %%X%08.08X %s\n", Utility, vaxc$errno, ResFileName); continue; } size = statBuf.st_size; if (Debug) fprintf (stdout, "%d bytes\n", size); if (!(aptr = calloc (1, size+1024))) exit (vaxc$errno); /****************/ /* process file */ /****************/ if ((fptr = fopen (ResFileName, "r", "shr=get")) != NULL) { if (statBuf.st_fab_rfm == FAB$C_VAR || statBuf.st_fab_rfm == FAB$C_VFC) { zptr = (sptr = aptr) + size; while (fgets (sptr, zptr-sptr, fptr)) sptr += strlen(sptr); size = sptr - aptr; } else size = fread (aptr, 1, size, fptr); if (Debug) fprintf (stdout, "%d bytes\n", size); fclose (fptr); if (!TotalFileCount) fprintf (stdout, "\ ------Total------ -----------Code------------ ----------Comment----------\n\ Lines Chars Lines Chars Lines Chars\n\ ------- --------- ------- ---- --------- ---- ------- ---- --------- ----\n\ "); if (size) { BothLineCount = BothCharCount = CodeCharCount = CodeLineCount = CommentCharCount = CommentLineCount = CommentCount = FileCharCount = FileLineCount = PrevCodeCharCount = PrevCommentCharCount = 0; TotalFileCount++; FileCharCount = size; zptr = (cptr = aptr) + size; while (cptr < zptr) { if (SAME2(cptr,'/*')) { /***********/ /* comment */ /***********/ cptr += 2; CommentCharCount += 2; CommentCount++; while (cptr < zptr && !SAME2(cptr,'*/')) { if (SLASHESC(cptr)) { CommentCharCount++; cptr++; } if (*cptr == '\n') { FileLineCount++; BothLineCount++; } if (!isspace(*cptr)) CommentCharCount++; cptr++; } if (cptr < zptr) { CommentCharCount += 2; cptr += 2; } } else if (SAME2(cptr,'//')) { /********************/ /* comment (to EOL) */ /********************/ cptr += 2; CommentCharCount += 2; CommentCount++; // to end of line while (cptr < zptr && *cptr != '\n') { if (SLASHESC(cptr)) { CommentCharCount++; cptr++; } if (!isspace(*cptr)) CommentCharCount++; cptr++; } if (cptr < zptr) cptr++; } else if (*cptr == '\"') { /***********/ /* literal */ /***********/ CodeCharCount++; cptr++; while (cptr < zptr && *cptr != '\"') { if (SLASHESC(cptr)) { CodeCharCount++; cptr++; } else if (*cptr == '\n') { FileLineCount++; BothLineCount++; CodeLineCount++; } CodeCharCount++; cptr++; } if (cptr < zptr) { CodeCharCount++; cptr++; } } else if (*cptr == '\n') { /************/ /* new line */ /************/ FileLineCount++; if (CodeCharCount > PrevCodeCharCount || CommentCharCount > PrevCommentCharCount) { BothLineCount++; if (CodeCharCount > PrevCodeCharCount) CodeLineCount++; PrevCodeCharCount = CodeCharCount; if (CommentCharCount > PrevCommentCharCount) CommentLineCount++; PrevCommentCharCount = CommentCharCount; } cptr++; } else if (!isspace(*cptr)) { /*************************/ /* significant non-space */ /*************************/ CodeCharCount++; cptr++; } else cptr++; } BothCharCount = CodeCharCount + CommentCharCount; TotalBothCharCount += BothCharCount; TotalBothLineCount += BothLineCount; TotalCharCount += FileCharCount; TotalCodeCharCount += CodeCharCount; TotalCodeLineCount += CodeLineCount; TotalCommentCharCount += CommentCharCount; TotalCommentLineCount += CommentLineCount; TotalCommentCount += CommentCount; TotalLineCount += FileLineCount; if (!DoOverAll) { if (strchr(fsptr,'*')) fprintf (stdout, "%s%*.*s\n", ResFileName, 78-ResFileNameLength, 78-ResFileNameLength, Dash80); fprintf (stdout, "%04d %7d %9d %7d %3d%% %9d %3d%% %7d %3d%% %9d %3d%%\n", TotalFileCount, FileLineCount, TotalCharCount, CodeLineCount, CodeLineCount * 100 / BothLineCount, CodeCharCount, CodeCharCount * 100 / BothCharCount, CommentLineCount, CommentLineCount * 100 / BothLineCount, CommentCharCount, CommentCharCount * 100 / BothCharCount); } } else fprintf (stdout, "%s-E-READ, %%X%08.08X %s\n", Utility, vaxc$errno, ResFileName); } else fprintf (stdout, "%s-E-OPEN, %%X%08.08X %s\n", Utility, vaxc$errno, ResFileName); free (aptr); } /**********/ /* report */ /**********/ if (!TotalFileCount) exit (status); if (TotalFileCount > 1) { if (!DoOverAll) fprintf (stdout, "%33.33s OVERALL %36.36s\n", Dash80, Dash80); fprintf (stdout, "%04d %7d %9d %7d %3d%% %9d %3d%% %7d %3d%% %9d %3d%%\n", TotalFileCount, TotalLineCount, TotalCharCount, TotalCodeLineCount, TotalCodeLineCount * 100 / TotalBothLineCount, TotalCodeCharCount, TotalCodeCharCount * 100 / TotalBothCharCount, TotalCommentLineCount, TotalCommentLineCount * 100 / TotalBothLineCount, TotalCommentCharCount, TotalCommentCharCount * 100 / TotalBothCharCount); } if (status == RMS$_NMF) status = SS$_NORMAL; return (status); } /*****************************************************************************/