LineCounter

Wersja 1.0, 13 kwietnia 2006

Wstęp

LineCounter to mały, przenośny program adresowany do programistów. Przeznaczony jest do zliczania sumarycznej liczby linii i znaków w plikach z kodem źródłowym danego programu. Został napisany w C++ i działa na konsoli tekstowej. Jest dostępny razem z kodem źródłowym na licencji GNU GPL. Program jest prosty, ale jednocześnie daje dość duże możliwości. Jego obsługa nie jest banalna, ale każdy programista powinien sobie z nią poradzić.

Przykładowe wyjście:

Analizowanie...
Katalogow: 3, plikow: 11
Wierszy: 5666, niepustych: 5044
Znakow: 168609 (164.66 kB), niebialych: 135169

Program napisałem w ciągu jednego dnia. Skłonił mnie do tego brak znanych mi narzędzi tego rodzaju, szczególnie na platformę Windows. Pod Linuksem owszem, można używać polecenia wc, a pod Windowsa jest wiele tego rodzaju programów (nierzadko bardzo rozbudowanych i płatnych), ale ja potrzebowałem czegoś, co po prostu pozwoliłoby mi szybko policzyć linie i pochwalić się kolegom, jak dużo kodu swojego silnika 3D już napisałem ;)

Projekt

LineCounter działa w oparciu o plik z rozszerzeniem LCP zwany projektem. Jego nazwę wraz z ewentualną ścieżką podaje się jako parametr do uruchamianego programu. W przypadku braku tego parametru program domyślnie szuka pliku o nazwie LineCounter.lcp w katalogu bieżącym.

Plik LCP jest plikiem tekstowym w języku XNL2, w kodowaniu jednobajtowym i z dowolnym formatem końca wiersza. Powinien mieć następującą składnię:

directories {
  ...
}

files {
  ...
}

W miejscu ... powinien znaleźć się zbiór reguł, a każda z nich w osobnej linii i w postaci słowa include lub exclude, a za nim maski z użyciem symboli wieloznacznych (ang. wildcards).

Program rozpoczyna analizę od katalogu bieżącego i ten katalog jest zawsze, bezwarunkowo analizowany. Analiza katalogu polega na wylistowaniu jego zawartości i każdy zawarty w nim plik może być wzięty pod uwagę do zliczania, a każdy podkatalog może zostać lub nie zostać rekurencyjnie przeanalizowany. O tym, czy dany plik lub katalog ma zostać przetworzony przez program, czy nie, decydują te właśnie reguły.

Dla każdego katalogu lub pliku program dopasowuje jego nazwę (wraz z pełną ścieżką) do kolejnych reguł. Maska może zawierać znaki specjalne:

Pozostałe znaki są traktowane dosłownie. Maska rozciąga się do końca linii - jest z punktu widzenia języka XNL2 tekstem i dlatego nie należy obejmować jej w cudzysłowy. Może zawierać dowolne znaki, także spacje. Separator katalogów w ścieżce można zapisywać jako / lub \ i nie robi to różnicy, zadziała pod każdym systemem. Wielkość liter podczas dopasowywania do maski nie jest uwzględniana.

Pierwsza znaleziona, pasująca reguła przerywa sprawdzanie i ostatecznie klasyfikuje dany plik lub katalog jako przeznaczony lub nieprzeznaczony do przetwarzania. Dlatego reguły węższe - np. wyłączające z analizy konkretne pliki - powinny poprzedzać reguły bardziej ogólne, np. akceptujące wszystkie pliki o danym rozszerzeniu. Katalog, do którego nie pasuje żadna reguła jest domyślnie akceptowany. Plik, do którego nie pasuje żadna reguła jest domyślnie odrzucany.

Czas na przykłady. Wyobraźmy sobie, że piszemy stronę WWW w PHP i chcemy policzyć statystyki całego projektu, czyli wszystkich plików o rozszerzeniu php w katalogu bieżącym i jego podkatalogach. Oto odpowiedni plik projektu:

directories {
}

files {
  include *.php
}

Wyobraźmy sobie teraz, że używamy przy tym dwóch bibliotek, które leżą w tym katalogu ale nie są nasze i dlatego nie chcemy ich uwzględniać. Jedna z nich mieści się w pliku lib.php, a druga zajmuje cały podkatalog o nazwie big_lib. Zmodyfikowany projekt będzie wyglądał tak:

directories {
  exclude big_lib
}

files {
  exclude lib.php
  include *.php
}

Katalogi

Podczas uruchamiania programu w grę wchodzą trzy różne katalogi:

  1. Katalog, w którym leży program wykonywalny
  2. Katalog, w którym leży plik projektu LCP (podajemy go jako parametr podczas uruchamiania programu)
  3. Katalog, w którym znajduje się kod do przeanalizowania (powinien to być katalog bieżący)

W najprostszym przypadku wszystkie trzy mogłyby być takie same, ale kopiowanie programu LineCounter do katalogu z twoim programem raczej nie miałoby sensu. Dlatego załóżmy na początek, że LineCounter znajduje się pod ścieżką C:\Program files\LineCounter\LineCounter.exe, a plik projektu LineCounter.lcp jak i kod programu leżą w katalogu D:\Programy\MojProgram. Wówczas prawidłowe uruchomienie programu polegałoby na:

  1. Przejściu do katalogu z kodem - wtedy stanie się bieżący
  2. Uruchomieniu programu - program sam znajdzie plik z projektem bo leży on w katalogu bieżącym i ma domyślną nazwę

Oto przykład z konsoli Windowsa:

C:\> cd D:\Programy\MojProgram

D:\Programy\MojProgram> "C:\Program files\LineCounter\LineCounter.exe"

Ponieważ w pliku projektu używamy ścieżek względnych, jest on niezależny od konkretnego kodu i dlatego można używać jednego, uniwersalnego projektu (jak ten dołączony domyślnie) do analizowania różnych swoich kodów. Wtedy plik LineCounter.lcp leży w innym katalogu, niż kod źródłowy - np. w katalogu z programem LineCounter. Wtedy trzeba podać ścieżkę do niego jako parametr uruchamianego programu:

C:\> cd D:\Programy\MojProgram

D:\Programy\MojProgram> "C:\Program files\LineCounter\LineCounter.exe" "C:\Progr
am files\LineCounter\LineCounter.lcp"

Może trochę to skomplikowane, ale myślę, że każdy sobie poradzi. Jeśli ktoś jest sprytny to może pokusić się nawet o napisanie sobie skryptu powłoki (BAT czy Bash) automatycznie uruchamiającej program z odpowiednim parametrem. Na przykład taki plik BAT:

@"C:\Program files\LineCounter\LineCounter.exe" "C:\Program files\LineCounter\LineCounter.lcp"
@pause

Autor

Dane autora:

Adam Sawicki
E-mail: regedit@regedit.gamedev.pl
Strona domowa: http://regedit.gamedev.pl

Copyleft © 2006 Adam Sawicki. Wszelkie prawa zastrzeżone. Program jest na licencji GNU GPL.

Podziękowania i pozdrowienia: