GNU Pascal Coding Standards

Copyright (C) 2001-2006 Free Software Foundation, Inc.

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the copyright holders.


Next: , Up: (dir)

Version

Prijevod dopunjen: 2003-04-27. Odgovara originalu od: 2006-02-02.


Next: , Previous: Top, Up: Top

1 O GNU Pascal Coding Standards

Napomena prevodioca:

Ovaj dokument sadrži prijevod teksta “GNU Pascal Coding Standards”. Za neke originalne engleske termine i izraze nisu nađeni zadovoljavajući prijevodi, pa se koriste ili engleski originalni izrazi, ili pak izrazi korišteni u žargonu struke. Za sva pitanja i povratne informacije glede prijevoda molimo kontaktirajte M. Todorovac mtodorov@alu.hr. Zahvaljujemo se svima koji su pomogli ovaj rad savjetima ili na drugi način. Kako se GPC intenzivno razvija, gdje god se pojavila razlika u ovom prijevodu u odnosu na engleski izvornik, treba uzeti izvornik kao točniji. Iznimke od ovoga će biti samo slučaj i samo iznimke.

GNU Pascal Coding Standards ("Standarde kodiranja u GNU Pascalu") je dizajnirala grupa volontera s GNU Pascal projekta. Cilj ovog dokumenta je proširivanje "GNU standarda kodiranja" (GNU Coding Standards) specifičnim informacijama o Pascal programiranju. Istini za volju, informacije sadržane u "GNU standardima kodiranja" uglavnom su relevantne za programe pisane u C jeziku. S druge strane, ta pravila također objašnjavaju mnoga pravila i principe koji su korisni za pisanje prenosivih, robustnih i pouzdanih programa. Mnoge od tih općenitih tema bi mogle biti dijeljene s ovim dokumentom uz samo nekoliko specifičnih primjedbi, tako da su pružene unakrsne reference koje će čitatelja povesti do općenitije informacije sadržane u "GNU standardima kodiranja".

Ovo izdanje GNU Pascal Coding Standards (GPCS) je nadopunjeno na dan 2006-02-02.

Dokument GNU Pascal Coding Standards je raspoloživ kao dio GPC distribucije – u binarnim distribucijama kao info datoteke, u distribucijama izvornog koda (source) također i kao Texinfo datoteke iz kojih se dodatni formati kao što su HTML, PostScript i PDF mogu generirati. HTML verzija je također raspoloživa na GPC matičnoj stranici, http://www.gnu-pascal.de.

Ispravke ili sugestije u vezi ovog dokumenta bi trebalo slati na GNU Pascal Compiler Documentation mailing listu, gpc-doc@gnu.de. Ako imate sugestiju, molimo uključite željenu verziju rečenica kako ih zamišljate u dokumentu; naše vrijeme je ograničeno. Context 'diff' izvorne Texinfo datoteke bi bio vrlo dobrodošao, ako je ikako moguće. Ako pak ne možete poslati 'context diff', molimo osjećajte se pozvanim da ipak svakako pošaljete svoju sugestiju.

Slijedeći ljudi su tirani, koji nameću svoj stil kodiranja zajednici programera: Peter Gerwinski `peter(at)gerwinski.de', Frank Heckenbach `frank(at)pascal.gnu.de', Markus Gerwinski `markus(at)gerwinski.de', Dominik Freche `dominik.freche(at)gmx.net', Nicola Girardi `nicola(at)g-n-u.de'.


Next: , Previous: Uvod, Up: Top

2 ... Ili kako zadržati software slobodnim ...

Ovo poglavlje iz 'GNU Coding Standards' raspravlja o tome kako učiniti sigurnim da GNU software ne zapadne u pravne poteškoće, i ostala srodna pitanja. See Intellectual Property.


Next: , Previous: Pravne začkoljice, Up: Top

3 Općenito o dizajnu programa

Ovo poglavlje raspravlja o nekim pitanjima koja biste trebali uzeti u obzir kod dizajna vlastitog programa.


Next: , Up: Savjeti glede dizajna

3.1 Koji jezik koristiti?

Osobno podržavamo ideju da je raznovrsnost programskih jezika dobra stvar i da su različiti jezici pogodniji za različite tipove zadataka. Za razliku od 'GNU Coding Standards', nećemo čitatelja pokušati uvjeravati da koristi C, Pascal niti bilo koji drugi jezik za sve zadatke.

Ako čitate ovaj tekst, već ste vjerojatno odlučili koristiti Pascal za neki projekt ili razmatrate njegovo korištenje. Ovaj dokument će sugerirati kako oblikovati vlastiti Pascal kod kad ste već odlučili da koristite GNU Pascal.


Next: , Previous: Programski jezik, Up: Savjeti glede dizajna

3.2 Povezivanje s bibliotekama C funkcija

Možete povezivati s C bibliotekama ili s C objektnim kodom vaše Pascal programe ili jedinice (`unit'). Molimo nadjite u GPC priručniku upute o tome kako se to izvodi. (see Other Languages)

Napose, za pristup C bibliotekama snažno preporučamo korištenje C wrappera. Ovo je pitanje prenosivosti. Mogu se pojaviti promjene između različitih verzija biblioteka koje bi utjecale na direktne `external' deklaracije u Pascal kodu. Trebali biste uskladiti wrappere tako da Pascal programi ili jedinice (`unit') rade s bilo kojom verzijom biblioteke koja vam je na raspolaganju.

U nekim situacijama kad rukujete s velikim paketima ne možete lako zadržati kompatibilnost između različitih verzija samih paketa. U ovakovom slučaju, možete povezivati (engl. linking) izravno s bibliotekom s kojom planirate raditi, te povežite u paket dodatnu C datoteku koja ne radi ništa osim provjere verzije. Evo primjera (na engleskom jeziku):

     #include <foo.h>
     #if FOO_MAJOR != 1 || FOO_MINOR != 2
     #error The GPC interface for libfoo was only written for libfoo-1.2.
     #error Please get libfoo-1.2 or check for a version of the GPC interface
     #error matching your version of libfoo.
     #endif

Primijeti korištenje `!=' umjesto `<' ili `>', kako bi se izvršila vrlo striktna provjera verzije. Molimo držite na umu da je ovo u redu ako postoji samo jedna implementacija biblioteke, npr. ovo možete s bibliotekom GTK, ali ne možete s libc, libm, curses itd.

Automatski prevodilac header datoteka je u planu koji bi učinio C wrappere suvišnima. Ovo je, međutim, nimalo trivijalan zadatak i nije sigurno da je u potpunosti moguć, tako da će potrajati neko vrijeme prije nego što bude na raspolaganju.

Možete uzeti kao pretpostavku da se GNU C prevodilac (engl. compiler) koristi da se prevedu wrapperi, kao i općenito bilo koji isječak C koda koji povezujete sa svojim Pascal kodom. Razlog za ovakvu pretpostavku je da jedino GNU C prevodilac garantirano ima sve konvencije kompatibilne s GNU Pascal prevodiocem na svakoj platformi na kojoj se oni vrte, s obzirom da dijele isti 'backend'. Također, GNU Pascal prevodilac je uvijek izgrađen zajedno s GNU C prevodiocem, tako da se može očekivati da je `gcc' raspoloživ uvijek kad je to slučaj i s `gpc'-om


Previous: Pascal i C, Up: Savjeti glede dizajna

3.3 Korištenje nestandardnih značajki

Pružene su mnoge GNU Pascal olakšice koje proširuju standardni Pascal jezik. Da li koristiti te ekstenzije u svojim programima je zamorno pitanje.

S jedne strane, korištenje ekstenzija može proizvesti čišći program. S druge strane - ljudi neće moći prevesti program ako GNU Pascal prevodilac nije na raspolaganju. One mogu prouzročiti da se program neće uspješno prevesti s drugim prevodiocima.

Općenito, najbolje je zadržati kompatibilnost prema drugim prevodiocima ili jezičnim standardima, ako je tu kompatibilnost lako postići. Međutim, na našu žalost, uz postizanje kompatibilnosti dobivate znatne poteškoće, pa i unazađenja. Na primjer, mogli biste morati dodati gomile `{$ifdef}'-ova da biste providjeli za neke nestandardne prevodioce, a oni pak čine kod težim sa čitanje, pisanje i održavanje. Još gore, `{$ifdef}'-ovi su sami po sebi nestandardna ekstenzija, tako da ne dobivate jako mnogo na ovaj način.

