Konstruktion av kommando och generell funktion för att anropa sorteringsalgoritmer samt Subversion versionshantering. Introduktion Målet var att göra ett program för sortering som har grundrutiner som kan sortera både strukturer av rådata och strukturer med pekare till rådata. Programmet skulle kunna anropas via ett kommandoanrop i Windows command prompt eller i Linux (Fedora 17). Jag har implementerat ett kommandogränssnitt för sortering och ett subrutiner som kan användas för att sortera olika typer av heltal / integers i C och C strängar av ASCII-tecken/bytes. I princip skall vilken sorteringsrutin som helst kunna anslutas till mitt programpaket, se mer nedan. Som en del av detta har jag även installerat en Subversion server för versionshantering under Cygwin, på kursens Windows 7 Professional försedda PC. Cygwin är en gratis programvara för Unix/Linux-emulering från Redhat som står bakom Linux distributionerna Fedora och Redhat. I Cygwin ingår en Linux-version av Subversion servern från "Apache Software Foundation" (som gör bl.a. den fria webservern Apache, de fria "Big Data"- verktygen Hadoops och Hive m.m.) Jag har använt Subversion's cygwin-klient respektive TortoiseSVN's Windows klient för versionshanteringen. Jag har dessutom valt att använda cygwin's ssh server för att kunna tunnla via ssh till subversion servern under Cygwin/Windows, även om det i första hand använts för att tunnla in till Cygwin's subversion-server direkt på den lokala hosten (men även från min Linux-dator hemma i mitt lokala nätverk). -1-
Problembeskrivning Vill göra ett kommando och subrutiner för sortering av godtyckliga typer av data i C. Jag har implementerat en kommandomottagning för Windows kommandoprompt respektive Linux/Unix terminalen och en subrutin och preprocessor macros för att åstadkomma detta. Jag har också sett till att ha modern versionshantering för mina filer med Subversion för versionshanteringen, i Linux, Windows 7 och i Windows 7, men med Linux/Unix emulerat av Cygwin. -2-
Teori Kan sortera godtyckliga data med ex qsort och bubblesort. Vad qsort och bubblesort behöver är en array/lista med antingen pekare till data objekt av en viss typ eller data objekt av en viss typ samt en rutin för att avgöra om två data-objekt är lika stora, större eller mindre än varandra. Versionshantering för en enskild användare kan implementeras med ett flertal olika versionshanteringssystem. Man kan säga att Unix/Solaris ursprungliga SCCS versionshanteringsystem var mer inriktat på den enskilda användaren än arbete i gruppoch projekt medan mer moderna versionshanteringssystem som Clearcase, Subversion eller git stödjer dels arbete i projekt och dels arbete distribuerat till ett antal skilda geografiska platser via internet och system av servrar. Ofta kan man integrera versionshanteringssystemet i det GUI/IDE som man använder för bl.a. konstruktion och debuggning, som CodeBlocks, Eclipse eller Visual Studio. Dagsläget för CodeBlocks verkar tyvärr vara att man inte kan anropa Subversion eller git direkt i från verktyget, utan måste göra det antingen från filhanteraren eller från kommando prompten i Windows respektive terminalen i Linux/Unix. Emacs med lisp-moden gud mode som debugverktyg och lisp-moden compile mode som produktionsmiljö, ett äldre text-baserat verktyg, stödjer dock både Subversion, Clearcase och git liksom riktiga gamla versionshanteringsverktyg som SCCS. -3-
Material HW och SW som använts PC med Windows 7 och CodeBlocks IDE/GUI för programvaruutveckling i bl.a. C samt TortoiseSVN Subversion klient. PC med Linux/Unix emuleringen Cygwin, gcc, gdb, subversion & ssh servrar & klienter, samt emacs & dess compile mode resp. gud (gdb-debuggning) mode samt stöd för versionshanteringen via Cygwin's subversion server (via ssh servern mot localhost i det här fallet). -4-
Metod MJUKVARA I C FÖR SORTERING Skrivit ett kommando för att sortera integer data, C-typen int. Testat att göra om detta kommando för att sortera data av C-typen short int samt skrivit ett separat program för att testa sortering av strängar. Alla programmen anropar min generella subrutin för sortering. Sorteringsrutinen för sortering klarar av listor/arrayer av pekare till strängar och vanliga listor/arrayer av de olika normallånga typerna av integers i C. KOMMANDO: Kommandot för att sortera integers ser ut enligt nedan: iterate_over_word_list_int_cont [-csrgq] [file...] [file...] där alternativen -csrgq motsvarar -c CSV format, komma separerat format -s Sortera lista -r Sortera i omvänd ordning (reverse order) -g Gruppera i jämna och udda listor, konkatenera sedan ihop listorna (eventuellt efter sortering) -q Sortera med quicksort (annars i dag med bubble-sort) Argumenten på slutet, fil att läsa från och fil att skriva till är icke-obligatoriska, det första hittade argumentet antas vara in-filen och det andra argumentet utfilen. Om ingen in-fil eller ut-fil finns/finns angiven läser/skriver man istället från vanliga kommandoprompten i Windows/kommandoraden i terminalen i Linux/Unix. -5-
SUBRUTIN ANROPAD FRÅN KOMMANDO-DEL Jag har definierat en generell subrutin för sortering av godtyckliga typer av data inklusive typerna ovan (om den anropas med ej implementerade typer av data listor/arrayer så leder det till programfel med en felutskrift via ett assert-anrop). -6-
Subrutinen void Create_sorted_list_of_anything(...) deklarerad/definierad i filerna iterate_over_word_list_int_cont.h/my_sort_int_cont.c har definierats att kunna sortera olika typer av datalistor, och ser ut enligt nedan, utdrag ur header-fil: // Parameters: // char *signedness - pointer to string "signed" or "unsigned" to indicate sign of used data type, // the first part of the data type name for the objects sorted // char *type - pointer to string containing the second part of the name of the used data type // of the objects sorted // bool bool_vector_list - boolean that has logical value true if array/list contains pointers to the data objects // sorted // bool bool_vector_list - boolean that has logical value true if array/list contains pointers to the data objects // sorted // bool reverse - boolean that has logical value true if the array/list is to be sorted in the reverse order // bool qsort_bool - boolean that has logical value true if the array/list is to be sorted using qsort method(default when // false is sorting using bubble-sort method) void Create_sorted_list_of_anything(void **sorted_primary_list_ptr, int count, bool reverse, bool qsort_bool, void *primary_list_ptr, const char *signed_ness, const char *type, bool bool_vector_list ); -7-
MACROS SOM ANVÄNDS FÖR ATT DEFINIERA "COMP"-FUNKTIONERNA FÖR DE OLIKA TYPERNA SOM ANVÄNDS AV SUBRUTINEN OVAN: Macro i filen comp_anything_scalar.h: // Macro defining function for comparing // anything scalar (that is a data object itself, // not a pointer to a data object), where type of scalar // is defined by inputs to macro as // SIGNEDNESS A_TYPE #define COMP_ANYTHING_W_DIRECTION(SIGNEDNESS,A_TYPE) signed int comp_##signedness##_##a_type##_w_direction (const void * elem1, const void * elem2 ) { signed int reverse_sign = 1; signed int result = -2; if( comp_direction_reverse ) { reverse_sign = -1; } const SIGNEDNESS A_TYPE *f = ((const SIGNEDNESS A_TYPE *)elem1); const SIGNEDNESS A_TYPE *s= ((const SIGNEDNESS A_TYPE *)elem2); if( *f > *s ) { result = 1; } else if( *f == *s ) { result = 0; } else { result = -1; } return ( reverse_sign * result ); } -8-
Macro i filen comp_anything_vector.h: // Macro defining function for comparing // anything vector (that is a pointer to the data object itself, // not the data object, part of a zero-terminated vector list/array), // where type of scalar is defined by inputs to macro as // // SIGNEDNESS A_TYPE // // Most usual case of this is an ordinary string #define COMP_ANYTHING_VECTOR_W_DIRECTION(SIGNEDNESS,A_TYPE) signed int comp_##signedness##_##a_type##_vector_w_direction (const void * elem1, const void * elem2 ) { signed int reverse_sign = 1; signed int result = -2; if( comp_direction_reverse ) { reverse_sign = -1; } const SIGNEDNESS A_TYPE *f = *((const SIGNEDNESS A_TYPE **)elem1); const SIGNEDNESS A_TYPE *s= *((const SIGNEDNESS A_TYPE **)elem2); while( *f && *s && ( *f == *s ) ) { f++; s++; / } if( *f == *s ) { result = 0; } else if( *f > *s ) { result = 1; } else { result = -1; } return ( reverse_sign * result ); } -9-
INSTALLATION AV GUI FÖR UTVECKLING (UTOM CODEBLOCKS) OCH SERVRAR OCH KLIENTER F. VERSIONSHANTERING INSTALLATION AV CYGWIN MED EMACS GUI, GCC, SVN&SSH KLIENT&SERVER Hämta cygwin från exempelvis www.cygwin.org och installera (det är klokt att göra det i 2 steg, ladda ner först, och installera från lokal kopia sedan, så du kan flytta installationen mellan PC) Installera emacs, gcc, gdb, allt i svn och ssh (det går att söka fram paketen i installationsverktyget) INSTALLATION AV SVN&SSH KLIENTER Installera TortoiseSVN från http://tortoisesvn.net/ (jag använder själv bara Subversion klienten) och ssh klient och agent för nyckel, Putty och Pageant från http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html och installera. -10-
ANVÄNDNING AV SVN ÖVER SSH MOT CYGWIN INSTALLATION OCH KONFIGURATION AV SVN&SSH SERVER I CYGWIN, SAMT KONFIGURATION AV SVN&SSH KLIENT I CYGWIN: Jag har av praktiska skäl valt att använda SVN servern i Cygwin, eftersom jag också jobbar i Cygwin med Emacs som GUI/IDE för utveckling. Jag hittade en tråd nedan, och har själv kompletterat den med uppdaterade instruktioner: http://www.coderhaus.com/?p=8#more-8 En viktig detalj är sedan att stänga ssh för inloggning via password, se tråd: http://linux-tips.org/article/60/disabling-ssh-password-authentication KONFIGURATION AV TORTOISESVN SVN&SSH KLIENT I WINDOWS 7: Det finns information om detta i tråden ovan, men det är viktigt att läsa tillägget här om hur man sätter upp TortoiseSVN för att använda Pageant för hantering av privata nycklar när man kontaktar Cygwin server via svn + ssh (via localhost, IP loop adressen för för den lokala maskinen). (Eftersom jag redan har en SVN server under Cygwin använder jag inte server delen av TortoiseSVN). Se tråd nedan för hur man använder pageant utan att referera till en Putty session (bättre när man skall dela sin utcheckning av SVN-repositoriet med SVN klienten i Cygwin): http://tortoisesvn.net/ssh_howto_logemann.html -11-
Resultat TEST AV PROGRAMKOD Jag har dels testat att sortera listor av C-typerna "signed int" och "signed short int" med kommandot ovan, dels i originalversion, dels hackat för att hantera listor med "signed short int". Jag har också gjort en test-rutin för att testa sortering av listor. Allting har packats i en gzippad tar fil, export_dir.tar.gz Resultatet av testkörningarna finns under: export_dir/test_int - test med sortering av integer export_dir/test_short - test med sortering av short integer export_dir/test_string - test med sortering av strängar Källkoden är bifogad under: export_dir/ - källkod och makefiler Sorteringen har fungerat som den skall i alla de fall jag provat i Cygwin's emulering av Linux/Unix enligt ovan. Det skall inte vara någon skillnad om man kör under Windows och kompilerar med CodeBlocks (projektfil finns) istället samt testar med hj.a. motsvarande batscript (fås från författaren på anmodan). -12-
ERFARENHET FRÅN ATT ANVÄNDA SUBVERSION: Det fungerar bra att använda SVN servern under localhost via ssh, både med Cygwin's egna svn och ssh klienter liksom med motsvarande för Windows 7, TortoiseSVN och putty samt putty's nyckelhantering för ssh via Pageant. Det är dock lite svårt att hitta en enda bra kokboksbeskrivning för hur allt detta skall göras. -13-
Slutsats Jag har implementerat generella C-macron och en generell funktion som skulle kunna användas för att sortera alla normal-långa C typer och strängar av char och andra arrayer av pekare till data. Jag har byggt en mycket bra och fungerande korsmiljö mellan Unix/Linux emulering (via Cygwin) och Windows 7 med bra debug-iden i båda fallen och väl fungerande versionshantering med Subversion. För Cygwin och Emacs gäller också att versionshanteringen integrerats med IDE/GUI-et för programproduktion och debuggning. -14-
Förbättringsförslag Lägg till parametrar för typ av indata till kommando ovan, använd listor/arrayer av typen "void" och "void *" där, och gör sedan generella rutiner för in och ut-matning av de olika typerna på samma sätt som vi gjorde rutiner för jämförelse i subrutinpaketet enligt ovan. Implementera allt detta med preprocessning med automatisk avkänning av typerna, om de är pekare/ej pekare och eventuellt även lesser/bigger-endian (gäller förstås allt typer av data i systemet man jobbar i). Implementera ett test-script i PERL istället för två test-script för respektive Cygwin och Windows 7's kommando-prompt. Registrera den använda datorn med en fri dynamisk DNS-service så att Subversion-servern kan adresseras med ett domännamn istället för med ip-adressen som kan variera. Fixa ett GUI/IDE med Subversion integrerat för Windows 7. -15-