Dr. Vermes Mátyás
2003. augusztus
A 90-es évek elejének egyik legnépszerűbb fejlesztő eszköze a Clipper volt, ennek örököse a CCC. A CCC a ComFirm munkájának melléktermékeként jött létre. A ComFirm több mint 10 éve fejleszti és üzemelteti lényegében egyetlen termékét, egy banki számlavezető rendszert. A körülmények kényszere folytán kezdetben Clipperben kellett dolgoznunk (előírta a megrendelő), de már az induláskor kerestük a váltás lehetőségét. Az akkori Clipperből ezért csak a jónak gondolt részeket vettük birtokba, ezekből a ,,jó'' részekből alakult ki a CCC.
A CCC név a Clipper to C Compiler szavak kezdőbetűiből származik. Nevéhez méltóan a CCC a Clipper kódot C++-ra fordítja, és az így kapott C++ forrásból az adott oprendszer eszközeivel csinál (fordít, szerkeszt) végrehajtható programot. Mivel a mai operációs rendszerek alapja a C/C++ nyelv, nem meglepő, hogy a CCC több operációs rendszeren is fut:
Windowson az MSC, Borland C és MinGW fordítókkal lehet CCC környezetet kialakítani. UNIX-on mindenhol a GNU C-t használjuk. Általánosságban elmondható, hogy a CCC-t tetszőleges UNIX rendszerre pár napos munkával portolni tudjuk. Ez egyúttal azt is jelenti, hogy a CCC-ben készült programok a CCC-vel együtt hordozhatók a felsorolt platformok között. Egy ilyen esettanulmányt ismertet a A Kontó számlavezető rendszer portolása Solarisra dokumentum.
Téved, aki azt gondolja, hogy a CCC valami ásatag dolog, ami csak régi Clipper alkalmazások portolására való. Jelenleg XMLRPC szervereket írunk, SQL alapú adatbázisprogramozást végzünk, digitális aláírásokat vizsgálunk CCC-ben. A Jáva terminál technológiával új, egyedülálló lehetőségek nyíltak a CCC előtt az internetes programozásban.
A CCC lényegében keletkezésétől fogva szabadon letölthető, és tetszőlges célra ingyenesen használható volt, 2005. őszén azonban a helyzet végleges tisztázása érdekében a CCC-t LGPL license hatálya alá helyeztük.
E sorok írója hallott olyan véleményt, miszerint a Clipper óriási kárt okozott a magyar informatikában, mivel rossz programozási stílusra nevelte a programozókat. Egy internetes fórumon, ahol a CCC-ről folyt a társalgás felvetették: Mi értelme van Clipperrel foglalkozni a .NET és Delphi korában? Van-e a Pythonnak, Perlnek, Pikenak, Rubynak létjogosultsága?
A CCC-t a régi Clippertől eltérően nem dBase adatbáziskezelésre szakosodott alkalmazásfejlesztő eszköznek tekintjük, hanem általános célú programnyelvnek. Éppúgy, ahogy az előbb felsorolt nyelvekre, pl. a Pythonra gondolunk.
Valóban a CCC leginkább a Pythonra hasonlít. Nem belső felépítését, hanem hangulatát, használhatóságát illetően. A Python jobban készen van (több csomag van hozzá), a CCC viszont nyíltabb (könnyebb hozzá C részeket írni), ezáltal könnyebb megírni a hiányzó interfészeket, komponenseket. Persze mindenki mondhatja magáról, hogy hozzá könnyebb C betéteket írni, de vajon a Pythonos olvasóim közül hányan bővítették már a Python-t C-vel? Ugyanakkor a CCC programkészítő környezet a C/C++ modulokat szó nélkül, automatikusan fordítja és linkeli a többi modullal együtt.
A Clipper/CCC programozási nyelv rendkívül praktikus. Egyáltalán nem nevel rossz programozási stílusra (persze a dilettánsok sok mindenre képesek). Felhasználási területe igencsak széles:
Másrészt minek újabb és újabb nyelveket kitalálni, ha jó a régi is. Persze változatlan állapotában a régi Clipper ma szegényesen hatna, ám a CCC sokmindennel kiegészült: objektum rendszerrel, többszál támogatással, névterekkel, könnyű hozzáféréssel a rendszer erőforrásaihoz, pl. az SQL adatbázisokhoz, openssl könyvtárhoz stb..
A CCC-ben végrehajtott bővítések közben nyelvi szempontból kompatibilisek maradtunk a régi Clipperrel. A mostani programjaink még mindig szintaktikailag helyes Clipper programok. Ez mutatja, hogy a Clipper valóban rugalmas (meglepően rugalmas) nyelv, amit érdemes életben tartani.
Informatív lehet tudni, hogyan és mire használják a CCC-t azok akik a legjobban ismerik, vagyis a készítői. Mint már írtam, a CCC egy banki rendszer portolására készült, és egy banki számlavezető rendszer nem engedheti meg magának, hogy hibázzon. A CCC tehát bizonyítottan használható és stabil.
A számlavezető alkalmazás kb. 100+ végrehajtható programból áll, amik egy közös adatbázison dolgoznak. Kb. 100-200 felhasználónk van, akik a bank országos fiókhálózatában hol ezt, hol azt a végrehajtható modult indítják el. Az egész alkalmazás centralizálva működik:
Vannak olyan alkalmazásaink, amik nem interaktívak, pl. az XMLRPC szerverek, amik tranzakciós API-t biztosítanak más rendszerek számára.
Vannak esetek, amikor a karakteres felület nem megfelelő, ilyen pl. az a program, ami az otthonról internetező banki ügyfél számára megmutatja a számlaegyenlegét. A GUI-t igénylő programok készítésére való a Jáva terminál. A Jáva terminálos alkalmazás két részből áll:
Az eddig felsorolt esetekben az a közös, hogy a CCC program mindig a szerveren fut. A CCC-t tehát döntően szerver oldali programozásra használjuk. Még az interaktív programjaink is a szerveren futnak.
A CCC régebbi rétegeiben vannak grafikus csatoló könyvtárak Windowshoz és az Fltk ablakkezelőhöz. Amikor ezek készültek, az volt a célunk, hogy a meglevő karakteres Clipper programok átírás nélkül fussanak grafikus környezetben. Ezt el is értük, de csak azon az áron, hogy a grafikus megjelenítés primitív. A primitívség nem a CCC/Clipper nyelv hibája, hanem a koncepció következménye. A közvetlen grafikus csatolók azért vannak elhanyagolva, mert nem támogatják kellőképpen a szerver oldali programozást.1
Nem célunk a régi DOS-os Clipper alkalmazások változtatás nélküli lefordítása. A CCC általános célú programnyelv. Lehet benne adatbáziskezelő szoftvert írni, ám az ilyen szoftver nem a nyelv része, hanem alkalmazás. Konkrétan, a régi Clipper dBase alapú adatbáziskezelése nem része a CCC-nek. Az eredeti Clipperből csak a jó részeket tartottuk meg, azokban viszont közel teljes a kompatibilitás. A CCC több területen kiterjeszti a Clippert: objektumok, szálak, névterek, kivételkezelés. A kiterjesztés minden esetben úgy valósul meg, hogy a CCC speciális esetként tartalmazza a Clippper 5.x-et, miközben minimális mennyiségű szintaktikai újítást vezet be. Bővebb információ található a témáról az Eltérések a CCC és a Clipper között dokumentumban.
A CCC egy C++-ban implementált veremgépre fordít. Nézzük, mit csinál a klasszikus Hello World programmal:
function main() ? "Hello World!" return NIL
amiből (a szokásos preprocesszálás után) a CCC a következő C++ kódot generálja:
//input: proba.ppo (3.1.01) #include <clp2cpp.h> extern void _clp_main(int argno); extern void _clp_qout(int argno); void _clp_main(int argno) { VALUE *base=stack-argno; stack=base+min(argno,0); while(stack<base+0)*stack++=NIL; push_call("main",base); // line(3); string("Hello World!"); _clp_qout(1); pop(); line(4); push(&NIL); {*base=*(stack-1);stack=base+1;pop_call();return;} // stack=base; push(&NIL); pop_call(); }
Amit érdemes megérteni a fenti kódban (a kevésbé fontos dolgok mellőzésével):
A haladóbbaknak. Nyilvánvalónak látszik, hogy stack mutató a verem tetejére. Ez így is van, a többszálúság miatt azonban a helyzet kicsit bonyolultabb: stack egy makró, amiből olyan kifejezés lesz, ami az aktuális szál privát vermének tetejére mutat.
Nem kell megijedni, a példa csak a veremgép bemutatásrára szolgál. A gyakorlatban a CCC programsorok millióit fordítja le anélkül, hogy bárki nézegetné a kapott C++ kódot.
A Python, Pike referenciaszámlálós szemétgyűjtést használ. Ennek lényege, hogy a rendszer nyilvántartja, hogy melyik objektumra hány változó hivatkozik.
A kezdőbbeknek. Vegyünk egy stringet, erről azt mondjuk, hogy a program egy objektuma. Ha az a változó értéke a string, akkor a változó erre a string objektumra hivatkozik. Ha a program végrehajt egy b:=a utasítást, akkor a stringre való hivatkozások száma nő, mert most már b is a stringre hivatkozik. Az a:=NIL utasítás viszont csökkenti a hivatkozások számát.Ha egy objektum referenciaszáma 0-ra csökken, az megszüntethető. Ennek a módszernek gyengéje, hogy hibázik azokban az esetekben, amikor az objektumok hivatkozási gráfjában kör van. Például, ha egy array elemként tartalmazza önmagát, akkor annak az arraynek (mint memóriaobjektumnak) a referenciaszáma sosem csökken 0-ra. A pythonosok erre azt mondják: ne csináljunk köröket.
A CCC szemétgyűjtése Cs.L. javaslata alapján a következőképpen megy: A rendszer időről időre a vermeken tárolt változókból kiindulva bejárja az objektumhivatkozások gráfját, eközben megjegyzi, hogy mely objektumokhoz jutott el. Azok az objektumok, amikhez a gráf bejárása nem vezet el, feleslegesek, és ezért meg lehet őket szüntetni.
Az utóbbi algoritmus jellemzője, hogy átlagosan gyorsabb a referenciaszámlálásnál, mert kevesebb adminisztrációt igényel, hátránya viszont, hogy időről időre megállítja a program futását. A tapasztalat szerint azonban az akadozás csak egészen nagy programoknál feltűnő. Egymillió objektumot kezelő, 100 MB memóriát foglaló CCC programok még kiválóan futnak.
Érdekességként említem, hogy a többszálú CCC tervezésekor eltűnődtem, nem volna-e mégis jobb a referenciaszámlálás. Ui. a referenciaszámlálást minden szál maga intézi, nincs szükség szemétgyűjtés alkalmából az összes többi szál leállítására. Ugyanakkor pedig azt látom, hogy a pythonosok ,,valódi'' szemétgyűjtésre vágynak. Hiába, a szomszéd kertje mindig zöldebb.
A CCC programozásban előtérbe kerültek azok a programok, amik egyáltalán nem igénylik a Clipper hagyományos képernyőkezelését:
ccc2 | alapkönyvtár |
ccc2_ui_ | képernyőkezelés nélküli interfész |
ccc2_uic | karakteres képernyő, lokális és távoli |
ccc2_uif | Fltk képernyőkezelés (UNIX-on) |
ccc2_uiw | Windows GUI képernyőkezelés |
ccc2_uid | dinamikusan választ uic és uif között (UNIX-on) |
A ccc2 és ccc2_ui_ könyvtárak adják a CCC magját, amivel már megírhatók a parancssoros programok, a háttérben futó szerverek. A jövőbeli fejlesztések erre a két alapkönyvtárra koncentrálódnak. E könyvtáraknál célkitűzés a szálbiztosság elérése.
A ccc2_uic, ccc2_uif, ccc2_uiw könyvtárak a korábbi (CCC 1.x) képernyőkezelő kódot tartalmazzák. Az uic könyvtárban kompatibilis módon implementálva van a hagyományos Clipper karakteres képernyőkezelés. Fontos alváltozatai a lokális és távoli megjelenítés, utóbbi Windowson is lehetővé teszi a távoli programhasználatot.
Az uif (Fltk) és uiw (Windows) könyvtárak grafikus megjelenítést biztosítanak. A dolog természetéből adódóan ezek nem lehetnek teljesen kompatibilisek a Clipperrel, viszont tartalmaznak olyan magasabb szintű objektumokat (menüvel felszerelt, adatrekordok között navigáló ablakot, dialogboxot), amik grafikus és karakteres módban egyformán programozhatók, és egyformán is működnek. Éveken át ezekből az objektumokból építettük az interaktív programjainkat. Használatuk a CCC programozási példák dokumentumban van leírva.
A ccc2_uid könyvtár az uic és uif könyvtárakban definiált globális Clipper szimbólumok metszetét tartalmazza. Az uid-vel linkelt programok karakteres és grafikus módban is működőképesek, környezeti változó beállításával lehet szabályozni, hogy ugyanaz a program melyik módban jelenjen meg.
Az utóbbi négy megjelenítő könyvtár (uic, uif, uiw, uid) nem szálbiztos. Ezek fejlesztése a jövőben nem folytatódik, mivel interaktív programok készítéséhez jobb és egyszerűbb a Jáva terminál.
A CCC könnyen bővíthető C/C++ primitívekkel, ezáltal könnyen el lehet érni a rendszer szolgáltatásait. Vegyünk két példát:
Az első, bár rövid, szándékosan nem triviális, UNIX-on és Windowson eltér, van benne paraméterátadás. A sleep függvény vár, a várakozási időt a függvény argumentumaként ezredmásodpercben kell megadni.
#ifdef _UNIX_ #include <sys/time.h> #include <sys/types.h> #endif #include <cccapi.h> void _clp_sleep(int argno) //nincs NG-ben { CCC_PROLOG("sleep",1); unsigned long ms=_parnu(1); if( ms ) { #ifdef _UNIX_ struct timeval t; t.tv_sec=ms/1000; t.tv_usec=(ms%1000)*1000; select(0,NULL,NULL,NULL,&t); #else Sleep( ms ); #endif } _ret(); CCC_EPILOG(); }
A második példa a UNIX fork hívást vezeti ki CCC szintre. Gondoljuk el, hogy a komplikált CCC program, az egész változóterével mindenestül megduplázódik, és két példányban fut tovább ...
#include <cccapi.h> void _clp_fork(int argno) { CCC_PROLOG("fork",0); _retni( fork() ); CCC_EPILOG(); }
A C kiegészítés szabályairól nincs dokumentáció, de nem is volna sok haszna. A komoly érdeklődő hamar eligazodik a bőségesen rendelkezésre álló példák alapján. Annyit azért megjegyzek, hogy a CCC (és általában minden veremgép) stabilitása a primitívek állandóságán alapul. Ha ugyanazokból a lego elemekből sok dolgot kirakunk, akkor a hibás darabok hamar kiselejteződnek. A CCC is annál stabilabb minél több programot írunk rajta.
A Clipper adatbáziskezelő eljárásait sosem használtuk eredeti formájukban, mert az akadályozta volna a programok portolását. A CCC-ben az indexszekvenciális filékezelésnek az ún. táblaobjektum ad keretet. A táblaobjektumok használatára a CCC programozási példák dokumentumban találunk bevezető jellegű információt. A táblaobjektum referencia szintű leírása található a Táblaobjektum referencia dokumentumban.
Az évek során többféle adatbáziskezelő könyvtárral implementáltuk a táblaobjektumot.
A táblaobjektum fel van szerelve egyszerű tranzakciókezeléssel, lásd a Táblaobjektum tranzakció kezeléssel dokumentumot, és naplózással: Módosítások naplózása a táblaobjektumokban.
Megemlítem még, hogy az adatbáziskezelés biztonsága nagy mértékben a CCC használatának módjából következik. Az adatkezelő programok nem a felhasználó gépén, hanem a (távoli) szerveren futnak. A szerveren levő filérendszerhez a felhasználóknak nincs közvetlen hozzáférése.
A CCC olyan új objektum rendszert kapott, ami felülről 100%-ban kompatibilis a régi Clipper objektumaival. A régi Clipper négy fixen beépített osztállyal rendelkezett (error, get, tbcolumn, tbrowse), ezeket nem lehetett módosítani, és új osztályok létrehozására sem volt lehetőség.
A CCC az objektumorientált nyelvek minden fontos jellemzőjével rendelkezik. A programozó új osztályokat definiálhat, melyek többszörös öröklődéssel származnak egymásból. Az ún. objektum alapú nyelvektől eltérően a CCC valódi osztályokkal dolgozik. Egy osztályban nyilvántartás található arról, hogy mik az ősosztályok, milyen attribútumokkal, milyen metódusokkal rendelkezik. Az osztályok megírásához nem vezettünk be új szintaktikát, minden közönséges függvény API-val történik. Részletesen foglalkozik a témával az Objektumok használata a CCC-ben dokumentum.
A többszálúság a 2.x változat újdonsága. Az alább felsorolt API áll rendelkezésre szálak indítására és szinkronizálására:
thread_create(codeblock,arg1,...) --> threadid thread_self() --> threadid thread_detach(threadid) --> status thread_exit() --> NIL thread_join(threadid) --> status thread_mutex_init() --> cMutex thread_mutex_lock(cMutex) --> status thread_mutex_trylock(cMutex) --> status thread_mutex_unlock(cMutex) --> status thread_mutex_destroy(cMutex) --> status thread_cond_init() --> cCond thread_cond_signal(cCond) --> status thread_cond_wait(cCond,cMutex[,nMillis]) --> status thread_cond_destroy(cCond) --> status
A thread_create()-ot pontosan úgy kell meghívni, mint az eval()-t, a különbség, hogy thread_create() azonnal visszatér, miközben az új szál futásnak indul. A CCC szintre kivezetett POSIX thread API CCC-ből ugyanúgy működik, mint C-ből. A POSIX szálak használatáról útmutató található a man-ban a pthread címszavaknál. Windowson ugyanez az API Win32 rendszerhívásokkal valósul meg.
Az alábbi demonstrációs program pi közelítő értékét számítja ki 4/(1+x2) numerikus integrálásával :
static pi:=0 static pi_lock:=thread_mutex_init() static intervals:=1000000 static thcount:=10 function main() local blk:={|ip|process(ip)} local th:={},n for n:=1 to thcount aadd(th,thread_create(blk,n)) next for n:=1 to len(th) thread_join( th[n] ) next ? "Estimation of pi is:", str(pi) return NIL function process(iproc) //iproc==1,2,... local localsum:=0 local width:=1/intervals local i, x for i:=iproc to intervals step thcount x:=(i-0.5)*width localsum+=4/(1+x*x) next localsum*=width thread_mutex_lock(pi_lock) pi+=localsum thread_mutex_unlock(pi_lock) return NIL
Életszerűbb példa a $CCCDIR/ccctutor/websrv-ben található többszálú HTTP szerver. Minden újonnan kapcsolódó klienst új szál szolgál ki, egy szál akkor szűnik meg, ha a kliens bontja a kapcsolatot, vagy 10 másodpercnél hosszabb ideig inaktív. Újabban a ComFirm weboldalait is ez a program szolgáltatja.
Hangsúlyozom, hogy a CCC-ben valódi, operációs rendszer szintű többszálúság valósul meg. Másképp nem is nagyon lehet, hiszen a CCC programkészítés végeredménye egy fordított/linkelt C program, szó sincs interpretálásról. Ezzel szemben a Python és Ruby interpreterek valójában egy szálon futnak, csak éppen váltogatják az aktuálisan interpretált kódrészletet.
A Jáva Terminál egy alkalmazásfüggetlen megjelenítő program, ami más programok részére biztosít GUI-t. Egy böngészőhöz lehetne hasonlítani, csakhogy ez nem HTML lapok, hanem dialogboxok megjelenítésére szakosodott. A dialogboxok Swing elemekből építkeznek: menü, push button, rádió button, check box, get (szerkesztő sablonnal felszerelt szövegmező), list box, táblázat (browse), ikonok, statikus szövegek, képek stb.. A terminál egy mindössze 300K-s, digitálisan aláírt jar filéből áll, ami a Jáva Web Start technológia alkalmazásával automatikusan installálódik az internetes felhasználó gépén.
A terminál és a CCC alkalmazás XML üzenetekkel kommunikál. Első lépében az alkalmazás elküldi a terminálnak a dialogbox XML leírását a megjelenítendő komponensek paraméterezésével, az adatok kezdőértékével. A későbbiek során ugyancsak XML üzenetekkel történik a dialogbox szerver oldali és a terminál oldali reprezentációjának szinkronban tartása. A kommunikáció SSL-lel titkosítható, így a használat nyilvános hálózaton is biztonságos. Ez a funkcionalitás az ügyviteli alkalmazások széles körének megfelelő felhasználói felületet nyújt, ugyanakkor a szerver oldali megvalósítása meglepően egyszerű. Az egyszerűség abból adódik, hogy a szerver a terminálra bízza a megjelenítés bonyolult feladatát, és maga csak a dialogboxok állapotának tárolásával, illetve az üzenetkezeléssel foglalkozik.
A CCC-nek mindig is erőssége volt a szerver oldali programozás és a távoli programfuttatás, a Jáva Terminál most ehhez igényes grafikus felületet is biztosít. F.Gy., a Raiffeissen fejlesztési vezetője így nyilatkozott: ,,maga a programozói álom''. Felhatalmazott rá, hogy ezt terjesszem. További információ található a témáról a Jáva Terminál oldalon.
A két utolsó könyvtár egységes objektumorientált interfészt ad Oracle és Postgres adatbázisokhoz. A koncepció szerint ugyanaz az alkalmazás a kód változtatása nélkül fut Oracle és Postgres szerverekkel. A téma bővebb kifejtése az SQL2 1.0 interfész dokumentumban található.
A CCC csomagokat kétféleképpen lehet beszerezni:
A CCC telepítése dokumentum leírja, hogyan lehet a CCC-t a semmiből indulva lefordítani.
Szó volt róla, hogy a CCC alkalmas kis ragasztóprogramok gyors készítésére, ezáltal scriptek helyettesítésére. Mivel a CCC nem interpreter, hanem fordítani, szerkeszteni kell, ez csak úgy lehetséges, ha jó eszközök vannak a fordítás támogatására. Ilyen eszköz a Build, ami maga is egy CCC (ragasztó) program.
A Build összegyűjti és kielemzi a projekthez tartozó forrásmodulokat, megkeresi bennük az include utasításokat, ezáltal megállapítja a függőségi viszonyokat. Megnézi, hogy az objectek és források közül melyik az újabb, szükséges-e az újrafordítás. Végül mindent lefordít, elkészíti a kért közönséges, vagy megosztott könyvtárat, végrehajtható állományokat. Mindehhez nem kell komplikált makefilét szerkeszteni, hanem csak egy ilyen parancsot adunk ki:
bapp_unix.bés minden automatikusan, másodperceken belül elkészül. A szokásos makefile helyett a forrásmodulok könyvtárakba szervezésével kell szabályozni a projekt tartalmát.
A Build nem csak kicsi, és nem csak Clipper nyelvű programok fordítására képes. Az egész CCC rendszer fordítását a Build végzi. Clippert egyáltalán nem tartalmazó C++ projektek fordítására is a Build-et használom. Mióta elkészült (3-4 éve) a make-t elő sem vettem. További infó a Programkészítés a Build-del dokmentumban.
Sajnos a CCC-nek nincs olyan szép, konzisztens dokumentációja, mint a korábban említett nyelvek akármelyikének. Mivel aligha lesz időm ilyet készíteni, a jövőben sem lesz. Vannak viszont dokumentációk egyes részterületekről (lásd a jelen dokumentum hivatkozásait), és van egy összefoglaló táblázat az alap CCC függvényeiről: CCC API. Szerencsére a CCC tényleg kompatibilis a Clipperrel, ezért használható hozzá az eredeti Clipper dokumentáció, illetve annak közkézen forgó HTML formátumú változata.
Másrészt az XMLRPC sokkal praktikusabb, mint a CORBA. Egy CORBA könyvtár nehézsúlyú dolog, amit magunk aligha fogunk megírni, ezért használatával hozzákötnénk magunkat egy külső szoftvercéghez, akit mindenféle baleset érhet, mint érte az Orbacust is. Az XMLRPC ellenben egyszerű: HTTP protokoll feletti XML szintaktikájú üzenetváltás, a szabvány leírása elfér 2 db A4-es oldalon.
A CCC-t Vermes Mátyás (e sorok írója) készítette még 1996-ban, Windows NT-n, Watcom fordítóval. A munka során tervezési kérdésekben mindig meghallgattam Csiszár Levente véleményét, akinek javaslata alapján készült többek között a CCC gráfbejárásos szemétgyűjtése. A UNIX/Linux-ra való portolás döntően Cs.L. munkája, amiben részt vett még Szanka Gábor és Tanos Áron. Az Fltk-ra épülő grafikus megjelenítő könyvtárat teljes egészében Cs.L. készítette. A karakteres és windowsos megjelenítő könyvtárak megírásában segítségemre volt Szabó Richárd.
A Kontó számlavezető rendszer portolása Solarisra
Eltérések a CCC és a Clipper között
CCC programozási példák
Táblaobjektum referencia
Saját kulcskezelőre épülő táblaobjektum
Táblaobjektum tranzakció kezeléssel
Módosítások naplózása a táblaobjektumokban
Objektumok használata a CCC-ben
Jáva Terminál
SQL2 1.0 interfész
CCC telepítése
Programkészítés a Build-del
CCC API
1 Időközben belekezdtem egy GTK csatoló írásába, ez lesz a CCCGTK. Terveim szerint ez a csatoló annyira lesz teljes, mint a PyGTK. Egyelőre kb. 10%-os állapotban van: az ablakok, menük, gombok, adatbeviteli mezők, feliratok, keretek, ... már működnek.
2 Érdekességként említem, hogy a socket könyvtárra alapozva mindössze 256 (=28) CCC sor elegendő volt egy olyan web szerver megírásához, ami már alkalmas a ComFirm honlapjának működtetésére. A szerver adogatja a filéket a böngészőnek, elég intelligens ahhoz, hogy szót értsen a Jáva Webstarttal, és többszálú lévén egyszerre több klienssel is foglalkozni tud. A program forrása a $CCCDIR/ccctutor/websrv-ben található.