Na kraju, sugeriramo da se ne brinete previše za kompatibilnost. Sva sučelja (engl. interface) GNU Pascal prevodioca (sam prevodilac i tzv. Run Time System) su otvorena. To znači da ih se može implementirati za druge prevodioce kad je potrebno, ili se čak i sam izvorni kod može koristiti uz uvjet da je licenca poštovana (čitajte više o GNU General Public License - GNU općoj javnoj licenci na adresi http://www.gnu.org/copyleft/gpl.html), radije nego da se osakaćuje kod nekorištenjem proširenih značajki. Jedan (ograničen) primjer ove strategije je `gpc-bp' jedinica za Borland Pascal, distribuirana s GNU Pascal prevodiocem. Mogli biste poželjeti pogledati njeno sučelje da vidite što točno sadrži. Lako ju je proširiti s dodatnim mogućnostima za kompatibilnost prema potrebi, iako postoje značajke koje nije lako emulirati (posebno one koje imaju specijalnu sintaksu).

Molimo da ne koristite slijedeće mogućnosti, osobito one koje su implementirane samo zbog kompatibilnosti prema unatrag:

Tekst GNU Coding Standards ima lijepih primjedbi na ovu temu. See Using Extensions.


Next: , Previous: Savjeti glede dizajna, Up: Top

4 Kako bi se programi trebali ponašati

Ovo poglavlje iz teksta GNU Coding Standards opisuje konvencije za pisanje robustnog softwarea. Također opisuje opće standarde za poruke o greškama, sučelje naredbene linije (engl. command line interface), te kako bi se biblioteke trebale ponašati. Ohrabrujemo vas da slobodno pročitate taj dio teksta GNU Coding Standards. See Program Behavior.

Ovdje su, međutim, posebne dodatne upute za programiranje u Pascalu.

Izbor između signalnih funkcija, o kojem se govori u GNU Coding Standards, se obavlja u Run Time System-u tako da ne trebate brinuti o tome.

Slijedeće odstupanje od GNU Coding Standards je podrazumno ponašanje za provjere grešaka koje detektiraju “nemoguća” stanja. Mi sugeriramo da ne napravite samo abort programa. Ovo bi pretpostavljalo da svaki korisnik može biti programer, ali mi ne vjerujemo da je to realistično. Naš je savjet da ispišete razumnu poruku o grešci tako da korisnici mogu prijaviti opis buga programerima koji nisu sami primijetili bug ili ga ne mogu reproducirati.

Također, tekst GNU standardi kodiranja preporučuju provjeru povratne vrijednosti svakog sistemskog poziva da li je možda završio s pogreškom. To se odnosi na C. U Pascalu, provjera grešaka je često automatska, tako da se ne trebate mučiti s tim provjerama. Mnoge ulazno/izlazne (I/O) rutine ne vraćaju status (npr. `Reset'), ali one koje vraćaju bi obično trebalo provjeriti.

Naravno možete onemogućiti automatske provjere pogrešaka i obaviti provjeru sami. Istini za volju, neke greške mogu prouzročiti da program automatski prekine (abort) izvođenje s porukom o grešci. Umjesto toga, naročito u jedinicama (`unit') i modulima, mogli biste željeti prijaviti pogrešku i dati korisniku priliku da intervenira i popravi stvari. Da biste to učinili, morate koristiti `{$I-}' direktivu prevodioca, i provjeriti vrijednost `IOResult' (see IOResult) ili globalnih varijabli za pogreške kao što je `InOutRes' (see InOutRes). Primijetite da se pozivi I/O rutina trenutno vraćaju ako je `InOutRes' postavljen, tako da ga nije neophodno provjeravati nakon svake operacije, pa je moguće slijedeće:

     {$local I-}
     Rewrite (f, 'bla');
     WriteLn (f, 'foo');
     WriteLn (f, 'bar');
     WriteLn (f, 'baz');
     Close (f);
     {$endlocal}
     if InOutRes <> 0 then
       begin
         WriteLn (StdErr, GetIOErrorMessage);
         ...
       end;

Bilo kako bilo, u vašem kodu biste mogli poželjeti provjeriti `Rewrite' i druge sistemske pozive sa zadatkom otvaranja, za koje je najveća vjerojatnost da bi mogli završiti neuspješno; tako da izbjegnete daljnje nepotrebne pozive.

Postoji skup rutina u GPC jedinici za imenovanje privremenih (temporary) datoteka, konfiguracijskih datoteka, i mnogo drugih stvari povezanih s imenima datoteka. Prednosti korištenja ovih je da rade na različitim vrstama sistema (na primjer Unix i DOS), pa se eventualni budući problemi mogu riješiti na jednom mjestu u Run Time System-u radije nego u nekoliko različitih programa ili jedinica (unit).

Što se tiče biblioteka, sugeriramo da ne stavljate svaku rutinu u posebnu datoteku. Nadamo se da će jednog dana GNU Pascal prevodilac znati to napraviti automatski na nivou linkera (povezivača). Trenutno, vjerujemo da je ugodnost programera znatno važnija nego veličina proizvedene binarne datoteke. Također ne preporučamo korištenje prefiksa u imenima, budući da će konflikti biti razriješeni upotrebom kvalificiranih identifikatora (`UnitName.RoutineName') u budućnosti. Dotada, molimo, koristite privremena zaobilazna rješenja (engl. work-around) kad se pojave konflikti.


Next: , Previous: Ponašanje programa, Up: Top

5 Kako najbolje upotrijebiti Pascal

Ovo poglavlje daje savjete o tome kako najbolje iskoristi jezik Pascal kod pisanja softwarea. Naravno, pravila se odnose samo na kod koji se objavljuje – ako na primjer želite zakomentirati stvari sa staromodnim komentarima poput `(* ovoga *)', to biste trebali učiniti privremeno i ukloniti to prije distribuiranja koda. Ali s obzirom da nikad ne znate da li ćete i kada objaviti svoj kod, dobra je ideja prionuti uz pravila od početka.


Next: , Up: Programiranje u Pascalu

5.1 Natuknice za programiranje u Pascalu

Pascal izvorne datoteke trebaju imati `.pas' sufiks. Ime datoteke bez sufiksa treba obično odgovarati imenu programa/jedinice/modula, ali sve malim slovima. U jednoj datoteci bi trebao biti samo jedan program/jedinica/modul.

Kod se mora prevesti s `-Wall' opcijom, sa i bez `-O3' opcije i to bez upozorenja. (See Direktive prevodiocu, o tome kako namjerno zabraniti neka upozorenja ako je stvarno neophodno.)

Ne koristite automatske `Result' varijable u funkcijama. Ako želite jednu, deklarirajte ju:

     function Foo (...) = Bar: Integer;

Koristite deklaraciju sa `=', ne bez, osim ako ne želite striktnu PXSC kompatibilnost.

Ako funkcija vraća `Boolean' da indicira uspješnu operaciju, `True' treba značiti uspjeh, a `False' grešku, za razliku od nekih C funkcija gdje `0' znači uspjeh.

Izbjegavajte `goto' i slične naredbe, kao što su `Exit', `Return', `Break', `Continue'. Izbjegavajte `goto' pod svaku cijenu (osim možda ne-lokalni `goto' za povratak iz duboko ugniježđenih funkcija u slučaju pogreške). Izbjegavajte ostale ako je moguće uz razuman uloženi napor. Ako bi to zahtijevalo dodatnu `Boolean' varijablu, ovo se broji kao izgovor za korištenje ovih naredbi ako to stvarno želite. Primijetite da često kod postaje znatno jednostavniji izbjegavanjem korištenja `Break' itd. i korištenjem umjesto toga boljih uvjeta za petlje i drugačijih vrsta petlje.

Nikad ne modificirajte brojače `for' petlji, niti se oslanjajte na njihovu vrijednost nakon izlaska iz petlje (Ovo nije samo pitanje stila, to je definicija Pascala. Ti postupci proizvode nedefinirane rezultate.)

Nikad se ne oslanjajte na nedefinirano ponašanje. Na primjer, na to da su globalne varijable inicijalizirane na `0' na početku programa, ili možda na novo alociranu memoriju koja se čini kao inicijalizirana, ili na memoriju koja nakon dealociranja naizgled zadržava neke vrijednosti, ili na to da brojači `for' for petlji izgledaju kao da imaju neku vrijednost nakon petlje – ništa od ovoga nije garantirano, i ponašanje se može promijeniti kad promijenite prevodilac ili njegovu verziju, ili ako promijenite platformu.

Nedefinirano znači NEDEFINIRANO, i činjenica da takve stvari izgledaju kao da rade na svim sistemima koje ste provjerili, kao i sa 42 druga prevodioca, ne znači točno ništa.

U komparacijama stavite “jače promjenljiv” izraz na lijevu stranu:

     for i := 1 to 10 do
       if a[i] = Foo then
         for j := 1 to 10 do
           if b[j] = a[i] then ...

Ako promatramo drugi redak iz gornjeg primjera, izraz na lijevoj strani (a[i]) se mijenja svakom iteracijom petlje, dok s desnom stranom (Foo) to nije slučaj. (U ovom slučaju pretpostavljamo da je Foo konstanta ili funkcija koja ne ovisi o i ili nekim drugim globalnim podacima. Inače bi moglo imati smisla da se Foo stavi na lijevu stranu, i možda stavi još jedan komentar da se to istakne.)

Zadnji redak gornjeg primjera može izgledati čudno, jer b[j] i a[i] mogu izgledati kao da imaju isti stupanj “promjenljivosti”. Međutim, u stvari se j mijenja češće nego i, tj. svaki put kad se i promijeni, j se već promijenio 10 puta.

Izbjegavajte dupliciranje koda. Lako je podleći iskušenju kopiranja koda, ali postaje noćna mora održavanja da se kasnije promjene izvode na nekoliko sličnih mjesta. Koristite rutine ili potprograme, jedinice ili module, bilo što. Planirajte svaki dio koda tako da taj dio može biti proširen. Nemojte posezati za previše dosjetljivim trikovima na mjestima koja će vjerojatno kasnije biti mijenjana.

Ne okružujte pojedinačne naredbe s `begin' i `end', osim ako nemate problem s visećim `else' ili pojedinačna naredba čini čitavo tijelo funkcije! Vidi slijedeće primjere:

     if foo then
       begin
         if bar then
           baz
       end  { Izbjegni problem s visećim else. }
     else
       qux  { Jedno-linijska naredba. }

Ne pišite prazne inicijalizatore jedinica. Ovo je primjer što ne raditi:

     ...
     
     procedure Foo;
     begin
       ...
     end;
     
     begin
     end.

Umjesto toga, jednostavno:

     ...
     
     procedure Foo;
     begin
       ...
     end;
     
     end.

Ne pišite neiskorištene deklaracije, osim u sučeljima (`interface') koja su namijenjena za korištenje od strane programa koji ih importira.

Sjetite se da su `Boolean'i `Boolean'i. Molimo koristite `if Foo then' umjesto `if Foo = True then', te `if not Foo then' umjesto `if Foo = False then'. Također, koristite `until False' na mjesto `until 1 = 0' – ovo izgleda pametnije. Druga uobičajena situacija je `Foo := Expression' umjesto `if Expression then Foo := True else Foo := False'.

Izbjegavajte dupliciranje globalnih identifikatora, tj. nemojte preopterećivati (engl. overload) ugrađene identifikatore, (čak iako GNU Pascal prevodilac to dozvoljava) te ne koristite isti globalni identifikator u nekoliko jedinica (`unit') ili modula. (Ovo svojstvo će biti prisutno u GNU Pascal prevodiocu u budućnosti pod imenom “kvalificirani identifikatori” (engl. “qualified identifiers” ali ga svejedno nemojte koristiti.

Obeshrabrujemo korištenje globalnih varijabli za ne-globalne svrhe (npr. korištenje varijable Counter korištene kao brojač u raznim lokalnim potprogramima). Umjesto toga, deklarirajte brojačke varijable za svaki potprogram koji ih treba. Ovo generalno također omogućava bolju optimizaciju generiranog koda.

Kada trebate beskonačnu petlju (iz koje se može iskočiti sa `Break'), sugeriramo da koristite repeat petlju radije nego while petlju jer ona pomiče kod manje udesno (barem tamo gdje je više od jedne naredbe u petlji). Preciznije:

     repeat
       ...
     until False

Umjesto:

     while True do
       begin
         ...
       end


Next: , Previous: Izabrane natuknice, Up: Programiranje u Pascalu

5.2 Eksplicitna provjera interne konzistentnosti

Kao što je navedeno u dokumentaciji GNU C biblioteke (see Consistency Checking) - dok pišete program, često je dobra ideja ubaciti u njega provjere da li su prekršene neke osnovne pretpostavke.

Razmotrite slijedeću proceduru u Pascalu:

     procedure DoSomethingOnAPString (StrPtr: PString);

Možete implicitno pretpostaviti da gornja procedura nikad neće biti pozvana sa nil kao argumentom, ali je sigurnije provjeravati da li je došlo do “nemogućeg stanja”, tj. provjeriti da li je `StrPtr' različito od nil, kao ovdje:

     procedure DoSomethingOnAPString (StrPtr: PString);
     begin
       Assert (StrPtr <> nil);
       ...
     end;

Ako ova provjera ne uspije, program proizvodi `runtime' pogrešku – pogrešku za vrijeme izvođenja. Mogli biste zaključiti da je kod koji zove ovu proceduru pogrešan (ili da trebate proširiti nevedenu rutinu), dakle bi ovo mogla biti pomoć u lociranju problema. Drugim riječima, provjera bazičnih pretpostavki na početku tijela potprograma je pravi način da se učini sigurnim da funkcija nije korištena na krivi način.

GNU C biblioteka daje assert makro naredbu za ove vrste provjera. GNU Pascal proviđa Pascal ekvivalent koji se zove Assert, ali se ponaša malo drugačije. Assert neće prekinuti vaš program, nego će radije prouzročiti pogrešku u vremenu izvođenja, `runtime error', (see Assert) koju možete "uhvatiti" npr. `Trap' jedinicom (see Trap).

Jednom kad mislite da je vaš program debugiran, možete zabraniti provjere grešaka izvođene Assert rutinom jednostavnim ponovnim prevođenjem s `--no-assertions' opcijom. Nikakve promjene source koda nisu potrebne da bi se zabranile ove provjere. Izrazi sa side-efektima u argumentima za `Assert' se i dalje izračunavaju (za razliku od C-a), tako da je u redu napisati:

     Assert (MyFunction (Foo, Bar) > 0)

Ovim će se uvijek pozvati MyFunction, ali samo da se učini sigurnim da je njen rezultat pozitivan ako `--no-assertions' nije dan.

Svejedno, preporuča se da ne zabranjujete provjere konzistentnosti, osim ako nikako ne možete podnijeti da se vaš program izvodi nešto sporije.


Next: , Previous: Provjera konzistentnosti, Up: Programiranje u Pascalu

5.3 Formatiranje izvornog koda

Najprije, izbjegavajte nepotrebne razmake na krajevima redaka. Također zapamtite da ne snimate datoteke s TAB karakterima, s obzirom na činjenicu da će ih razni editori ili različite konfiguracije interpretirati kao različite količine razmaka, time lomeći uvučenost (engl. indentation) programa. (Ako koristite GNU Emacs, funkcija `untabify' dobro dođe pri ruci; ako koristite VIM, opcija `expandtab' (`:set et'); u PENG-u se može koristiti opcija `Expand tabs').

Molimo izbjegavajte korištenje bilo kakvih kontrolnih znakova, osim newline (znak za novi redak), naravno. Ovo znači nema form feed (`#12'), znakova za novu stranicu. Oni su preporučeni u GNU Coding Standards da razdvajaju logično odvojene dijelove, ali ih nemojte koristiti barem u Pascal kodu. Također nemojte koristiti ni znak `SUB', (`#26'), koji se pogrešno koristi kao end-of-file (kraj datoteke) indikator u DOS-u. Stariji DOS editori stavljaju taj znak na kraj svake datoteke bez dobrog razloga, jer čak i FAT file system zna pronaći kraj datoteke sam po sebi.

Preporučujemo maksimalnu duljinu retka od 68 znakova, tako da se može otisnuti u TeX-u sa default fontom na A4 papiru, ili 78 znakova, za ekrane sa 80 stupaca. Ovo nije fiksno pravilo, jer lomljenje redaka često smanjuje čitljivost koda.

Koristite prazne retke između blokova. Blokovi su dugi komentari, `type', `const', `var', `label' odsječci, tijela potprograma, inicijalizatori i finalizatori jedinica (`unit') i modula, `program', `unit', `interface', `implementation', `module', `export', `uses', `import' retci, globalne direktive prevodioca. Ako se dugi komentar odnosi na prateću deklaraciju, stavite samo prazni redak prije komentara, ne između komentara i same deklaracije. Posebna iznimka su blokovi unutar istog potprograma – ne koristite prazne retke na tim mjestima. Na primjer:

     procedure Short;
     var
       Foo: Integer;
       Bar: Char;
     begin
       ...
     end;

Ali se sjetite staviti prazne retke da razdvojite potprograme, kao u slijedećem primjeru:

     procedure Long;
     const
       ...
     var
       varijable korištene od Sub ...
     
       procedure Sub;
       var
         ...
       begin
         ...
       end;
     
     var
       varijable koje nisu korištene od Sub ...
     begin
       ...
     end;

Primijetite da ne biste trebali koristiti prazan redak nakon deklaracije glavnog potprograma, osim ako deklaracija ugniježđenog potprograma slijedi odmah. Inače bi deklaracija glavnog potprograma izgledala kao forward deklaracija.

Primijetite da smo u odsječku koda odvojili lokalne varijable (ili konstante) prije i poslije potprograma – ovo nije obavezno.

Naravno, ono što smo rekli za potprograme je također ispravno za pod-potprograme na bilo kojoj dubini.

Prazni redak bi trebao biti među varijablama istog tipa, gdje je to prikladno, da ih se logički razdvoji. U slučaju da se komentar pojavljuje prije deklaracije, prazna linija mora biti prije komentara. Inače prazna linija dolazi prije deklaracije.

Prazni retci se mogu koristiti u dugim komentarima da razdvoje paragrafe.

Bez praznih redaka na početku ili kraju datoteke, samo znak za novi red na kraju. Bez višestrukih praznih redaka.


Next: , Previous: Formatiranje, Up: Programiranje u Pascalu

5.4 Komentiranje vašeg rada

Komentare treba staviti u vitičaste zagrade kao ovdje:

     { Ovo je lijepi komentar. :-) }

Ne koristite komentare starog stila između okruglih zagrada i zvjezdica, kao npr. ove:

     (* Ovo je ružan komentar :-(, kakav ne biste smjeli koristiti. *)

Također, ne koristite komentare započete s dvostrukom kosom crtom:

     // Još jedan primjer komentara koji ne koristiti.

Iako ISO Pascal eksplicitno dozvoljava miješane komentare, GNU Pascal prevodilac ih uopće ni ne prihvaća, ako ih ne uključite opcijom ili odgovarajućom direktivom prevodiocu `{$mixed-comments}' – ali to ne želite učiniti. Ovdje je nekoliko primjera miješanih komentara, koje ne biste smjeli slijediti:

     (* This ... }
     { ... and that. *)

Također, nastojte izbjegavati ugniježđene (engl. nested) komentare, kao `{ { Ovaj ovdje } }'. Ovi su u redu ako želite staviti nešto TeX naredbi u komentar ili nešto više egzotično. Koji god razlog imate za korištenje ugniježđenih komentara, potrebno je da ih omogućite direktivom prevodiocu, `{$nested-comments}'. Ne koristite `--nested-comments' opciju naredbene linije. Stavite sve takve opcije u izvorni kod, tako da netko pokušavajući prevesti ga ne mora ispitivati koje su opcije naredbene linije potrebne, te zato jer bi opcije komandne linije pogodile sve izvorne datoteke, npr. kad se prevodi projekt sa više jedinica/modula.

Molimo pišite vaše komentare na engleskom, jer je engleski jedini jezik kojeg gotovo svi programeri u svim zemljama mogu čitati. Ako ne pišete dobro engleski, molimo pišite komentare na engleskom najbolje što možete, pa onda tražite druge ljude da vam pomognu preformulirati ih. Ako ne možete pisati komentare na engleskom, molimo pronađite nekoga da radi s vama i prevede vaše komentare na engleski.

trebali biste usvojiti “French Spacing”, tj. samo jedan razmak na kraju rečenice. Tako ne možete koristiti GNU Emacs `M-a' i `M-e' kombinacije tipki za kretanje između rečenica. Nadamo se da možete živjeti bez toga. Također, molimo stavite samo jedan razmak nakon vitičaste zagrade koja otvara komentar i prije zatvarajuće zagrade.

Ako se komentar odnosi samo na jednu liniju koda, napišite ga ako je moguće nakon linije koda, u istom retku, odvojenog od koda s dva razmaka. Ovo je također dozvoljeno za `interface' odsječak jedinice (`unit') i za globalne varijable. Često je vjerojatno da ćete pisati ovu vrstu komentara uz `record' i `object' polja. U ostalim slučajevima, komentari idu u jedan ili više vlastitih redaka, ako npr.:

     { foo bar baz }

Ili duže:

     { foo bar
        baz }

Ili s paragrafima:

     { foo bar
        baz
     
        qux }

Komentari trebaju biti smješteni prije koda koji opisuju, i trebaju imati isti nivo uvlačenja retka. Slijedeći primjer bi to trebao pojasniti:

     { Moji tipovi. }
     type
       ...
     
     type
       { Moji prvi tipovi. }
       Foo = Integer;
       ...
     
     begin
       { Moja prva naredba. }
       Bla;
       { Početak petlje. }
       repeat
         { Tijelo petlje. }
         ...
       { Završi kad se Nesto desi }
       until Nesto
     end;

Primijeti poziciju komentara uz `until'.

Komentari koji opisuju globalnu deklaraciju bi trebali biti u jednoj ili više vlastitih linija, neposredno prije deklaracije. Na primjer:

     { Ovo je Foo. Radi ovo i ono. }
     procedure Foo;

Ne pišite “trivijalne” komentare, poput onih u gornjim primjerima. Trebali biste izbjegavati komentare pišući jasan kod. Linus Torvalds ističe ovo snažno u 'Kernel Coding Style':

Comments are good, but there is also a danger of over-commenting. Never try to explain how your code works in a comment: it's much better to write the code so that the working is obvious, and it's a waste of time to explain badly written code. Generally, you want your comments to tell what your code does, not how.

Prijevod:

Komentari su dobri, ali postoji također opasnost od prekomjernog komentiranja. Nikad ne pokušavajte objasniti kako vaš kod radi u komentaru: mnogo je bolje napisati kod tako da je njegovo `funkcioniranje' očito, i gubitak je vremena komentiranje loše napisanog koda. Općenito, možete željeti za vaše komentare da kažu što vaš kod radi, ne kako.

(Primijetite da mi inače poprilično odstupamo od Linusovog stila kodiranja.)

“Tricky” kod je vrijedan komentiranja. “Tricky” kod definiramo kao kod koji radi ne tako očite stvari, podrazumijeva pretpostavke koje nisu očigledne, postoji nešto o čemu se mora voditi računa prilikom njegovog mijenjanja, nije ono što izgleda na prvi pogled, postoje nuspojave (side-effect) ili zahtijeva druge dijelove koda da budu promijenjeni simultano s njim. Tricky kod bi se trebao koristiti vrlo štedljivo.

U slučaju da se komentar odnosi na neko drugo mjesto u kodu, bilo u istoj ili u drugoj datoteci, molimo referirajte na to mjesto ne s brojem retka (ovaj će se previše često mijenjati), nego pomoću imena potprograma ili pomoću konteksta. Također, razmislite da je korisno staviti komentar na to drugo mjesto koji pokazuje natrag. (Ne uvijek, ali ponekad se to pokazalo korisnim za nas.)

Da se zakomentira dio koda, koji se ne bi trebao prevesti, trebate ga omeđiti sa `{$if False} ... {$endif}' radije nego da koristite komentar.

Da se razdvoje logični dijelovi unutar velikih modula ili jedinica, možete koristiti specijalni komentar – mi predlažemo fiksan uzorak jer ga je lako pronaći:

     {@section Ime odsječka}
     {@subsection Ime pododsječka}

Primijeti da nema razmaka iza otvorene vitičaste zagrade, niti ispred zatvorene u ovom slučaju.

Modul ili jedinica (`unit') treba imati komentar za svaku od svojih 'interface' deklaracija, tako da je 'interface' dio datoteke sa izvornim kodom pouzdan izvor dokumentacije. Ovo je opcionalno za bilo koju deklaraciju koja se pojavljuje samo u 'implementation' dijelu ili u `program'ima. Naravno, nekoliko srodnih deklaracija (npr. grupe konstanti) mogu dijeliti komentar.

Utility nazvan `pas2texi' će biti napisan da omogući izgradnju Texinfo datoteka iz Pascal komentara. Ovo će omogućiti pojedine vrste formatiranja i naglašavanja unutar komentara. Oni će biti opisani u dokumentaciji `pas2texi' programa i/ili u budućim verzijama ovog dokumenta.

Možete koristiti “fixme” komentare, da biste ukazali na stvari koje treba ispraviti u kodu, ili u biblioteci (ili modulu, ili jedinici, ili korištenom prevodiocu) koje direktno pogađaju kod, zahtijevajući zaobilazni pristup (engl. work-around). Ovi komentari trebaju imati na početku barem dva `@' – dodajte toliko `@' koliko je urgentno pitanje koje opisuju.

Ovi komentari mogu sadržavati manje ili više opskurne detalje o problemu, naročito ako je korijen problema negdje drugdje. Na primjer, komentar `{ @@fjf226 }' deklarira prateći kod kao zaobilaznicu za problem koji je demonstriran u GNU Pascal prevodiočevom test programu `fjf226.pas'. (To je datoteka koju možete pronaći u source distribuciji GNU Pascal prevodioca.)

“Fixme” komentare ne bi se smjelo miješati s običnim komentarima. Ako trebate obje vrste, koristite ih odvojeno, čak i ako direktno slijede jedan drugoga. Oni se mogu koristiti bilo gdje, čak i unutar naredbi, jer su privremeni po naravi. Većina normalno pada u područje tijela, osim ako utječu na sučelja (`interface'). Specijalno sučelja za koja je vjerojatno da će biti promijenjena trebaju imati `@@' komentar neposredno prije njihovog opisnog (deskripcijskog) komentara.


Next: , Previous: Komentari, Up: Programiranje u Pascalu

5.5 Redoslijed blokova koda

Molimo započnite svaku datoteku sa komentarom koji sadrži, u slijedećem redoslijedu:

Općenito, mogli biste pratiti slijedeći redoslijed deklaracijskih blokova:

Možete odstupiti od ovog poretka kad je neophodno ili to čini kod više čitljivim. Ovo je jedan primjer gdje poredak ne može biti poštovan:

     type
       TNesto = record
         Ovo, ono: Integer
       end;
     
     const
       NekaKonstanta = SizeOf (TNesto);

Gornja pravila se primjenjuju na deklaracijske blokove i u potprogramima.

Kad postoji nekoliko više ili manje neovisnih dijelova, posebno u velikim jedinicama ili modulima, možete primijeniti ovaj redoslijed unutar svakog dijela. Ne stavljajte, na primjer, konstante svih dijelova zajedno. Morate održati kod čitljivim.

Varijable koje se koriste samo u glavnim programima moraju biti deklarirane globalnim u Pascalu, iako GNU Pascal nudi ekstenziju koja dozvoljava deklariranje varijabli na proizvoljnim mjestima u kodu (see var). U ovom slučaju, kao kontrast prethodnom općem pravilu, često je bolje staviti njihovu deklaraciju upravo prije `begin' glavnog programa, nakon svih potprograma itd., naročito kad je više nego nekoliko takvih varijabli i veličina izvorne datoteke nije malena. Tako, blok deklaracije varijabli je lakše uočljiv i lakše se mijenja od strane programera dok se uređuje glavni program, i tako činite sigurnim da ih potprogrami slučajno ne bi upotrijebili.

Kada definirate tip zajedno s njegovim pokazivačkim tipom, najprije deklarirajte pokazivač. Lakše ih je prepoznati osobito ako je tip dugački record ili object. Također, time postaje moguće korištenje rekurzivnih struktura (npr., korištenje pokazivača na tip unutar tog istog tipa). Trebali biste staviti predmetak `T' imenu tipa i `P' asociranom imenu tipa pokazivača. Pogledajmo primjer:

     type
       PMojInt = ^TMojInt;
       TMojInt = Integer;
     
       PListaNizova = ^TListaNizova;
       TListaNizova = record
         Next: PListaNizova;
         s: TNiz
       end;

Primijetite da je `Next' polje specificirano prvo. Sugeriramo da ga uvijek stavljate kao prvo polje kod rekurzivnih tipova, budući da to dozvoljava nekim generičkim potprogramima za rad s listama da budu nešto malo efikasniji dok 'putuju' listom, tj. nema offseta.

Sugeriramo stavljanje svih pokazivačkih tipova unutar svake `type' deklaracije na prvo mjesto, iako to ne smatramo obaveznim. Ovo je primjer:

     type
       { Pokazivački tipovi }
       PFoo = ^TFoo;
       PBar = ^TBar;
       PBaz = ^TBaz;
     
       { Neki vlastiti cjelobrojni tipovi }
       TFoo = Integer attribute (Size = 16);
       TBar = Cardinal attribute (Size = 16);
       TBaz = Cardinal attribute (Size = 32);

Unutar objektnih tipova možete imati tri deklaracijska područja. Postoje tri rezervirane riječi za započinjanje takvih područja: `public', `protected', `private'. Unutar svakog od tih područja slijedite slijedeći redoslijed:

U `implemetation' dijelu objekta, stavite tijela potprograma u istom redoslijedu u kojem se pojavljuju u deklaraciji u `interface' dijelu. Ovo se također odnosi na jedinice i module, u kojima implementacija treba odražavati `interface' deklaracije.

Nemojte koristiti završni `;' na kraju bloka, tj. ispred `end', `until', itd. osim `case' – zadnja grana prije `else' grane bi trebala imati `;', da se izbjegnu problemi poput:

     case ...
       Foo:
         if Bar then  { naknadno umetnuti }
           begin
             ...
           end  { ako ovdje nema `;' ... }
       else  { ... ovo će biti pogrešno uzeto kao `then'-ov `else' }
         ...

(Isto ako je `if' bio tamo duže i `else' grana od `case' je kasnije umetnuta.)

U objektu, može izgledati čudno da se izostavi `;' nakon zadnjeg člana koji je najčešće metoda. Stoga ga dozvoljavamo, a radi konzistentnosti također i u `record'-ima.


Next: , Previous: Redoslijed, Up: Programiranje u Pascalu

5.6 Velika i mala slova u imenima

Rezervirane riječi bi trebale biti kompletno u malim slovima, uključivo direktive, tj. riječi koje su rezervirane samo u nekim kontekstima, kao `protected'. Ako koristite direktive kao identifikatore (za što je vjerojatno da će vam nanijeti bol) izvan njihovog konteksta, pišite ih kao identifikatore.

Kao specijalnu iznimku, možete koristiti `File' pisan velikim početim slovom kad je korišten kao tip sam po sebi tj. netipizirana datoteka, za razliku od `file of Char'. Isto se ne može reći za `procedure' kao tip (u stilu Borland Pascala), budući da `File' može biti valjan tip, dok je `procedure' konstruktor tipa, tj.:

     procedure Foo (var a: File);  { Ovo radi. }
     procedure Foo (var a: procedure);  { Ovo baš i ne. }

Slijedeći problem su velika i mala slova u identifikatorima. Nema razlike između ugrađenih (built-in) i korisnički definiranih (user-defined) identifikatora. Samo prvo slovo bi trebalo biti veliko, ili ako se sastoji od više spojenih riječi ili kratica, početno slovo svake od riječi bi trebalo biti veliko – ne koristite znak za podvlačenje (underscore). Kratice koje su postale dio govornog jezika mogu biti pisane kao takve. Na primjer, `Dos' ili `DOS'; ali uvijek `GPC', ne `Gpc'. Ovdje su neki primjeri identifikatora: `Copy', `SubStr', `BlockRead', `IOResult', `WriteLn', `Sqr', `SqRt', `EOF', `EOLn'.

Ova se pravila primjenjuju i na identifikatore konstanti, također – za razliku od C makroa.

Također primijetite da se vrlo mali identifikatori mogu pisati u cijelosti malim slovima, kao `i' ili `s1' ili `xx'. Takve kratke identifikatore bi trebalo koristiti samo lokalno. Mogu biti korišteni kao parametri globalnih potprograma, jer je područje valjanosti (engl. scope) takvih identifikatora također lokalno, i njihova imena zapravo nisu od nikakva značaja pozivanom potprogramu. Korištenje ovakvih identifikatora u globalnom kontekstu bi svakako trebalo izbjeći, posebno u jedinicama (unit), modulima ili bibliotekama (jer autor ne zna u kojem će se kontekstu koristiti).

Molimo budite konzistentni sa vašim izborom velikih i malih slova. Znate da vas Pascal neće ozlijediti ako mijenjate taj izbor kroz kod, ali molimo vas držite se istog izbora.

Za identifikatore za vrijednosti pobrojanih (`enum') tipova i za blokove konstanti, tj. mjesta gdje uvodite mnogo identifikatora može biti korisno koristiti dvoslovni prefiks malim slovima i `_', kao kontrast prethodnim pravilima:

     type
       TFooBar = (fb_Foo, fb_Bar, fb_Baz, fb_Qux);
     { Moji Foo-ovi }
     const
       mf_Foo = 1;
       mf_Bar = 3;
       mf_Baz = 42;

U objektno-orijentiranom kodu (posebno u konstruktorima), često postoji potreba da parametar korespondira polju objekta (npr., da se proslijedi vrijednost kojom se inicijalizira polje). Budući da se oba ne mogu zvati istim imenom, polje bi trebalo imati “prirodno” ime budući da se obično koristi u više rutina, a ime parametra bi trebalo biti promijenjeno (engl. “mangled”) FIXME: Još nismo pronašli zaista zadovoljavajuće pravilo za ovu modifikaciju (neki koriste `a' kao prefiks), i ako imate bilo kakvu dobru ideju, javite nam.

Što se makroa tiče, izričito preporučujemo da ih uopće ne koristite. Molimo, ne koristite makroe u svojih programima. Pokušajte izbjeći makroe u svojim programima, jer su oni zli. Vjerujemo da ne smijete koristiti makroe u svojem kodu. Nakon svega rečenog, ako se i dalje usudite koristiti makro, pišite ih potpuno velikim slovima i razdvojite riječi znakom za podvlačenje, `_'. Kako makroi ne poštuju Pascalove domene deklarirarnosti (engl. scope), ima smisla pisati ih drugačije. Ovo se odnosi na uvjetne direktive, također.


Next: , Previous: Velika i mala slova, Up: Programiranje u Pascalu

5.7 Korištenje naredbi prevodiocu

Općenito sugeriramo korištenje direktiva prevodiocu toliko malo dok je to još moguće i razumno, jer one čine kod težim za razumijevanje (npr. kad provjeravate nuspojave (side-effects)) i modificiranje (npr. kad se pomiču dijelovi koda iz ili u područje djelovanja direktiva prevodiocu). Direktive bi trebalo pozivati kao u primjeru:

     {$vaša-direktiva-prevodiocu}

Definitivno ne ovako (see Komentari):

     (*$nemoj-koristiti-ovakvu-direktivu*)

Također, definitivno ne na ovaj način, koji ovisi o lomljenju linija, što sa Pascalom normalno nije slučaj:

     #vaša-direktiva-prevodiocu

Slično vrijedi za makro definicije:

     {$define ...}

Ovo također ušteđuje pisanje obrnute kose crte prije prekidanja linija, kao kontrast prema `#define'. Ali vi ionako nećete koristiti makroe, zar ne? (see Velika i mala slova)

Što se razmaka tiče, ne tipkajte razmak ispred zatvarajuće vitice, kako ne može biti jednoga niti poslije otvarajuće vitice. Ako spajate mnogo direktiva zajedno, ne stavljajte razmake između svake, jedan zarez je dovoljan.

Unutar direktiva ne bi trebalo biti komentara. Pišite ih odvojeno umjesto toga, kao ovdje:

     {$X+}  { Trebamo extended sintaksu. }

Borland Pascal dozvoljava miješanje komentara s direktivama, no realno gledano to je pogrešno korištenje.

Kratke forme pozivanja direktiva su u redu, no duge forme su barem jednako dobre, ako već nećemo reći preferirane. Kratke forme se moraju pisati velikim slovima, a duže malim (osim za argumente osjetljive na 'veličinu' slova (engl. case-sensitive), kao što su poruke i imena datoteka – naravno, imena datoteka moraju uvijek biti tretirana kao case-sensitive, čak i na DOSu, da se sačuva prenosivost koda).

Možete kombinirati nekoliko direktiva, također i miješati duge i kratke, u jednom jedinom pozivu, na primjer kao u slijedećem:

     {$gnu-pascal,I-,X+}

Svaka jedinica ili modul bi trebala imati `{$gnu-pascal,I-}' ili `{$gnu-pascal,I+}' blizu početka (nakon komentara u zaglavlju s opisom i licencom). `{$gnu-pascal}' omogućuje jedinici da bude prevedena bez opcija za dijalekte čak i ako je glavni program preveden s nekima od njih. `{$I-}' ili `{$I+}' govori korisniku (iako je jedno od ovog podrazumno stanje) da li jedinica obrađuje sama ulazno/izlazne pogreške ili im dozvoljava da one izazovu pogreške u vremenu izvođenja (`runtime error'). Prvi pristup je poželjniji za većinu jedinica. Za programe, ova stavka je opcionalna. Rutine koji vraćaju ulazno/izlazne pogreške bi trebale imati atribut `iocritical' (see attribute):

     procedure CriticalRoutine; attribute (iocritical);

`{$W-}' (no warnings – bez upozorenja) smije se koristiti samo lokalno, i mora imati “fixme” (popravi me) komentar (see Komentari), jer situacija indicira problem s kodom ili s prevodiocem.

Molimo, nemojte onemogućivati upozorenja kad ste samo prelijeni da napišete kod koji ne proizvodi upozorenja.

Svaka zastavica prevodioca koja nije postavljena globalno (na primjer, zajedno s `{$gnu-pascal}', vidi gore) treba biti postavljena s `{$local ...}'. Drugim riječima, ne ovako:

     {$I-} Reset (f); {$I+}

Nego ovako:

     {$local I-} Reset (f); {$endlocal}

Prvo je pogrešno ako je `{$I-}' već bio postavljen. Čak i ako programer može znati i uzeti u obzir koje je globalno postavljeno stanje, ovo se može u neko vrijeme promijeniti, ili se dio koda može kopirati ili premjestiti. Zadnja forma je sigurnija u ovim slučajevima.

Da bi to učinili još i jasnijim, iz zadnja dva pravila slijedi:

     {$local W-} Foo; {$endlocal}  { @ GPC proizvodi suvišno upozorenje }

Opet, nastojte izbjegavati lokalne direktive. `{$I-}' je ponekad potreban. `{$X+}' može biti korišten ako je stvarno, stvarno neophodan (što je više moguće lokalnije): izbjegavajte aritmetiku pokazivača.

Ne koristite `{$X+}' da ignorira rezultate funkcija, ne koristite `{$ignore-function-results}', također. Previše je lako da se ignorira rezultat koji se ne bi trebao. Ponekad, posebno kad se povezuje s stranim C bibliotekama, mogli biste se susresti sa funkcijama koje imaju suvišan rezultat, koji vjerojatno ne biste željeli provjeravati. Možete deklarirati takve funkcije s `ignorable' specijalnim atributom, tako da će njihove povratne vrijednosti biti tiho ignorirane.

Koristite dummy varijable ako želite ignorirati rezultat pojedinog poziva rekurzivne funkcije čiji rezultat ne bi trebalo ignorirati generalno. Ali u takvim slučajevima provjerite pažljivo da li se rezultat može sigurno ignorirati. Ako bi, međutim, neočekivan rezultat indicirao “nemoguću” situaciju, obično je bolje provjeriti rezultat i ispisati upozorenje o neočekivanom slučaju, barem ako je `DEBUG' definiran (see Direktive prevodiocu).

Direktive povezivaču (engl. linker) tj. `{$L}' za biblioteke i C (ili drugi jezik) izvorne datoteke bi trebalo staviti blizu početka i brzo nakon `implementation' retka u jedinicama i modulima. Nekoliko biblioteka i C datoteka u jednoj direktivi su mogući ako logički pripadaju zajedno (na primjer, biblioteka i njezini C wrapperi), ali ne za odvojene stvari. Ovu se direktivu ne bi smjelo miješati s drugim direktivama (što čak niti ne funkcionira ako `L' dolazi prvi – suprotno bi moglo raditi, ali se ne bi trebalo koristiti). Eksterne deklaracije biblioteke ili C rutina bi trebale neposredno slijediti direktivu (osim u jedinici ili modulu za one koje ulaze u sučelje - interface). Korištenje `{$L}' u programima često nije dobra ideja, pisanje jedinice (`unit') je često dobro za apstrakciju i mogućnost ponovnog korištenja koda.

Uvjetno prevođenje bi ponekad moglo biti korisno, ali biste trebali koristiti toliko malo `{$ifdef}'-ova koliko je to moguće, budući da oni smanjuju čitljivost. Kad se kondicionali koriste zbog razlika među sistemima, provjerite značajke (na primjer, `__BYTES_LITTLE_ENDIAN__') ili grupe sistema (na primjer, `__OS_DOS__') radije nego pojedine sisteme, da biste bolje providjeli za sisteme koje ne poznajete ili koji možda još i ne postoje.

Ako je moguće (ovo možda još nije na raspolaganju), koristite predefinirane konstante (na primjer, `BytesBigEndian', `OSDosFlag') radije nego `define' konstrukte za kod gdje je to moguće – (“uvijek netočne” grane će biti dokinute u optimizatoru, ali ćete još uvijek dobiti provjeru sintakse kao dodatnu dobrobit pored činjenice da niste koristili preprocesor); za deklaracije tipova ovo obično nije moguće i morat ćete koristiti `define' konstrukcije. Dobar primjer je deklaracija tipa `TWindowXY' u CRT jedinici. Pogledajte:

     TWindowXYInternalCard8 = Cardinal attribute (Size = 8);
     TWindowXYInternalFill = Integer attribute (Size = BitSizeOf (Word) - 16);
     TWindowXY = packed record
       {$ifdef __BYTES_BIG_ENDIAN__}
       Fill: TWindowXYInternalFill;
       Y, X: TWindowXYInternalCard8
       {$elif defined (__BYTES_LITTLE_ENDIAN__)}
       X, Y: TWindowXYInternalCard8;
       Fill: TWindowXYInternalFill
       {$else}
       {$error Endianness is not defined!}
       {$endif}
     end;

`DEBUG' zastavica bi se trebala koristiti samo (i baš samo) za kod koji pomaže uklanjanju bugova, tj. kod koji ne mijenja realnu funkcionalnost. Programi se moraju moći uspješno prevesti sa postavljanjem `DEBUG' i bez njega. Prvo se može izvršavati sporije i može pružiti korisne dodatne poruke u pogodnom obliku, tj. jasno označene kao debug poruke, na primjer prefiksom `DEBUG: ', i mogu prekinuti program kad detektiraju pogrešna ili dubiozna stanja.

Kondicionali se mogu također koristiti da se naprave različite verzije nekog koda, npr. koristeći GMP brojeve ako je uvjet zadovoljen odnosno normalne cijele ili realne brojeve u drugom slučaju (GMP je biblioteka za rad s proizvoljno velikim brojevima). U ovom slučaju, ime i značenje svih takvih define konstrukcija mora biti objašnjeno pri vrhu. (Na primjer, vidi `__BP_TYPE_SIZES__', `__BP_RANDOM__' i `__BP_PARAMSTR_0__' u System jedinici.) Kod se mora ispravno prevesti s bilo kojom kombinacijom postavljenih kondicionala, što znači da morate testirati eksponencijalno rastući broj slučajeva – ovdje leži dobar razlog da se njihov broj drži toliko malim koliko je to moguće.

Druga slična upotreba kondicionala je da se izabere između različitih implementacija. Ovu biste strategiju smjeli koristiti samo ako su sve implementacije podržane ili ih planirate podržati. U drugim slučajevima, bolje je premjestiti staru implementaciju u “muzej” i držati kod čistim. Sve primjedbe o prevođenju koda iz prethodnog pravila se također primjenjuju i ovdje.

Kad trebate koristiti komplicirane kondicionale, koristite Pascal sintaksu, tj. formatirajte kondicionale u skladu s pravilima Pascal koda, radije nego prema C sintaksi. Ovo je smiješan primjer:

     {$if defined (Foo) or False}

Namjesto toga, ovo je primjer koji ne slijediti:

     {$if defined (Foo) || 0}

Ili još gore:

     #if defined (Foo) || 0

Specijalni kondicional se treba koristiti da se privremeno 'zakomentira' kod. Ovdje je prikladna sintaksa:

     {$if False} ... {$endif}

Standardno bi se uvjetna naredba trebala koristiti u programima ili jedinicama ili modulima koje distribuirate kako biste učinili sigurnim da je korištena ispravna verzija GNU Pascal prevodioca. Možete slijediti ovaj obrazac:

     {$if __GPC_RELEASE__ < 20020510}
     {$error This unit requires GPC release 20020510 or newer.}
     {$endif}


Next: , Previous: Direktive prevodiocu, Up: Programiranje u Pascalu

5.8 Kako koristiti razmake u kodu

Općenito, nikakvi se višestruki razmaci ne bi trebali koristiti osim za uvlačenje redaka (indentation) i osim slučajeva opisanih niže.

Jedan razmak ide prije i poslije operatora, poslije `:=' i `..', kao i `:' u `Write', `WriteLn' i `WriteStr'; nakon zareza i drugih upotreba `:'. Slijedeći primjer bi to trebao pojasniti:

     var
       Foo: Integer;
       ...
     begin
       Foo := 42;
       WriteLn (Foo + 3 : 5, ' bar')
     end;

Ne bi trebalo stavljati razmak prije unarnog `-'. U stvari, ove su forme korektne: `x - 1', `-x', `-1'.

Razmak mora ići prije otvorene zagrade (`(') i nakon zatvarajuće zagrade (`)'), osim ako nije susjedna drugoj zagradi, uglatoj zagradi, `^', `;', ili `,'. Drugim riječima, razmak ide između identifikatora ili ključnih riječi i otvorene zagrade (`('). (Svi ostali razmaci u ovom primjeru se podrazumijevaju po prethodnom pravilu.) Pogledaj:

     Foo (Bar^(Baz[Qux * (i + 2)]), Fred (i) + 3);

Za indeksiranje polja zapravo nemojte koristiti razmak prije otvorene uglaste zagrade, tj. `Foo[42]' radije nego `Foo [42]'. Međutim, umetnite razmak prije otvorene uglaste zagrade u deklaracijama polja, kao ovdje:

     Foo: array [1 .. 42] of Integer;

Razmak dolazi prije otvorene uglaste zagrade konstruktora skupa (`set') u nekim situacijama – ove zagrade bi trebalo tretirati kao okrugle, za razliku od uglatih zagrada u indeksiranju polja.

Na primjer:

     x := [0, 2 .. n];

Ali:

     Foo ([1, 2, 3]);

Nema razmaka uz `.' i `^':

     Rec.List^.Next^.Field := Foo

Kao što smo već istaknuli, jedan razmak ide nakon otvorene vitice i nakon zatvarajuće vitice u komentarima, ali ne i u direktivama prevodiocu. Također, i rekli smo to već negdje u priručniku, dva razmaka idu prije komentara nakon retka koda. Na primjer:

     Inc (x);  { Increment x. }

Opcionalno možete koristiti dodatne razmake da učinite kod “tabularnim”. Naše je mišljenje da ovo jako povećava čitljivost koda jer su ljudsko oko i mozak trenirani da prepoznaju takve strukture, te se sličnosti i razlike između redaka lakše uočavaju. Također, kad se kod mijenja, lakše se pronalaze povezana mjesta. Primjena ovog principa može se vidjeti u deklaracijama sučelja (engl. interface) (ne toliko primjenljivo kad su razdvojeni komentarima, ali, na primjer, kad su opisani zajedničkim komentarom iznad svih metoda):

     function Pos             (const SubString, s: String): Integer;
     function LastPos         (const SubString, s: String): Integer;
     function PosCase         (const SubString, s: String): Integer;
     function LastPosCase     (const SubString, s: String): Integer;
     function CharPos         (const Chars: CharSet; const s: String): Integer;
     function LastCharPos     (const Chars: CharSet; const s: String): Integer;
     function PosFrom         (const SubString, s: String; From: Integer): Integer;
     function LastPosTill     (const SubString, s: String; Till: Integer): Integer;
     function PosFromCase     (const SubString, s: String; From: Integer): Integer;
     function LastPosTillCase (const SubString, s: String; Till: Integer): Integer;

Također je moguće:

     procedure Foo;
     function  Bar ...;
     procedure Baz;

I, naravno:

     const
       FooBar = 1;
       Baz    = 2;
       Quux   = 3;

Ista “tabularna” strategija korištena u deklaracijama sučelja i konstanti može se koristiti i u inicijalizatorima:

     const
       Foo: TBarArray =
         (('Foo'    ,  3),
          ('Bar baz', 42),
          (''       , -1));

I u `case' naredbama:

     case ReadKeyWord of
       kbLeft    : if s[n] > l    then Dec (s[n]) else s[n] := m[n];
       kbRight   : if s[n] < m[n] then Inc (s[n]) else s[n] := l;
       kbUp      : if n > 1 then Dec (n) else n := 5;
       kbDown    : if n < 5 then Inc (n) else n := 1;
       kbHome    : s[n] := l;
       kbEnd     : s[n] := m[n];
       kbPgUp,
       kbCtrlPgUp: n := 1;
       kbPgDn,
       kbCtrlPgDn: n := 5;
       kbCR      : Done := True;
     end

I opcionalno u drugom kodu:

     WriteCharAt (1, 1, 1,     Frame[1], TextAttr);
     WriteCharAt (2, 1, w - 2, Frame[2], TextAttr);
     WriteCharAt (w, 1, 1,     Frame[3], TextAttr);


Next: , Previous: Razmaci, Up: Programiranje u Pascalu

5.9 Gdje prelamati retke koda

Prijelom retka je opcionalan nakon lokalnih `const', `type', `var' deklaracija ako one sadrže jedinu deklaraciju (ali je moguće imati višestruke identifikatore u jednom retku).

     procedure Baz;
     var Foo, Bar: Integer;
     begin
       ...
     end;

Naravno, slijedeće je također prihvatljivo:

     procedure Baz;
     var
       Foo, Bar: Integer;
     begin
       ...
     end;

Ali nemojte slijediti ovaj primjer:

     procedure Baz;
     var Foo, Bar: Integer;
         Qux: Real;
     begin
       ...
     end;

Ako imate mnogo deklaracija možete prelomiti linije na nekoliko načina. Slijedi preferirani oblik za `var' deklaracije:

     var
       Foo, Bar, Baz, Qux, Quux, Corge, Grault, Garply, Waldo, Fred,
         Plugh, Xyzzy, Thud: Integer;

ili:

     var
       Foo, Bar, Baz, Qux, Quux, Corge, Grault, Garply, Waldo: Integer;
       Fred, Plugh, Xyzzy, Thud: Integer;

Slijedeća je, međutim, pogodnija za polja `record'a i javnih `object' polja, posebno ako uz mnoge od njih ili sve stoji komentar. of them:

     var
       Foo,
       Bar,
       Baz,
       Qux: Integer;

Ne bi trebalo biti lomljenja linija nakon `var' deklaracija u bloku naredbi, jer oni dozvoljavaju samo jednu deklaraciju, a prekidanje retka bi izgledalo kao da su daljnje deklaracije dozvoljene.

     Foo := Bar;
     var Baz: array [1 .. Foo] of Integer;

Budući da su to GNU Pascal ekstenzije, koristite ovakve deklaracije štedljivo, na primjer za varijable čija veličina ovisi o vrijednostima izračunatim unutar potprograma, ili za varijable unutar inicijalizatora jedinica (unit) ili modula, iako biste mogli poželjeti koristiti potprogram.

Ne umećite prijelom retka nakon `label'. Pogledajte kako bi trebali deklarirati labele:

     label Foo, Bar, Baz;

I, radi kompletnosti, ovdje je kako to ne činiti:

     label
       Foo,
       Bar,
       Baz;

Nekoliko deklaracija u različitim linijama ponekad čak i ne funkcioniraju:

     label
       Foo;
       Bar;
       Baz;

Slijedi primjer kako koristiti prijelome redaka unutar `case' naredbe.

     case
       foo:
         begin
           ...
         end;
       bar,
       baz .. qux:
         ...
       else
         ...
     end;

Ili (“tabularno”):

     case
       foo:        begin
                     ...
                   end;
       bar,
       baz .. qux: ...
       else        ...
     end;

Duge naredbe ili deklaracije bi trebale biti prelomljene ili uvijek prije operatora ili uvijek poslije njih (gdje je područje tog 'uvijek' barem jedan potprogram) ili nakon zareza, s uvlačenjem redaka takvim da se značenje učini jasnim:

     if (x = y)
        and (foo
             or (bar
                 and (baz or qux))
             or fred) then

ili:

     if (x = y) and
        (foo or
         (bar and
          (baz or qux)) or
         fred) then

Ovdje je kako koristiti lomljenje redaka u if-then-else naredbama. Drugo korištenje za njih je gdje bi koristili `case' naredbu da je moguće, ali to nije slučaj (na primjer jer tipovi nisu cjelobrojni (ordinal), ili jer vrijednosti koje treba usporediti nisu konstantne, ali ako usporedba uključuje funkciju (`StrEqualCase'), ili postoje dodatne usporedbe).

     if ... then
       a
     else if ... then
       b
     else
       c

Ako su `a' i ne-`a' glavni slučajevi, a `b' i `c' pod-slučajevi od ne-`a', koristite slijedeće (iako razlika može ponekada biti stvar ukusa):

     if ... then
       a
     else
       if ... then
         b
       else
         c

Slijedeći (biologijski prilično nepotpun) primjer sadrži mješavinu obaju formi koju smatramo razumnom:

     if Staniste = 'Voda' then
       { Životinje koje žive u vodi }
       WriteLn ('Da li je to riba?')
     else if Staniste = 'Zrak' then
       { Životinje koje žive u zraku }
       WriteLn ('Da li je to ptica?')
     else
       { Životinje koje žive na kopnu }
       if BrojNogu = 8 then
         WriteLn ('Da li je to pauk?')
       else
         WriteLn ('Da li je to gnu?')

Glavni slučajevi su određeni staništem, a broj nogu razdvaja neke pod-slučajeve.

Za normalne kontrolne petlje ovdje je kratka lista mogućnosti:

     for ... do
       ...
     while ... do
       ...
     repeat
       ...
     until ...

Ako je samo jedna naredba nakon `if', ili u `for' ili u `while' petlji, ili između `repeat' i `until', te ako je ta naredba dovoljno kratka, možete staviti naredbu u samo jedan redak, ovako:

     if ... then ...
     for ... do ...
     while ... do ...
     repeat ... until ...

Ovdje je kako se ponašati ako su umiješani `begin' i `end'.

     if ... then
       begin
         ...
       end
     for ... do
       begin
         ...
       end
     while ... do
       begin
         ...
       end

Indentacija (uvlačenje redaka) je 2 znaka široka, za svako od `begin', `then', `else', `case', `do' (`for', `while', `with', `to begin', `to end'), `repeat', `record', `object', `type', `const', `var', `label'.

Tijela i lokalne varijable i sl. globalnih potprograma se ne smiju uvlačiti, kao niti globalne deklaracije. Svaki ugniježđeni potprogram (zaglavlje i tijelo) i njegove deklaracije, nasuprot tome, moraju biti uvučeni.

     program Prog;
     
     var
       GlobalVar: Integer;
     
     procedure GlobalProc;
     var LocalVar: Integer;
     
       procedure LocalProc;
       var LocalLocalVar: Integer;
       begin
         WriteLn ('This is a local procedure.')
       end;
     
     begin
       WriteLn ('This is a global procedure.')
     end;
     
     begin
       WriteLn ('This is the main program.')
     end.

Zapisi s promjenljivim tipom (variant record) bi trebali biti uvučeni kao što slijedi:

     type
       Foo = record
         NonVariant: Foo;
       case Discriminant: Bar of
         Val1: (Variant1: Baz;
                Variant2: Qux);
         Val2: (Variant3: Fred)
       end;
     
     var
       Foo: record
         [ kao iznad ]
       end = [ inicijalizirajući dio ]

Veća indentacija, tj. više od 2 znaka široka, može se koristiti da se prelamaju naredbe ili deklaracije ili da se postigne “tabularnost” koda.

Kondicionali (`{$ifdef}') trebaju biti na istom nivou indentacije kao i kod na koji utječu:

     begin
       {$ifdef DEBUG}
       WriteLn ('Debugging verzija');
       {$endif}
       ...
     end;

Kratki kondicionali koji pogađaju samo jedan izraz mogu se napisati unutar jednog retka:

     Foo := {$ifdef DEBUG} 'debug' {$else} 'release verzija' {$endif};

Ako ih se namjerno koristi na način protivan normalnim sintaksnim pravilima, stavite ih tamo gdje izgleda da najbolje pristaju i napišite komentar:

     begin
       { Izvrši kod bezuvjetno ako je debugging verzija }
       {$ifndef DEBUG}
       if NekiUvjet then
       {$endif}
         begin
           ...
         end
     end;

U većini ćete situacija pronaći ljepši i ne manje efikasan način pisanja istih naredbi. U ovom slučaju, to se može učiniti na ovaj način:

     begin
       if {$ifdef DEBUG} True {$else} NekiUvjet {$endif} then
         begin
           ...
         end
     end;

Ili još bolje:

     { globally }
     const
       DebugFlag = {$ifdef DEBUG} True {$else} False {$endif};
     
     begin
       if DebugFlag or NekiUvjet then
         begin
           ...
         end
     end;


Next: , Previous: Lomljenje redaka, Up: Programiranje u Pascalu

5.10 Znakovni nizovi

Većina pravila koja smo pokrili dosad ne djeluju unutar znakovnih nizova. Općenito, poruke sadržane u nizovima trebaju slijediti pravila iz teksta GNU Coding standards, na primjer, stavite citirana imena unutar ``' i `'', iako to znači da ćete morati podvostručiti `'' u Pascal nizovima. See Errors, za više informacija.

Normalno biste trebali koristiti nizove omeđene jednostrukim navodnicima, kao `'ovo je lijep niz kojeg čitate''. Koristite nizove u dvostrukim navodnicima kad trebate escape sekvence u C stilu kao npr. `"\t"'. Primijetite da je `NewLine' (`"\n"') predefiniran, tako da je preporučljivo koristiti `NewLine' osim ako ne morate koristiti niz u C stilu za druge svrhe.

Niz koji zauzima više redaka možete koristiti ovako:

     WriteLn ('Bok
     svijete')

ili (možda bolje, posebno ako tekst u nizu sadrži paragrafe i/ili uvlačenje redaka sam po sebi):

     WriteLn (
     'Bok
     svijete')

Međutim, također je moguće koristiti:

     WriteLn ('Pozdrav' + NewLine + 'svijete')

(Primijetite da se gornji primjer neće prevesti bez korištenja GPC jedinice (unit)).

Ili, naravno:

     WriteLn ('Pozdrav');
     WriteLn ('svijete')

Ako želite provjeriti da li je niz prazan, koristite slijedeću sintaksu:

     if s = '' then
       ...

GNU Pascal prevodilac će ovo optimizirati u slijedeći više efikasan test, stoga možete koristiti prethodni, kraći, bez kajanja:

     if Length (s) = 0 then
       ...

Ovo se odnosi i na `<>', naravno, čak i za pridruživanja gdje je `s := ''' preporučeni oblik i biti će optimiran od strane GPC-a u `SetLength (s, 0)'.


Next: , Previous: Znakovni nizovi, Up: Programiranje u Pascalu

5.11 Tehnike za internacionalizaciju

Molimo pogledajte u GPC manualu o tome kako se internacionalizacija programa izvodi (see I18N).


Previous: Internacionalizacija, Up: Programiranje u Pascalu

5.12 MemoryMap

Ovaj se odsječak GNU Coding Standards također odnosi na GNU Pascal. Samo se prisjetite da `mmap' zapravo znači `MemoryMap' u tom kontekstu. See Mmap.


Next: , Previous: Programiranje u Pascalu, Up: Top

6 Dokumentiranje programa

Preporučujemo čitanje odgovarajućih poglavlja u tekstu GNU Coding Standards, kako se ona primjenjuju također i u ovom kontekstu. See Documentation. Međutim, postoje neke primjedbe vrijedne spominjanja ovdje.

Što se man stranica tiče, bilo bi dobro imati jednu koja ukazuje na Info dokumentaciju. Postoji GNU program, zvan `help2man', koji generira man stranicu na osnovi `--help' ispisa programa. Radi dobro, osim što uvijek ispisuje `FSF' što nije točno za sve programe prevedene s GNU Pascal prevodiocem, ali se izlaz lako može promijeniti (na primjer, automatski, koristeći `sed').

Međutim, ne ulažite previše napora u man stranice. One mogu biti rješiv problem u početku, ali održavati ih konzistentnim s Texinfo datotekama znači mnogo posla. Povrh svega, ako ih ne držite ažurnim vjerojatnije je da će kreirati više konfuzije nego što će biti od pomoći.

S jedne strane, ako su man stranice previše skraćene vjerojatno će im nedostajati važne informacije. S druge strane, ako nisu skraćene, postaju teške za navigaciju.

Drugim riječima, posvetite se Info (tj. Texinfo) dokumentaciji.


Next: , Previous: Dokumentacija, Up: Top

7 Proces izdanja verzija softwarea

Molimo pročitajte odgovarajuće poglavlje u GNU Coding Standards. Primijetite da veliki napori sa auto-alatkama C-a nisu neophodni za normalne GNU Pascal programe. Makefile datoteke također često nisu neophodne u GNU Pascalu. See Managing Releases.


Up: Izdanja programa

7.1 Konvencije Makefile datoteka

Za vaš Pascal projekt vjerojatno nećete trebati velike `Makefile' datoteke i nećete trebati koristiti `autoconf' ili `automake'. Možete proslijediti `--automake' GNU Pascal prevodiocu tako da prevodilac vodi brigu o međusobnim zavisnostima za vas. (U vrijeme dok ovo pišemo, GNU Pascalov `automake' ima nekih manjih bugova, ali će oni biti ispravljeni. Također, postoji i plan za alatku zvanu `gp', koja je u razvoju, koja bi još uvelike pojednostavnila proces kompilacije. Ostanite na vezi. U svakom slučaju, obično nećete trebati pisati kompleksne `Makefile' datoteke sami.)

Jednostavan Makefile može biti u redoslijedu kao:

     GPC_FLAGS=-O2
     
     all: foo
     
     foo: foo.pas unit1.pas
     	gpc --automake $(GPC_FLAGS) foo.pas
     
     mostlyclean:
     	-rm -f *.o *.gpi *.gpd core
     
     clean: mostlyclean
     	-rm -f foo
     
     distclean: clean
     
     extraclean: distclean
     	-rm -f *~*
     
     maintainer-clean: extraclean

Mogli biste, međutim, poželjeti da stavite druga pravila u `Makefile' za izgradnju dokumentacije, podatkovnih datoteka, izradu distribucija i slično. Takve stvari su izvan područja ovog teksta. Obično možete izvesti Pascal kompilacije s jednim jedinim `gpc --automake' pozivom po programu.


Next: , Previous: Izdanja programa, Up: Top

8 Rječnik pojmova korištenih kroz tekst

Rutine (potprogrami) su ili `procedure', ili funkcije (`function'), ili konstruktori (`constructor'), ili destruktori (`destructor'), ili korisnički definirani operatori.

Deklaracije su oni dijelovi programa koji “najavljuju” postojanje i svojstva određenih objekata kao što su konstante, tipovi, varijable, rutine, jedinice (unit), moduli i sam program.

Naredbe su dijelovi programa koji zapravo “rade” nešto. Pojedina naredba je ili dodjela vrijednosti, ili poziv procedure, ili naredba za skok (`goto', `Exit', `Return', `Break', `Continue'), ili asemblerska naredba, ili složena naredba (`begin' ... `end', `if', `case', `repeat', `while', `for', `with') koja opet može sadržavati jednu ili nekoliko naredbi.

Identifikatori su takvi jezični elementi koji daju imena objektima kao što su rutine, konstante, tipovi, varijable, jedinice (unit), moduli. Oni mogu biti (lokalno) redefinirani, za razliku od ključnih riječi koje su dio fiksnih sintaktičkih konstrukcija (na primjer `if' ... `then' ... `else') i ne mogu biti redefinirani. Makro naredbe nisu jezički elementi budući da su ekspandirani u preprocesoru i prevodilac ih nikada niti ne vidi.

Endianness znači poredak u kojem su bajtovi vrijednosti dužih od jedne riječi smještene u memoriju. Ovo pogađa, npr. cjelobrojne vrijednosti i pokazivače dok, npr. polja jednobajtnih znakova nisu time pogođena. (see Endianness)

Primijeti: I druge se stavke mogu dodati ovdje ako vam se to čini korisnim. Ako biste željeli definiciju nekog drugog pojma, dajte nam do znanja.


Previous: Rječnik pojmova, Up: Top

Indeks

Table of Contents