commit 8bca91456122aea62bbd06a72dba8c7c667d97a4 Author: Gürer Özen Date: Fri Jun 3 18:10:51 2005 +0000 sadeleÅŸtirme. diff --git a/images/pisi-gelistirici-small.png b/images/pisi-gelistirici-small.png new file mode 100644 index 00000000..a8b4d4dc Binary files /dev/null and b/images/pisi-gelistirici-small.png differ diff --git a/images/pisi-gelistirici.odg b/images/pisi-gelistirici.odg new file mode 100644 index 00000000..d124f0a5 Binary files /dev/null and b/images/pisi-gelistirici.odg differ diff --git a/images/pisi-gelistirici.png b/images/pisi-gelistirici.png new file mode 100644 index 00000000..e370221c Binary files /dev/null and b/images/pisi-gelistirici.png differ diff --git a/images/pisi-istemci-small.png b/images/pisi-istemci-small.png new file mode 100644 index 00000000..c98fc21a Binary files /dev/null and b/images/pisi-istemci-small.png differ diff --git a/images/pisi-istemci.odg b/images/pisi-istemci.odg new file mode 100644 index 00000000..a98b1f95 Binary files /dev/null and b/images/pisi-istemci.odg differ diff --git a/images/pisi-istemci.png b/images/pisi-istemci.png new file mode 100644 index 00000000..4b5b3eed Binary files /dev/null and b/images/pisi-istemci.png differ diff --git a/pisi.lyx b/pisi.lyx new file mode 100644 index 00000000..ec495baa --- /dev/null +++ b/pisi.lyx @@ -0,0 +1,1904 @@ +#LyX 1.3 created this file. For more info see http://www.lyx.org/ +\lyxformat 221 +\textclass article +\language turkish +\inputencoding auto +\fontscheme default +\graphics default +\paperfontsize default +\spacing single +\papersize Default +\paperpackage a4 +\use_geometry 0 +\use_amsmath 0 +\use_natbib 0 +\use_numerical_citations 0 +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation skip +\defskip medskip +\quotes_language english +\quotes_times 2 +\papercolumns 1 +\papersides 1 +\paperpagestyle default + +\layout Title + +PISI +\newline +(Packages Installed Succesfully as Intented) +\layout Author + +S.Çağlar Onur , Onur Küçük , +\newline +Barış Metin +\layout Date + +29 Mart 2005 +\layout Date + +Sürüm 0.3 +\layout Standard +\pagebreak_top \pagebreak_bottom + +\begin_inset LatexCommand \tableofcontents{} + +\end_inset + + +\layout Section + +Giriş +\layout Standard + +Paket, bir uygulamayı ya da işletim sisteminin bir parçasını tüm bileşenleriyle + toplu olarak ifade eden bir kavramdır. + Uygulamaların bir yerden bir yere taşınması (örneğin bir CD yada ağ kaynağından + gelip, sisteme kurulması) sırasında bazı bileşenlerin geride unutulmamasını + sağlar. + Bir sistemdeki onbinlerce dosyayı, görevleri ve ait oldukları uygulamalar + bazında birkaç yüz pakete ayırarak yönetilebilir kılar. + Kullanıcının büyük bir sistemde neler bulunduğuna hakim olabilmesini kolaylaştı +rır. +\layout Standard + +Bu paketleri kurup kaldırmak, çeşitli kaynaklardan temin etmek, sorgulamak, + sistemdeki değişiklikleri takip etmek için, paket yöneticisi adını verdiğimiz + bir uygulamaya ihtiyaç vardır. +\layout Section + +Paket Yöneticisi Gereksinimleri +\layout Subsection + +Kullanıcı gereksinimleri +\layout Itemize + +Bilişim okuryazarı adını verdiğimiz hedef kullanıcımızın temel isteği, sisteme + istediği uygulamaları kurabilmektir. +\begin_deeper +\layout Itemize + +Kur emri, komut satırı, grafik arayüzler, ya da sistemin otomatik olarak + pakete ihtiyaç olduğunu saptamasıyla kolayca verilebilmeli, mümkün olduğunca + soru sorulmadan ve kullanıcıyı rahatsız etmeden yerine getirilmelidir. +\layout Itemize + +Aynı şekilde yapılandırma sorularından kaçınılmalıdır. + Bu işler ÇOMAR tarafından otomatik halledilecek, ya da kullanıcının verdiği + emirlerle sonradan yapılacaktır. + Bu, örneğin sunucu uygulamaları kurulurken sunucu ayarı soruları vs sorulmaması +nı getirir. +\layout Itemize + +Kurulum elden geldiğince hızlı olmalıdır. +\end_deeper +\layout Itemize + +Kurulu programların yeni sürümleri çıktıkça, veya üzerinde düzeltmeler ve + güvenlik onarımları yapılmış yeni paket sürümleri yayımlandıkça, bilişim + okuryazarı kullanıcımız elindeki uygulamaları güncellemek isteyecektir. +\begin_deeper +\layout Itemize + +Paketin her sürümünün önem derecesini (yeni özellikler, hata düzeltmeleri, + güvenlik açığı düzeltmesi) belirtebilmek gereklidir. + Böylece kullanıcı vakti yada ağ bağlantı hızı yetersiz olduğunda acil önem + taşıyan ve yapılması gerekli güncellemeleri, diğerlerinden kolayca ayırabilecek +tir. +\layout Itemize + +Bir paketin eski veya deneysel sürümlerini kurmayı, hedef kullanıcımızın + bir ihtiyacı olarak görmüyoruz. + Kullanıcımız paketteki en son düzeltmeleri isteyecektir, ve eğer uygulama + ayrı özellik kümesine sahip iki ayrı yoldan geliştirilmekteyse, bu uygulamayı + iki ayrı paket olarak tutabiliriz. + Bu basitleştirmedeki amacımız paket yöneticisini basit tutmaktan ziyade, + kullanıcının paketin eski bir sürümünü kurup, sonra bunu unutarak daha + sonra çıkacak güncellemeleri kaçırmasını önlemektir. +\layout Itemize + +Benzeri şekilde, paketler üzerinde ayrı ayrı güncelleme politikası belirleyebilm +ek, faydasından çok kafa karışıklığı yaratacağından dolayı desteklenmeyecektir. +\end_deeper +\layout Itemize + +Nerdeyse her uygulama kendi sürüm numarası verme politikasına sahip olduğundan, + paketin asıl sürüm numarası yanında, düzenli olarak artacak bir numara + daha vererek, kullanıcının kolayca hangi sürümlerin yeni olduğunu ayırt + edebilmesini sağlamalıyız. + Aynı uygulama sürümünün çeşitli hata düzeltmeleri içeren farklı paket sürümleri + olabileceği de düşünülürse bunun önemi anlaşılır. +\layout Itemize + +Kullanıcı, artık ihtiyaç duymadığı bir uygulamayı, yer ve takip tasarrufu + amacıyla kaldırmak isteyebilir. + Kullanıcının bu seçimi kolayca yapabilmesi için, ihtiyaç duyulmayan paketler, + kurulu paketlerin kapladığı alan gibi bilgileri sunabilmeliyiz. +\layout Itemize + +Kullanıcı sistemde nelerin kurulu olduğunu, hangi paketleri kurabileceğini, + kurulu paketlere ait bilgileri, sistemdeki bir bileşen veya dosyanın hangi + uygulamaya ait olduğunu ve benzeri bir takım bilgileri sorgulayabilmelidir. +\layout Itemize + +Varolan paket yöneticilerinin (rpm, dpkg, portage, vs) paket kapsamları + kullanıcılara bazı zorluklar yaşatmaktadır. +\begin_deeper +\layout Itemize + +Kapsam çok geniş olduğunda (örneğin tek bir KDE pakedi), kullanıcı her güncellem +ede çok büyük dosyalar çekmekte, sisteme kullanmayacağı bileşenleri (örneğin + KDE oyunları, ya da bilmediği dillere ait destekler) kurmaktadır. +\layout Itemize + +Kapsam dar tutulup küçük paketler oluşturulduğunda ise paket sayısının artmasınd +an dolayı, paket kavramının getirdiği soyutlama azalmakta, sisteme büyük + bir platformu kurmak için kendisi bir bileşen içermeyip yalnızca diğer + paketleri kurdurtan sanal paketler gibi yama çözümler gerekmektedir. +\layout Itemize + +Kullanıcıya uygulamaları belli özellikleri (örneğin geliştirme kitleri, + grafik arayüzü, dil destekleri, ek uygulamaları, vs) opsiyonel olarak kurulabil +ecek biçimde sunabilirsek, ve paket temin sistemimizi yalnızca gereken özellikle +ri getirecek biçimde inşa edersek, hem kapsam sorunları, hem vakit ve ağ + bağlantı hızı açısından yaşanan sorunlar çözülecektir. +\layout Itemize + +Uygulamayı kod olarak çekip, değişik özellikler ile derleyebilecek portage + benzeri bir sistem hedef kullanıcımıza zorluklar çıkaracak ve doğrudan + bir fayda sağlamayacaktır. + Ancak kimi programların farklı biçimde derlenmiş hallerini pakede ayrı + bir özellik olarak koyabiliriz (örneğin mplayer pakedinde farklı işlemciler + için derlenmiş birkaç tane +\emph on +mplayer +\emph default + programı gibi). +\end_deeper +\layout Itemize + +Paketler farklı hedeflere kurulabilecek biçimde +\begin_inset Quotes eld +\end_inset + +relocatable +\begin_inset Quotes erd +\end_inset + + özellik taşımalıdır. + Bu, farklı hedeflere kurulum, ya da başkasına ait sistemde ev dizinine + kurulum gibi yeteneklerin sağlanması için gereklidir. +\layout Itemize + +Paket bileşenlerinin değişip değişmediği kontrol toplamları, hash fonksiyonları + gibi yöntemlerle tespit edilebilir. + Paket yöneticisinin böyle bir durumu kontrol edebilmesi, ve örneğin bir + kullanıcı hatası sonucu silinen/değişen dosyaları tekrar temin edip düzeltebilm +esi kullanıcıya kolaylık sağlar. +\layout Subsection + +Paketleyici gereksinimleri +\layout Itemize + +Paket hazırlamak kolay olmalıdır. +\layout Itemize + +Kolayca paket oluşturabilmek için, tercihen bir grafik arayüz ile paket + hazırlanabilmelidir. + Üst geliştirici kodunu alıp, gerekli bilgileri hazırlatacak, gerekli işaretleme +leri kolayca yapabilecek bir araç kullanılabilir. +\layout Itemize + +Paketleyici hatalarının farkedilmeden gözden kaçması önlenmelidir. +\layout Subsection + +Paket kaynağı gereksinimleri +\layout Itemize + +Kullanıcı paketleri CD, disket, internet gibi çeşitli kaynaklarla ulaşıp + kurabilmek isteyecektir. + Temel olarak iki tip kaynak sözkonusudur. +\layout Itemize + +İlk tip, pakedi tek bir dosya olarak taşıyabilen ve programı disketle, epostayla + ve benzeri yollarla dağıtmaya uygun bir arşiv dosyasıdır. +\begin_deeper +\layout Itemize + +Bu arşiv içinden belirli bir dosyaya, bütün arşivi açmadan erişilebilmelidir. +\layout Itemize + +Mümkünse arşivin yaygın olarak bilinen ve kullanılan araçlarla açılabilmesinde + yarar vardır. +\end_deeper +\layout Itemize + +İkinci tip kaynak ise internet yada yerel ağ üzerinden bir paket grubunun + indeks bilgilerini ve kendilerini sunabilecek bir +\begin_inset Quotes eld +\end_inset + +depo +\begin_inset Quotes erd +\end_inset + + sunucusudur. +\begin_deeper +\layout Itemize + +Aynı biçimde, bir pakedin belirli dosyalarına direk erişilebilmelidir. + Paketler Web üzerinden sunulurken bunu sağlamak için pakedi açık olarak + tutabiliriz. +\end_deeper +\layout Itemize + +Kullanıcı birden fazla kaynaktan paketleri temin edebilmelidir. +\layout Subsection + +Güvenlik gereksinimleri +\layout Itemize + +Kullanıcının CD, internet, vs gibi değişik ortamlar aracılığı ile temin + ettiği paketlerin kimden geldiğini bilebilmesi, ve içeriğinin yolda değişmediği +nden emin olması için bir dijital imza sistemi desteklenmelidir. +\layout Itemize + +Gerektiğinde pakedi oluşturan kişinin imzası dışında, üçüncü parti kurum + veya kişilerin de pakedi deneyip, güvendiğini belirtebilmesi için, birden + fazla kişi tarafından pakedin imzalanabilmesi iyi olacaktır. +\layout Subsection + +Yapılandırma Yöneticisi (ÇOMAR) gereksinimleri +\layout Itemize + +Bir paket kurulduktan sonra, pakete ait CSL betikleri ÇOMAR'a bildirip kayıt + ettirmelidir. +\layout Itemize + +Bir paket kaldırılmadan önce ÇOMAR'dan bu pakete ait betikleri kaldırmasını + istemelidir. +\layout Itemize + +Bir paket eğer CSL betiği sağlıyorsa, paketin hangi OM dallarına ait betikler + içerdiği bilgisini tutmalıdır. +\layout Itemize + +Verilen bir OM dalı için, hangi paketlerin bu dala ait betik içerdiğini + verebilmelidir. +\layout Itemize + +Kurulması emredilen bir paket, kitaplık ve programların yanısıra OM üzerinden + sağlanan bazı görevlere ihtiyaç duyabilir. + Bu durumda paket yöneticisinin o bacaktaki görevi sağlayan uygun bir pakedin + kurulu olup olmadığına bakması, gerekiyorsa o görevi sağlayan paketlerden + birini kurması gereklidir. +\layout Itemize + +Paket yöneticisi, bir pakete ait bir dosyanın sistemde nereye yerleştirilmiş + olduğunu söyleyebilmelidir. +\layout Section + +Neden PİSİ? +\layout Standard + +Gereksinimlerimizi sağlayabilmek için çeşitli tipte bağımlılıklar, farklı + özelliklerle kurulabilen paketler, en az dosya indirme ile kurulum gibi + özelliklere ihtiyacımız olacaktır. + Halihazırdaki paket sistemleri bunları sağlamadıkları için yeni bir paket + yöneticisi yazmak gereği doğmuştur. +\layout Standard + +Bu amaçla PİSİ (Packages Installed Successfully as Intented) adını verdiğimiz + yazılımı geliştiriyoruz. +\layout Section + +PİSİ Tasarımı +\layout Subsection + +PSPEC Dosyası +\layout Standard + + +\series bold +PSPEC (PİSİ SPEC) +\series default + dosyası paketin oluşturulması için gerekli olan temel bilgiyi tanımlar. + PSPEC dosyası, oluşturulacak paketin ne olduğu, hangi başka paketlere bağımlılı +k içerdiği, nasıl derlenmesi ve sisteme nasıl kurulması gerektiğini tanımlayan + betikleri gösteren; kısaca paketin oluşturulması için gerek duyulan her + türlü bilginin içinde bulunduğu dosyaya verilen isimdir. + +\layout Standard + +Bir PSPEC dosyasından, dolayısı ile bir kaynaktan birden fazla paket oluşturulab +ilir. + Örneğin kpdf paketi kdebase-sürüm.no.tar.gz kaynağından oluşturulabilecek + yalnızca bir pakettir. +\layout Standard + +PSPEC dosyalarının içerebileceği alanlar şu şekilde tanımlanmıştır; +\layout Itemize + + +\series bold +Global +\begin_deeper +\layout Itemize + + +\series bold +Meta +\begin_deeper +\layout Itemize + + +\series bold +Homepage: +\series default +Uygulamanın web sitesinin URL'sini belirtir. +\layout Itemize + + +\series bold +Version: +\series default + Uygulamanın sürüm numarasını belirtir. + (3.4.0 gibi) +\layout Itemize + + +\series bold +Release: +\series default + Bu uygulama için hazırlanan paketin sürüm numarasını belirtir. + (12 gibi) +\layout Itemize + + +\series bold +CFlags: +\series default +Paketin hangi ek derleyici bayrakları ile derleneceğini belirtir. +\layout Itemize + + +\series bold +Source: +\series default + Uygulamanın orjinal kaynak kodlarının bulunduğu adresi belirtir. +\layout Itemize + + +\series bold +SourceCheckSum: +\series default +Orjinal kaynak kodun doğrulama bilgisini (MD5, SHA v.s) verir. +\layout Itemize + + +\series bold +File(s): +\series default +Uygulama ile gelmeyen ama sistemde bulunması gereken dosyaları belirtir. + File, farklı dosyalar için birden fazla tekrarlanabilir. + (init betikleri, belirli bir yere yerleştirilecek simgeler, vb.) +\begin_deeper +\layout Standard + + +\series bold +Attribute(s) +\layout Itemize + + +\series bold +Destination: +\series default +Harici dosyaların kopyalanacağı yeri belirtir. + Kaynak kod açıldığında oluşacak dizin sıradüzeni (hiyerarşi) içerisindeki + konumunu bağlantılı (rölatif) olarak gösterir. +\end_deeper +\layout Itemize + + +\series bold +Patch(s): +\series default +Uygulamaya hazırlanan yamaları ve uygulanış sıralarını belirtir. +\begin_deeper +\layout Standard + + +\series bold +Attribute(s) +\layout Itemize + + +\series bold +Order: +\series default + Uygulanacak yamaların sırasını belirtir. + Nümerik bir değerdir. +\end_deeper +\layout Itemize + + +\series bold +Packager(s): +\series default +Paketi oluşturan kişilerin adı/soyadı ve e-posta adresi belirtir. +\begin_deeper +\layout Itemize + + +\series bold +PackagerName: +\series default + Paket geliştiricisinin adı ve soyadı. +\layout Itemize + + +\series bold +PackagerEmail: +\series default + Paket geliştiricisinin e-posta adresi. +\end_deeper +\layout Itemize + + +\series bold +License(s): +\series default +Uygulamanın lisansını belirtir. + (GPL, BSD v.s gibi) +\end_deeper +\layout Itemize + + +\series bold +BuildRequirments: +\series default + Kaynağın derlenmesi sırasında ihtiyaç duyulan bağımlılıklardır. +\begin_deeper +\layout Itemize + + +\series bold +BuildTimePackage(s): +\series default +Kaynağın derlenebilmesi için mutlaka sistemde kurulu olarak bulunması gereken + paketleri belirtir. +\begin_deeper +\layout Itemize + + +\series bold +Name: +\series default + Bağımlı olunan paketin adıdır. +\layout Itemize + + +\series bold +Version: +\series default + Bağımlı olunan tek bir sürüm numarasını bildirir. +\layout Itemize + + +\series bold +VersionFrom: +\series default + Bu sürüm numarasından sonraki tüm sürüm numaralarına bağımlılığı tarif + eder. +\layout Itemize + + +\series bold +VersionTo: +\series default + Bu sürüm numaralarına kadar olan bağımlılığı tarif eder. +\end_deeper +\end_deeper +\layout Itemize + + +\series bold +Actions: +\series default +Kaynağın derlenmesinden kurulumuna kadar kullanılacak olan BASH betiklerini + işeret eder. + Bash betikleri PSPEC dosyasının bulunduğu dizindeki +\emph on +actions +\emph default + dizininde saklanırlar. +\begin_deeper +\layout Itemize + + +\series bold +Setup: +\series default +Kaynağın kurulması, ayarlanması için gerekli bash betiğinin adını verir. + Kaynak derleme dizinine Source, File ve Patch bölümlerinde ifade edilen + dosyalar kullanılarak PİSİ tarafından otomatik bir şekilde açılır. + Derleme öncesi kaynağa yapılması gereken tüm işlemler (Autotools kullanan + paketlerde ./configure betiğinin çalıştırılması gibi) setup betiği tarafından + yapılır. +\layout Itemize + + +\series bold +Build: +\series default +Kaynağın derlenmesi için gerekli bash betiğinin adını verir. +\layout Itemize + + +\series bold +Test: +\series default +Kaynağı derlendikten sonra test edilmesi için gerekli bash betiğinin adını + verir. +\layout Itemize + + +\series bold +Install: +\series default +Kaynağı sisteme kuran bash betiğinin adını verir. + Bu betik içerisinde kaynak kullanılmakta olan sistemin dizin sıradüzeninden + bağımsız olarak, PİSİ tarafından tanımlanan kurulum dizinine (installroot) + kurulur. +\end_deeper +\layout Itemize + + +\series bold +History: +\series default +Paket üzerine bir güncelleme yapıldığında, güncelleme ile ilgili temel bilgileri + verecektir. + +\begin_deeper +\layout Itemize + + +\series bold +Update: +\series default + Kaynağa yapılan bir güncellemeyi tarif eder (yeni yama, yeni bir dosya + eklenmesi veya Actions içerisindeki betiklerden birinin yeniden düzenlenmesi + gibi). +\begin_deeper +\layout Itemize + + +\series bold +Date: +\series default +Güncellemenin yapıldığı tarih ve saat bilgisini belirtir. +\layout Itemize + + +\series bold +Version: +\series default +Güncellemenin yapıldığı versiyonu belirtir. +\layout Itemize + + +\series bold +Release: +\series default + Güncellemenin yapıldığı revizyonu belirtir. +\layout Itemize + + +\series bold +Status: +\series default +Güncellemenin kritikliği belirtir. + (BugFix, SecurityUpdate, Enhancement) +\end_deeper +\end_deeper +\end_deeper +\layout Itemize + + +\series bold +Package +\begin_deeper +\layout Itemize + + +\series bold +Meta +\begin_deeper +\layout Itemize + + +\series bold +Name: +\series default + Paketin birden fazla küçük parçaya bölündüğünde oluşacak parçalardan ilkinin + adını belirtir. +\layout Itemize + + +\series bold +Description: +\series default +Uygulama hakkında özet bir açıklayıcı bilgi içerir. + Çoklu dil desteğine sahiptir. +\layout Itemize + + +\series bold +Container(s): +\series default + Uygulamanın hangi uygulama grubuna dahil olduğu bilgisini tanımlar. + Bir paket birden fazla +\series bold +\emph on +Container +\series default +\emph default +'a dahil olabilir. + (Farklı aitlikler olabilir, bir ana kaynaktan türeme veya belirli, ortak + bir işlevi yerine getirme gibi. + +\series bold +\emph on +Container +\series default +\emph default + bunların hepsini tanımlamaktadır). + +\series bold +\emph on +Container +\series default + tanımları her +\series bold +Pardus +\series default + sürümü için sabit bir liste olarak sunulacaktır. + +\emph default + Paket geliştiricileri bu listeyi kullanarak paketledikleri yazılımı bir/bir + kaç +\series bold +Container +\series default +'a dahil edebilirler. +\end_deeper +\layout Itemize + + +\series bold +RunTimeRequirements: +\series default +Oluşturulan paketin kurulabilmesi/kullanılabilmesi için sağlanması gereken + bağımlılıklardır. +\begin_deeper +\layout Itemize + + +\series bold +RunTimePackage: +\series default +Uygulamanın derlendikten sonra çalışabilmesi veya ek özellik kazanabilmesi + için gerekli paketleri belirtir. +\begin_deeper +\layout Itemize + + +\series bold +Name: +\series default + Bağımlı olunan paketin adını belirtir. +\layout Itemize + + +\series bold +Version: +\series default + Bağımlı olunan tek bir sürüm numarasını belirtir. +\layout Itemize + + +\series bold +VersionFrom: +\series default + Bu sürüm numarasından sonraki tüm sürüm numaralarına bağımlılığı tarif + eder. +\layout Itemize + + +\series bold +VersionTo: +\series default + Bu sürüm numaralarına kadar olan bağımlılığı tarif eder. +\end_deeper +\layout Itemize + + +\series bold +ComarOM: +\series default +Uygulamanın +\series bold +ÇOMAR +\series default +'ın hangi +\series bold +OM +\series default + bacağına ihtiyacı olduğunu belirtir. +\end_deeper +\layout Itemize + + +\series bold +Provides +\begin_deeper +\layout Itemize + + +\series bold +CSL: +\series default +Paketin yanında taşıdığı +\series bold +CSL/CSL +\series default +'lerin nerede/nerelerde olduğunu belirtir. +\layout Itemize + + +\series bold +OM: +\series default + Uygulamanın +\series bold +ÇOMAR +\series default +'ın +\series bold +OM +\series default + bacağında hangi uca/uçlara oturduğunu belirtir. +\end_deeper +\layout Itemize + + +\series bold +Conflicts +\begin_deeper +\layout Itemize + + +\series bold +ConflictedWith: +\series default +Paketin kurulmasını engelleyen, kurulduğu zaman sistemde hangi paketler + ile çakışacağını, hangi paketler ile uyumsuz olduğunu belirtir. + (modutils ve module-init-tools gibi) +\end_deeper +\layout Itemize + + +\series bold +Provides (Paketin bir parçası OM ve CSL provide edebilir) +\begin_deeper +\layout Itemize + + +\series bold +CSL: +\series default +Paketin yanında taşıdığı +\series bold +CSL/CSL +\series default +'lerin nerede/nerelerde olduğunu belirtir. +\layout Itemize + + +\series bold +OM: +\series default + Uygulamanın +\series bold +ÇOMAR +\series default +'ın +\series bold +OM +\series default + bacağında hangi uca oturduğunu belirtir. +\end_deeper +\end_deeper +\layout Standard + + +\emph on + +\begin_inset Marginal +collapsed true + +\layout Standard + + +\emph on +örnek 1-2 spec dosyası hazırlayıp buraya yerleştirmek gerekiyor +\end_inset + + +\layout Standard + +PSPEC dosyasında Global bölümü kaynaktan oluşturulacak tüm paketleri etkiler. + Tanımlanan her Package bölümü ise kaynaktan oluşturulacak bir paketin tarifidir. + Her PSPEC dosyasında en az bir Package bölümü olmak zorundadır. +\layout Standard + +PSPEC dosyası, belirlenecek paket formatının içinde +\series bold +\emph on +XML +\series default +\emph default + dosyası olarak tutulacaktır. + XML dosyalarının doğrulanması için kullanılabilecek bilgi +\emph on +pisi-spec.dtd +\emph default + dosyasında tanımlanmıştır. +\layout Standard + +Aynı uygulamanın farklı mimarilere veya farklı amaçlara hizmet eden sürümlerini + paket haline getirmek için farklı +\series bold +PSPEC +\series default + dosyaları kullanılacaktır. + +\layout Subsection + +metadata.xml +\layout Standard + + +\series bold +Metadata +\series default + dosyası bir uygulamanın paket haline geldikten sonra yanında taşıyacağı + ve paket ile ilgili bilgileri barındıran dosyadır. + +\layout Standard + + +\series bold +Metadata +\series default + dosyası sadece oluşturulan paket ile ilgili bilgileri tutmaktan sorumludur. + Paket'den hakkında temel bilgi bu dosyadan alınacaktır. +\layout Standard + +Bu bilgilerin büyük kısmı +\series bold +PSPEC +\series default + dosyasının işlenmesi sonucu ile +\series bold +Metadata +\series default + dosyasına yazılmaktadır. + PSPEC dosyasındaki Global/Meta, Global/History ve Package içerisindeki + tüm bilgiler Metadata içerisine yazılır. + Metadata PSPEC dosyasından alınan bilgilerin yanında kaynak derlendikten + ve paket oluşturulduktan sonra alınabilecek diğer bilgileri de içerir (paketin + kurulduktan sonra sistemde kapyacağı alanın boyutu gibi). +\layout Standard + + +\series bold +Metadata +\series default + dosyasının içeriği şöyle tanımlanmıştır; +\layout Standard + + +\begin_inset Marginal +collapsed true + +\layout Standard + +metadata.xml'i de spec dosyasında olduğu gibi detaylandırmak ve XML biçimi + şeklinde (iç içe) yazmak gerekiyor +\end_inset + + +\layout Itemize + + +\series bold +Metadata +\begin_deeper +\layout Itemize + + +\series bold +PSPEC dosyasının Global/Meta bölümü +\layout Itemize + + +\series bold +PSPEC dosyasının Global/History bölümü +\layout Itemize + + +\series bold +PSPEC dosyasının +\series default + +\series bold +ilgili Package bölümü +\layout Itemize + + +\series bold +Distribution: +\series default + Paketin ait olduğu dağıtımı belirtir (Pardus). +\layout Itemize + + +\series bold +DistributionRelease: +\series default + Paketin ait olduğu dağıtımın hangi sürümü için oluşturduğunu belirtir (1.0). +\layout Itemize + + +\series bold +Architecture: +\series default +Paketin hangi mimari için yapıldığını belirtir. +\layout Itemize + + +\series bold +InstallSize: +\series default +Paketin sisteme kurulduğunda kaplayacağı alanın tahmini boyutunu belirtir. +\end_deeper +\layout Standard + +Yukarıda tanımlanan +\series bold +Metadata +\series default + dosyası, belirlenecek paket formatının içinde +\series bold +\emph on +XML +\series default +\emph default + dosyası olarak tutulacaktır. + Metadata XML dosyalarının doğrulanması için kullanılabilecek bilgi +\emph on +pisi-metadata.dtd +\emph default + dosyasında tanımlanmıştır. +\layout Subsection + +files.xml +\layout Standard + +Kaynak derlendikten sonra oluşan dosyaların oluşturulan pakete göre +\series bold +(Package) +\series default + sınıflandırılması gerekmektedir. + Tek bir kaynaktan birden fazla paket oluşturulması, kaynağın derlenmesinden + sonra oluşan dosyaların sınıflandırılması ile olur. +\layout Standard + +files.xml dosyası paket geliştirme aracı/araçları ile oluşturularak paket + içerisine yerleştirilir. +\layout Itemize + + +\series bold +Files +\begin_deeper +\layout Itemize + + +\series bold +Package: +\series default +Dosya serisinin hangi +\series bold +\emph on +SubPackage +\series default +\emph default +'i oluşturduğunu belirtir. + (örn. + mysql-devel, mysql-client, mysql-server , mysql-doc) +\layout Itemize + + +\series bold +File: +\series default + Pakete dahil edilecek bir dosyayı tarif eder. +\begin_deeper +\layout Itemize + + +\series bold +Path: +\series default + Dosyanın, paket içerisindeki yerini belirtir. + +\series bold +PISI +\series default + gereklerinden biri paketin belirtilen konuma kurulabilmesi olduğu için + konum bilgisi bağımlı (rölatif) olarak verilir. +\layout Itemize + + +\series bold +Type: +\series default + Dosyanın tipini belirtir. + Paket sisteme kurulduğunda, veritabanına bu tip tanımı ile işaretlenerek + yerleştirilecektir. + (binary, conf, lib, data gibi) +\layout Itemize + + +\series bold +Hash: Path +\series default + ile belirtilen dosyanın +\emph on +hash +\emph default + değerini verir. +\end_deeper +\end_deeper +\layout Standard + +files.xml dosyalarının doğrulanması için kullanılabilecek bilgi +\emph on +pisi-files.dtd +\emph default + dosyasında tanımlanmıştır. +\layout Subsection + +PSPEC Deposu +\layout Standard + +Paketleri oluşturmak için gerekli PSPEC dosyaları hiyerarşik bir yapıda + bir +\emph on +subversion +\emph default + deposunda sunulacaktır. + Geliştirme işlemleri bu depo üzerinde yapılacaktır. + PSPEC deposunda paketler +\emph on + +\begin_inset Quotes eld +\end_inset + + +\series bold +\emph default +ilk harflerine göre +\series default +\emph on + +\begin_inset Quotes erd +\end_inset + + +\emph default + konumlandırılırlar. + Her paket kendine ait bir dizinde PSPEC dosyası, paket oluşturma için gerekli + olan ek dosyalar ve yamaların içinde bulunduğu files +\series bold +/ +\series default + dizini ve paket oluşturmada kullanılacak betiklerin bulunduğu actions +\series bold +/ +\series default + dizinine sahiptir. +\layout Standard + +Bir geliştiricinin +\series bold +Pardus Linux +\series default +'a paket yapması için yalnızca PSPEC depo sıradüzeninde paket için gerekli + olan dosyaları sağlaması yeterlidir. + +\series bold +Pardus Linux +\series default +'un belirli zamanlarda kullanıcılara sunulacak sürümlerini oluşturmak için + bu PSPEC deposundaki bu bilgiler kullanılarak PİSİ paketleri oluşturulacaktır. + +\layout Standard + +Bir yazılımın birden fazla sürümünün depoya eklenmesi gerekiyorsa, farklı + paket isimleri ile depoya yerleştirilirler. + (gtk1, gtk2 gibi...) +\layout Subsubsection + +Örnek PSPEC Deposu Sıradüzeni +\layout Itemize + + +\series bold +a +\series default +/ +\begin_deeper +\layout Itemize + + +\series bold +a +\series default +cpid/ +\begin_deeper +\layout Itemize + + +\series bold +a +\series default +cpid-1.0.2.pspec +\layout Itemize + +files.xml +\layout Itemize + + +\series bold +files/ +\begin_deeper +\layout Itemize + +acpid-1.0.2-branch.patch +\layout Itemize + +acpid.init +\end_deeper +\layout Itemize + + +\series bold +actions/ +\begin_deeper +\layout Itemize + +setup.sh +\layout Itemize + +build.sh +\layout Itemize + +install.sh +\end_deeper +\end_deeper +\end_deeper +\layout Subsection + +Container +\layout Standard + +(Will be...) +\layout Standard + +Container nedir? Ne işe yarıyor? +\layout Standard + +Container listesi... +\layout Subsection + +İkili Paket Deposu +\layout Standard + +Oluşturulan ikili paketler +\series bold +PSPEC +\series default + dosyalarının tutulduğu hiyerarşik yapının aynısına sahip bir depoda sunulacaktı +r. + Paketlerin içerisinde bulunan +\emph on +metadata.xml +\emph default + dosyaları depodaki paketlerden alınarak ve birleştirilerek +\series bold +pisi.index +\series default + isminde bir içerik (depo içeriği) dosyası düzenli aralıklar ile oluşturulacaktı +r ( +\series bold +Çağlar: +\series default + Burada cron illa mecbur yöntem olmak zorunda değil sanki, şimdilik zikretmeyeli +m, build farm zamanında bir çözüm buluruz ). + İçeriğinde mevcut sürümün bilgilerini içerecek bir dosya oluşturulacaktır. + Bu dosya dağıtımın tüm paketleri için şu bilgileri içerecektir; +\layout Itemize + + +\series bold +Name: +\series default +Paketin adı +\layout Itemize + + +\series bold +Definition: +\series default +Paketin kısa tanımı +\layout Itemize + + +\series bold +Version: +\series default +Yazılımın sürüm numarası +\layout Itemize + + +\series bold +Release: +\series default +Paketin revizyon numarası (kaçıncı paketlenmesi) +\layout Itemize + + +\series bold +License: +\series default +Paketin lisansı +\layout Itemize + + +\series bold +RuntimeReq: +\series default + Kurulmak/Çalışmak için hangi paketlere ihtiyacı var? +\layout Itemize + + +\series bold +Provides: +\series default +Paket neler sağlıyor (tanım yukarıda) +\layout Itemize + + +\series bold +History: +\series default + PSPEC dosyasından alınmış olan paket durumunu gösteren bölüm. +\layout Itemize + + +\series bold +Conflicts: +\series default + Paketin sistemde hangi paketler ile aynı anda kurulu olarak bulunamayacağı + bilgisi. +\layout Itemize + + +\series bold +PackageSize: +\series default +Paketin kapalı (kurulmadan önceki) boyutu. + Bu bilgi pisi paketinin dosya sisteminde kapladığı alan alınarak oluşturulacakt +ır. +\layout Itemize + + +\series bold +InstalledSize: +\series default +Paket kurulduğunda sistemde ne kadar yer kaplayacak? +\layout Standard + + +\series bold +pisi.index +\series default + dosyasının biçimi XML'dir. + Dosyanın doğrulanması için kullanılabilecek bilgi +\emph on +pisi-index.dtd +\emph default + dosyasında tanımlanmıştır. +\layout Standard + +Bu dosya değiştirilmeyecek ve sadece Dağıtım Sürüm değiştirdiği zaman yenisi + oluşturulacaktır. + Aktif sürüm sırasında tüm değişiklikler +\series bold +ChangeSet +\series default + olarak sunulacaktır. + İstemci bilgisayarlarca çekilecek ve bağımlılık çözme, paket veritabanını + arama, paket kurma/kaldırma işlemleri bu dosyaların +\series bold +pisi.index +\series default + ile birleştirilmesi yardımı ile yapılacaktır. + +\layout Standard + + +\series bold +ChangeSet +\series default +'ler +\series bold +pisi.index +\series default + dosyasına yama olarak sunulacaklardır. + Kolay oluşturulan, az bant genişliği isteyen ve efektif olmaları açısından + içeriklerini +\series bold +pisi.index +\series default +'in bir önceki revizyonlarından olan farkları arttırımsal (incremental) + olarak oluşturacaktır. +\layout Standard + +Kullanıcı bilgisayarında oluşturulacak depo veritabanı pisi.index ve Changeset'le +r yardımı ile yaratılacaktır. + Kullanıcının depodaki paketlerin en güncel bilgilerini alabilmesi için + depo veritabanını düzenli olarak güncellemesi gerekmektedir. + Bu işlem bir arkaplan uygulaması ile otomatik olarak yaptırılabilir. +\layout Standard + +Depoya eklenecek ikili paketler geliştiriciden alınmayacak, PİSİ derleme + ortamı tarafından hazırlanıp uygun görülen depoya yerleştirilecektir. + Böylece geliştiricinin sisteminden kaynaklanabilecek olası problemlerin + (sürüm farklılıkları, sorunlu ya da güvensiz yazılımlar vs.) önüne geçilecektir. +\layout Standard + +PİSİ istemcisi birden fazla depo ile çalışabilecektir. + Birden fazla depo tanımlanması durumunda öncelikli depo her zaman +\series bold +Pardus Resmi Deposu +\series default + olacaktır. + Diğer depolar eşit önceliğe sahip olacaklardır ve kullanıcı elle belirtmediği + sürece tüm depolarda bulunan paketler resmi depodan alınacaktır. +\layout Subsection + +PİSİ Paketinin Yapısı +\layout Standard + +PİSİ paketleri ikili bir biçimde sunulacaktır. + Bu bölüm paketlerin biçemini (format) ve içerdiklerini tanımlamaktadır. +\layout Standard + + +\series bold +PISI +\series default + paketi, içerisinde aşağıdaki bölümler olan bir +\emph on +PK-ZIP +\emph default + paketidir. + Bu sayede paketler standart araçlar ile açılabilir/erişilebilir olacaklardır. +\layout Itemize + + +\series bold +metadata.xml: +\series default + PSPEC dosyasından alınacak ve üzerine eklenecek bilgiler ile oluşturulacak + Meta bilgisi +\layout Itemize + + +\series bold +files.xml: +\series default + Paket içerisinde bulunan dosyaların bir listesi +\layout Itemize + + +\series bold +Ek dosyalar: +\series default + CSL betikleri ve bunun gibi... + (Barış: Bunları da bir dizin içerisine koymak uygun olabilir) +\layout Itemize + + +\series bold +Install/ dizini: +\series default + Paketin kurulu biçimi. + Paketin sisteme kurulumu bu dizinin belirtilen dizine açılır. +\layout Subsection + +Süreçlerin Tarifi +\layout Standard + +Süreç tariri paket sisteminin en temel görevlerini, tasarımı özetlemek amacı + ile anlatır. +\layout Subsubsection + +Paket Oluşturmak +\layout Standard + + +\begin_inset Graphics + filename images/pisi-gelistirici-small.png + rotateOrigin center + +\end_inset + + +\layout Standard + +Bir geliştiricinin paket oluşturmak için izleyeceği adımlar şöyledir; +\layout Itemize + + +\series bold +Geliştirici Grafik Arayüzü +\series default + ya da konsol araçları yardımı ile PSPEC dosyası yukarıda anlatılan yapıya + uygun olarak oluşturulur. + Gerekli olacak yamalar ve dosyalar yukarıda tarif edildiği gibi files/ + dizinine yerleştirilir. +\layout Itemize + +Oluşturulan PSPEC dosyası, hazırlanan paketin derlenebilmesi için PİSİ tarafında +n işlenir. + Eğer gerekli paketler sistemde mevcut değil ise bu paketler PİSİ tarafından + sisteme kurularak, sistem derleme işlemine hazır hale getirilir. + +\emph on +(bunun için kullanıcıdan bir onay gerekiyor mu? Evet?) +\layout Itemize + +Oluşturulan PSPEC dosyasının Global bölümündeki bilgiler işlenerek kaynak + kod sisteme alınır ve doğruluğu kontrol edilir. + Gerekli dosya ve yamalar yukarıda anlatılan biçime uygun bir şekilde PISI +\series bold + +\series default +tarafından açılır ve gerekli yamalar koda uygulanır. + +\emph on +(Adam kaynağın hash'ini kendisi çıkarmayacak sanırım. + Doğruluğunu burada kontrol etmek mantıklı değil gibi?) +\layout Itemize + + +\series bold +PSPEC +\series default +dosyasının +\series bold +Actions +\series default + bölümündeki +\emph on + +\emph default +betikler sıra ile +\series bold +Pisi +\series default + tarafından işletilerek kaynak koddan ikili veri oluşturulur. +\layout Itemize + +Geliştirici (tercihen grafik arayüz yardımı ile) derleme sonrası oluşturulan + dosyaları, PSPEC dosyasında tanımlanan Package bölümlerine göre sınıflandırır. + Oluşturulacak her paket için files.xml dosyası yaratılır. +\layout Itemize + +PİSİ, PSPEC ve files.xml dosyalarını işleyerek paketi veya paketleri oluşturur. +\layout Itemize + +Geliştirici oluşturduğu paketleri sisteminde test eder. +\layout Itemize + +Oluşturulan paket oluşturma dosyaları (PSPEC dosyası, files/ dizini ve actions/ + dizini) +\series bold +Merkezi Paket Derleme Çiftliği +\series default + tarafından derlenmek üzere +\series bold +PSPEC +\series default + +\series bold +Dosyalar Deposu +\series default +'na iletilir. +\layout Itemize + +İletilen +\series bold +PSPEC +\series default + dosyası +\series bold +Merkezi Paket Derleme Çiftliği +\series default + tarafından ikili paket veya paketler haline getirilir. +\layout Itemize + +Oluşturulan paket veya paketler +\series bold +Paket Deposu +\series default +'na yerleştirilir. +\layout Subsubsection + +Paket Kurmak +\layout Standard + + +\begin_inset Graphics + filename images/pisi-istemci-small.png + rotateOrigin center + +\end_inset + + +\layout Standard + +Bir istemcinin sisteme paket kurmak için izleyeceği yol şöyledir; +\layout Itemize + +Sistemdeki ilgili uygulamalardan biri PİSİ'ye paket kurması için istekte + bulunur. +\layout Itemize + +PİSİ, kendi yapılandırma dosyasını işleyerek, kendi yapılandırma dosyasının + içindeki bilgilerin ışığında +\series bold +Paket Deposu +\series default +ndan deponun durumu ile ilgili bilgileri ( +\series bold +ChangeSet +\series default +ler ve kullanıcı yeni bir depo kullanmaya başladıysa +\series bold + pisi.index +\series default +) alır. + +\layout Itemize + + +\series bold +Depo +\series default +dan aldığı bilgileri +\series bold +Depo Veritaban +\series default +ına yerleştirir. +\layout Itemize + +PİSİ istenen paketin kurulması için gerekli olan bilgileri, ihtiyaç duyulan + paketleri belirler. + Gerekli olan paketleri +\series bold +Paket Deposu +\series default +ndan çekerek sisteme kurar. + Eğer çakışan paketler var ise bunları çözer. +\layout Itemize + +PİSİ Kurulacak paketi +\series bold +Paket Deposu +\series default +ndan çeker ve çektiği paketin doğruluğunu kontrol ederek sisteme kurar. + Kurduğu paket ile ilgili bilgileri +\series bold +Kurulu Paket Veritabanı +\series default +'na yerleştirir. +\layout Itemize + +Paketlerin yanında taşıdığı +\series bold +CSL +\series default + betiklerini +\series bold +ÇOMAR +\series default +'a verir. +\layout Subsubsection + +Paket Kaldırmak +\layout Standard + +Bir istemcinin sisteme paket kaldırmak için izleyeceği yol şöyledir; +\layout Itemize + +Sistemdeki ilgili uygulamalardan biri PİSİ'ye paket kaldırmak için istekte + bulunur. +\layout Itemize + +PİSİ, kendi yapılandırma dosyasını işleyerek, +\series bold +Kurulu Paket Veritabanı +\series default +ndan paketin başka bir paket tarafından gereksinim duyulup duyulmadığını + kontrol eder. +\layout Itemize + +PİSİ paketi kaldırır. + +\layout Itemize + +ÇOMAR'a ilgili CSL betiklerini kaldırması için silinen paket ile ilgili + bilgi verir. +\layout Subsubsection + +Bağımlılık çözmek +\layout Standard + +PİSİ içerisinde paket bağımlılığı, doğrudan paket isim ve sürüm numarasına + bağımlılık olarak tanımlanmıştır. + Bu yüzden paket bağımlılığının çözümü depo veritabanından bağımlılığı oluşturan + paketleri iteratif olarak çıkarmak ile sınırlıdır. +\layout Standard + +Paketler için tanımlanan bir diğer bağımlılık tipi ise COMAR OM (Object + Model) bacaklarına olan bağımlılıktır. + Bu bağımlılığın çözümü için Kurulu Paketler ve Depo veritabanları sorgulanarak + ilgili OM bacağını sağlayan bir paketin sistemde kurulu durumda olup olmadığı + bilgisi çıkartılır. + Eğer yoksa ilgili OM bacağını sağlayan paketlerin bir listesi sunulur. +\layout Subsection + +Veritabanları +\layout Standard + +İstemci makinadaki paket veritabanı aşağıdaki bölümlere sahip olacaktır. + Veritabanları +\series bold +\emph on +BerkleyDB +\series default +\emph default + veritabanlarıdır. +\layout Itemize + + +\series bold +Kurulu Paketler Veritabanı: +\series default + +\emph on +Paket adı, sürüm numarası, hangi depodan kurulduğu ve dosyalar (files.xml) + +\emph default +bölümlerini içerecektir. +\layout Itemize + + +\series bold +Depo Veritabanları: +\series default + Birden fazla depo veritabanı olabilir. + Her depo için +\series bold +pisi.index +\series default + dosyası içeriği depo veritabanına aktarılacaktır. +\layout Subsubsection + +Kurulu Paketler Veritabanı +\layout Standard + +Will be... +\layout Subsubsection + +Depo Veritabaları +\layout Standard + +Will be... +\layout Subsection + +libpisi +\layout Standard + +Paket veritabanının ana yüklenicisi libpisi kütüphanesi olacaktır. + Kütüphanenin temel görevleri aşağıdaki liste ile özetlenebilir. +\layout Itemize + +Bir paketi sisteme kurma +\layout Itemize + +Sistemden bir paketi kaldırma +\layout Itemize + +Verilen bir PİSİ paketini açma +\layout Itemize + +Verilen bir PİSİ paketi içerisinden yalnızca bir dosyayı/dizini çıkarma + (metadata.xml dosyası veya install/ dizini gibi) +\layout Itemize + +Bağımlılık çözümleme +\layout Itemize + +Depo veritabanını sorgulama +\layout Itemize + +Kurulu paketler veritabanını sorgulama +\layout Itemize + +Verilen bir ikili paketi sorgulama +\layout Itemize + +İkili paketler deposundan bir paketi çekme/alma (fetch). +\layout Itemize + +PSPEC dosyalarını okuma/işleme/oluşturma. +\layout Itemize + +PSPEC dosyasında belirtilen bir uygulama kaynağını çekme/alma (fetch) +\layout Itemize + +Farklı dosya tiplerini (zip, tar, tar.gz, tar.bz2) açma +\layout Itemize + +Action betiklerini çalıştırma +\layout Itemize + +İkili PİSİ paketi oluşturma +\layout Itemize + +Kurulu paketler veritabanını güncelleme (yeni girdi ekleme, girdi silme + veya bir girdiyi güncelleme) +\layout Itemize + +Dosya sistemini paket işlemleri için sorgulama (bir paketin kurulumu için + diskte yeteri kadar boş yer bulunuyor mu?) +\layout Itemize + +Dosya özetlerini (hash) oluşturme ve doğruluklarını kontrol etme. +\layout Itemize + +Paketi imzalama ve imzanın doğruluğunu kontrol etme. +\layout Itemize + +COMAR sistemi ile iletişim kurma (CSL betiklerinin COMAR'a bildirilmesi, + betiklerin COMAR'dan kaldırılması) +\layout Standard + +Bu gerekleri sağlamak için libpisi modülleri aşağıdaki şekilde gruplanmışlardır. +\layout Itemize + +XML +\layout Itemize + +DB +\layout Itemize + +ZIP +\layout Itemize + +Utils +\begin_deeper +\layout Itemize + +unpack (tar, tar.gz, tar.bz2, zip) +\layout Itemize + +md5 +\layout Itemize + +patch +\layout Itemize + +gpg +\layout Itemize + +fileutils (stat, vb. + şeyler için) +\end_deeper +\layout Itemize + +DepSolver (bağımlılık çözümleyici) +\layout Itemize + +Fetcher (curl) +\layout Itemize + +ActionExec (Action betiklerinin çalıştırılması) +\layout Itemize + +COMAR +\layout Itemize + +Package (xml, zip, gpg, md5 modüllerini kullanıyor...) +\layout Subsection + +PİSİ Package Builder (GUI) +\layout Itemize + +PSPEC dosyasını kullanıcının tanımları doğrultusunda oluşturacak +\layout Itemize + +Action betiklerini kullanıcıya yazdıracak +\layout Itemize + +files.xml dosyasını/dosyalarını oluşturacak. +\layout Itemize + +libpisi kullanarak paket oluşturacak. +\layout Section + +Diğer +\layout Standard + +PİSİ C++ ile yazılacak +\layout Standard + +XML işlemleri için xerces-c kütüphanesi kullanılacak. +\layout Standard + +berkleyDB +\layout Standard + +libcurlpp +\the_end diff --git a/spec/pisi-files.dtd b/spec/pisi-files.dtd new file mode 100644 index 00000000..5981e4a2 --- /dev/null +++ b/spec/pisi-files.dtd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/spec/pisi-spec.dtd b/spec/pisi-spec.dtd new file mode 100644 index 00000000..8c10890b --- /dev/null +++ b/spec/pisi-spec.dtd @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/tasma/pisifiles/files.xml b/spec/tasma/pisifiles/files.xml new file mode 100644 index 00000000..b0b7bab7 --- /dev/null +++ b/spec/tasma/pisifiles/files.xml @@ -0,0 +1,21 @@ + + + + + + + + + + bin/tasma + etc/xdg/menus/kde-settings.menu + lib/kde3/kcm_tasmanet* + share/* + + + + + + diff --git a/spec/tasma/tasma.pspec b/spec/tasma/tasma.pspec new file mode 100644 index 00000000..866b89a7 --- /dev/null +++ b/spec/tasma/tasma.pspec @@ -0,0 +1,71 @@ + + + + + + + + tasma + Configuration GUI for Pardus desktop + 0.2 + 1 + http://www.uludag.org.tr/projeler/masaustu/tasma/ + GPL + ftp://ftp.uludag.org.tr/pub/uygulamalar/tasma/0.2/tasma-0.2.tar.gz + + Barış Metin + baris@uludag.org.tr + + + + + + automake + + + + autoconf + + + + libtool + + + + qt-devel + 3.0 + + + + kdelibs-devel + 3.3.2 + + + + + kdelibs + 3.3.2 + + + + kdebase + 3.3.2 + + + + + + + + setup.sh + + + build.sh + + + install.sh + + + + diff --git a/tree/Makefile b/tree/Makefile new file mode 100644 index 00000000..d94efb98 --- /dev/null +++ b/tree/Makefile @@ -0,0 +1,6 @@ +all: + @g++ main.cpp -o depTree + @echo "Running dummy depTree..." + @./depTree +clean: + rm -f depTree diff --git a/tree/main.cpp b/tree/main.cpp new file mode 100644 index 00000000..fe238bfd --- /dev/null +++ b/tree/main.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +#include "tree.hh" + +using namespace std; + +class Package +{ + public: + Package( string name ) { this->name = name; }; + ~Package() {}; + string getName() { return this->name; }; + private: + string name; +}; + +typedef tree Tree; + +int main(int argc, char *argv[]) +{ + vector dependencies; + + Package *kdebase = new Package("kdebase"); + Package *kdelibs = new Package("kdelibs"); + Package *kdeartwork = new Package("kdeartwork"); + Package *kdepim = new Package("kdepim"); + Package *glibc = new Package("glibc"); + Package *gcc = new Package("gcc"); + Package *xorg = new Package("xorg-x11"); + + Tree depTree; + Tree::iterator top, element; + + top = depTree.begin(); + + /* + * kde_ + * |_kdebase_ + * | |_kdelibs + * | |_kdeartwork_ + * | | + * | |_xorg-x11_ + * | |_glibc + * | |_gcc + * | + * |_kdepim_ + * |_xorg-x11_ + * |_glibc + * |_gcc + */ + + element = depTree.insert( top, *kdebase ); + depTree.append_child( element, *kdelibs ); + element = depTree.append_child( element, *kdeartwork ); + element = depTree.append_child( element, *xorg ); + depTree.append_child( element, *glibc ); + depTree.append_child( element, *gcc ); + element = depTree.insert( top, *kdepim ); + element = depTree.append_child( element, *xorg ); + depTree.append_child( element, *glibc ); + depTree.append_child( element, *gcc ); + + cout << "...Tracked Dependencies..." << endl; + + Tree::post_order_iterator sib_post = depTree.begin_post(); + while( sib_post != depTree.end_post() ) + { + vector::iterator p = find( dependencies.begin(), dependencies.end(), sib_post->getName() ); + + if( p == dependencies.end() ) + dependencies.push_back( sib_post->getName() ); + + ++sib_post; + } + + for( int i = 0; i < dependencies.size(); i++ ) + cout << dependencies[i] << endl; + + return 0; +} diff --git a/tree/tree.hh b/tree/tree.hh new file mode 100644 index 00000000..0d139204 --- /dev/null +++ b/tree/tree.hh @@ -0,0 +1,2029 @@ +/* + + $Id: tree.hh,v 1.117 2004/11/07 18:23:41 kp229 Exp $ + + STL-like templated tree class. + Copyright (C) 2001 Kasper Peeters + + See + + http://www.damtp.cam.ac.uk/user/kp229/tree/ + + for more information and documentation. See the Changelog file for + other credits. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + TODO: - 'Move' members are long overdue; will hopefully be incorporated in the + next release. + - Fixed depth iterators do not iterate over the entire range if there + are 'holes' in the tree. + - If a range uses const iter_base& as end iterator, things will + inevitably go wrong, because upcast from iter_base to a non-sibling_iter + is incorrect. This upcast should be removed (and then all illegal uses + as previously in 'equal' will be flagged by the compiler). This requires + new copy constructors though. + - There's a bug in replace(sibling_iterator, ...) when the ranges + sit next to each other. Turned up in append_child(iter,iter) + but has been avoided now. + - "std::operator<" does not work correctly on our iterators, and for some + reason a globally defined template operator< did not get picked up. + Using a comparison class now, but this should be investigated. +*/ + +#ifndef tree_hh_ +#define tree_hh_ + +#include +#include +#include +#include +#include + +// HP-style construct/destroy have gone from the standard, +// so here is a copy. + +namespace kp { + +template +void constructor(T1* p, T2& val) + { + new ((void *) p) T1(val); + } + +template +void constructor(T1* p) + { + new ((void *) p) T1; + } + +template +void destructor(T1* p) + { + p->~T1(); + } + +}; + +template +class tree_node_ { // size: 5*4=20 bytes (on 32 bit arch), can be reduced by 8. + public: + tree_node_ *parent; + tree_node_ *first_child, *last_child; + tree_node_ *prev_sibling, *next_sibling; + T data; +}; + +template > > +class tree { + protected: + typedef tree_node_ tree_node; + public: + typedef T value_type; + + class iterator_base; + class pre_order_iterator; + class post_order_iterator; + class sibling_iterator; + + tree(); + tree(const T&); + tree(const iterator_base&); + tree(const tree&); + ~tree(); + void operator=(const tree&); + +#ifdef __SGI_STL_PORT + class iterator_base : public stlport::bidirectional_iterator { +#else + class iterator_base { +#endif + public: + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + iterator_base(); + iterator_base(tree_node *); + + T& operator*() const; + T* operator->() const; + + void skip_children(); // do not iterate over children of this node + unsigned int number_of_children() const; + + sibling_iterator begin() const; + sibling_iterator end() const; + + tree_node *node; + protected: + bool skip_current_children_; + }; + + class pre_order_iterator : public iterator_base { + public: + pre_order_iterator(); + pre_order_iterator(tree_node *); + pre_order_iterator(const iterator_base&); + pre_order_iterator(const sibling_iterator&); + + bool operator==(const pre_order_iterator&) const; + bool operator!=(const pre_order_iterator&) const; + pre_order_iterator& operator++(); + pre_order_iterator& operator--(); + pre_order_iterator operator++(int); + pre_order_iterator operator--(int); + pre_order_iterator& operator+=(unsigned int); + pre_order_iterator& operator-=(unsigned int); + }; + + class post_order_iterator : public iterator_base { + public: + post_order_iterator(); + post_order_iterator(tree_node *); + post_order_iterator(const iterator_base&); + post_order_iterator(const sibling_iterator&); + + bool operator==(const post_order_iterator&) const; + bool operator!=(const post_order_iterator&) const; + post_order_iterator& operator++(); + post_order_iterator& operator--(); + post_order_iterator operator++(int); + post_order_iterator operator--(int); + post_order_iterator& operator+=(unsigned int); + post_order_iterator& operator-=(unsigned int); + + void descend_all(); + }; + + typedef pre_order_iterator iterator; + + class fixed_depth_iterator : public iterator_base { + public: + fixed_depth_iterator(); + fixed_depth_iterator(tree_node *); + fixed_depth_iterator(const iterator_base&); + fixed_depth_iterator(const sibling_iterator&); + fixed_depth_iterator(const fixed_depth_iterator&); + + bool operator==(const fixed_depth_iterator&) const; + bool operator!=(const fixed_depth_iterator&) const; + fixed_depth_iterator& operator++(); + fixed_depth_iterator& operator--(); + fixed_depth_iterator operator++(int); + fixed_depth_iterator operator--(int); + fixed_depth_iterator& operator+=(unsigned int); + fixed_depth_iterator& operator-=(unsigned int); + + tree_node *first_parent_; + private: + void set_first_parent_(); + void find_leftmost_parent_(); + }; + + class sibling_iterator : public iterator_base { + public: + sibling_iterator(); + sibling_iterator(tree_node *); + sibling_iterator(const sibling_iterator&); + sibling_iterator(const iterator_base&); + + bool operator==(const sibling_iterator&) const; + bool operator!=(const sibling_iterator&) const; + sibling_iterator& operator++(); + sibling_iterator& operator--(); + sibling_iterator operator++(int); + sibling_iterator operator--(int); + sibling_iterator& operator+=(unsigned int); + sibling_iterator& operator-=(unsigned int); + + tree_node *range_first() const; + tree_node *range_last() const; + tree_node *parent_; + private: + void set_parent_(); + }; + + // begin/end of tree + inline pre_order_iterator begin() const; + inline pre_order_iterator end() const; + post_order_iterator begin_post() const; + post_order_iterator end_post() const; + fixed_depth_iterator begin_fixed(const iterator_base&, unsigned int) const; + fixed_depth_iterator end_fixed(const iterator_base&, unsigned int) const; + // begin/end of children of node + sibling_iterator begin(const iterator_base&) const; + sibling_iterator end(const iterator_base&) const; + + template iter parent(iter) const; + template iter previous_sibling(iter) const; + template iter next_sibling(iter) const; + template iter next_at_same_depth(iter) const; + + void clear(); + // erase element at position pointed to by iterator, return incremented iterator + template iter erase(iter); + // erase all children of the node pointed to by iterator + void erase_children(const iterator_base&); + + // insert node as last child of node pointed to by position (first one inserts empty node) + template iter append_child(iter position); + template iter append_child(iter position, const T& x); + // the following two append nodes plus their children + template iter append_child(iter position, iter other_position); + template iter append_children(iter position, sibling_iterator from, sibling_iterator to); + + // short-hand to insert topmost node in otherwise empty tree + pre_order_iterator set_head(const T& x); + // insert node as previous sibling of node pointed to by position + template iter insert(iter position, const T& x); + // specialisation: insert node as previous sibling of node pointed to by position + //pre_order_iterator insert(sibling_iterator position, const T& x); + sibling_iterator insert(sibling_iterator position, const T& x); + // insert node (with children) pointed to by subtree as previous sibling of node pointed to by position + template iter insert_subtree(iter position, const iterator_base& subtree); + // insert node as next sibling of node pointed to by position + template iter insert_after(iter position, const T& x); + + // replace node at 'position' with other node (keeping same children); 'position' becomes invalid. + template iter replace(iter position, const T& x); + // replace node at 'position' with subtree starting at 'from' (do not erase subtree at 'from'); see above. + template iter replace(iter position, const iterator_base& from); + // replace string of siblings (plus their children) with copy of a new string (with children); see above + sibling_iterator replace(sibling_iterator orig_begin, sibling_iterator orig_end, + sibling_iterator new_begin, sibling_iterator new_end); + + // move all children of node at 'position' to be siblings, returns position + template iter flatten(iter position); + // move nodes in range to be children of 'position' + template iter reparent(iter position, sibling_iterator begin, sibling_iterator end); + // ditto, the range being all children of the 'from' node + template iter reparent(iter position, iter from); + + // new style move members, moving nodes plus children to a different location + template iter move_after(iter target, iter source); + template iter move_before(iter target, iter source); + template iter move_ontop(iter target, iter source); + + // merge with other tree, creating new branches and leaves only if they are not already present + void merge(sibling_iterator, sibling_iterator, sibling_iterator, sibling_iterator, + bool duplicate_leaves=false); + // sort (std::sort only moves values of nodes, this one moves children as well) + void sort(sibling_iterator from, sibling_iterator to, bool deep=false); + template + void sort(sibling_iterator from, sibling_iterator to, StrictWeakOrdering comp, bool deep=false); + // compare two ranges of nodes (compares nodes as well as tree structure) + template + bool equal(const iter& one, const iter& two, const iter& three) const; + template + bool equal(const iter& one, const iter& two, const iter& three, BinaryPredicate) const; + template + bool equal_subtree(const iter& one, const iter& two) const; + template + bool equal_subtree(const iter& one, const iter& two, BinaryPredicate) const; + // extract a new tree formed by the range of siblings plus all their children + tree subtree(sibling_iterator from, sibling_iterator to) const; + void subtree(tree&, sibling_iterator from, sibling_iterator to) const; + // exchange the node (plus subtree) with its sibling node (do nothing if no sibling present) + void swap(sibling_iterator it); + // find a subtree +// template +// iterator find_subtree(sibling_iterator, sibling_iterator, iterator from, iterator to, BinaryPredicate) const; + + // count the total number of nodes + int size() const; + // check if tree is empty + bool empty() const; + // compute the depth to the root + int depth(const iterator_base&) const; + // count the number of children of node at position + unsigned int number_of_children(const iterator_base&) const; + // count the number of 'next' siblings of node at iterator + unsigned int number_of_siblings(const iterator_base&) const; + // determine whether node at position is in the subtrees with root in the range + bool is_in_subtree(const iterator_base& position, const iterator_base& begin, + const iterator_base& end) const; + // determine whether the iterator is an 'end' iterator and thus not actually + // pointing to a node + bool is_valid(const iterator_base&) const; + + // determine the index of a node in the range of siblings to which it belongs. + unsigned int index(sibling_iterator it) const; + // inverse of 'index': return the n-th child of the node at position + sibling_iterator child(const iterator_base& position, unsigned int) const; + + class iterator_base_less { + public: + bool operator()(const typename tree::iterator_base& one, + const typename tree::iterator_base& two) const + { + return one.node < two.node; + } + }; + tree_node *head, *feet; // head/feet are always dummy; if an iterator points to them it is invalid + private: + tree_node_allocator alloc_; + void head_initialise_(); + void copy_(const tree& other); + template + class compare_nodes { + public: + bool operator()(const tree_node *a, const tree_node *b) + { + static StrictWeakOrdering comp; + return comp(a->data, b->data); + } + }; +}; + +//template +//class iterator_base_less { +// public: +// bool operator()(const typename tree::iterator_base& one, +// const typename tree::iterator_base& two) const +// { +// txtout << "operatorclass<" << one.node < two.node << std::endl; +// return one.node < two.node; +// } +//}; + +//template +//bool operator<(const typename tree::iterator& one, +// const typename tree::iterator& two) +// { +// txtout << "operator< " << one.node < two.node << std::endl; +// if(one.node < two.node) return true; +// return false; +// } + +template +bool operator>(const typename tree::iterator_base& one, + const typename tree::iterator_base& two) + { + if(one.node > two.node) return true; + return false; + } + + + +// Tree + +template +tree::tree() + { + head_initialise_(); + } + +template +tree::tree(const T& x) + { + head_initialise_(); + set_head(x); + } + +template +tree::tree(const iterator_base& other) + { + head_initialise_(); + set_head((*other)); + replace(begin(), other); + } + +template +tree::~tree() + { + clear(); + alloc_.deallocate(head,1); + alloc_.deallocate(feet,1); + } + +template +void tree::head_initialise_() + { + head = alloc_.allocate(1,0); // MSVC does not have default second argument + feet = alloc_.allocate(1,0); + + head->parent=0; + head->first_child=0; + head->last_child=0; + head->prev_sibling=0; //head; + head->next_sibling=feet; //head; + + feet->parent=0; + feet->first_child=0; + feet->last_child=0; + feet->prev_sibling=head; + feet->next_sibling=0; + } + +template +void tree::operator=(const tree& other) + { + copy_(other); + } + +template +tree::tree(const tree& other) + { + head_initialise_(); + copy_(other); + } + +template +void tree::copy_(const tree& other) + { + clear(); + pre_order_iterator it=other.begin(), to=begin(); + while(it!=other.end()) { + to=insert(to, (*it)); + it.skip_children(); + ++it; + } + to=begin(); + it=other.begin(); + while(it!=other.end()) { + to=replace(to, it); + to.skip_children(); + it.skip_children(); + ++to; + ++it; + } + } + +template +void tree::clear() + { + if(head) + while(head->next_sibling!=feet) + erase(pre_order_iterator(head->next_sibling)); + } + +template +void tree::erase_children(const iterator_base& it) + { + tree_node *cur=it.node->first_child; + tree_node *prev=0; + + while(cur!=0) { + prev=cur; + cur=cur->next_sibling; + erase_children(pre_order_iterator(prev)); + kp::destructor(&prev->data); + alloc_.deallocate(prev,1); + } + it.node->first_child=0; + it.node->last_child=0; + } + +template +template +iter tree::erase(iter it) + { + tree_node *cur=it.node; + assert(cur!=head); + iter ret=it; + ret.skip_children(); + ++ret; + erase_children(it); + if(cur->prev_sibling==0) { + cur->parent->first_child=cur->next_sibling; + } + else { + cur->prev_sibling->next_sibling=cur->next_sibling; + } + if(cur->next_sibling==0) { + cur->parent->last_child=cur->prev_sibling; + } + else { + cur->next_sibling->prev_sibling=cur->prev_sibling; + } + + kp::destructor(&cur->data); + alloc_.deallocate(cur,1); + return ret; + } + +template +typename tree::pre_order_iterator tree::begin() const + { + return pre_order_iterator(head->next_sibling); + } + +template +typename tree::pre_order_iterator tree::end() const + { + return pre_order_iterator(feet); + } + +template +typename tree::post_order_iterator tree::begin_post() const + { + tree_node *tmp=head->next_sibling; + if(tmp!=feet) { + while(tmp->first_child) + tmp=tmp->first_child; + } + return post_order_iterator(tmp); + } + +template +typename tree::post_order_iterator tree::end_post() const + { + return post_order_iterator(feet); + } + +template +typename tree::fixed_depth_iterator tree::begin_fixed(const iterator_base& pos, unsigned int dp) const + { + tree_node *tmp=pos.node; + unsigned int curdepth=0; + while(curdepthfirst_child==0) { + tmp=tmp->next_sibling; + if(tmp==0) + throw std::range_error("tree: begin_fixed out of range"); + } + tmp=tmp->first_child; + ++curdepth; + } + return tmp; + } + +template +typename tree::fixed_depth_iterator tree::end_fixed(const iterator_base& pos, unsigned int dp) const + { + assert(1==0); // FIXME: not correct yet + tree_node *tmp=pos.node; + unsigned int curdepth=1; + while(curdepthfirst_child==0) { + tmp=tmp->next_sibling; + if(tmp==0) + throw std::range_error("tree: end_fixed out of range"); + } + tmp=tmp->first_child; + ++curdepth; + } + return tmp; + } + +template +typename tree::sibling_iterator tree::begin(const iterator_base& pos) const + { + if(pos.node->first_child==0) { + return end(pos); + } + return pos.node->first_child; + } + +template +typename tree::sibling_iterator tree::end(const iterator_base& pos) const + { + sibling_iterator ret(0); + ret.parent_=pos.node; + return ret; + } + +template +template +iter tree::parent(iter position) const + { + assert(position.node!=0); + return iter(position.node->parent); + } + +template +template +iter tree::previous_sibling(iter position) const + { + assert(position.node!=0); + iter ret(position); + ret.node=position.node->prev_sibling; + return ret; + } + +template +template +iter tree::next_sibling(iter position) const + { + assert(position.node!=0); + iter ret(position); + ret.node=position.node->next_sibling; + return ret; + } + +template +template +iter tree::next_at_same_depth(iter position) const + { + assert(position.node!=0); + iter ret(position); + + if(position.node->next_sibling) { + ret.node=position.node->next_sibling; + } + else { + int relative_depth=0; + upper: + do { + ret.node=ret.node->parent; + if(ret.node==0) return ret; + --relative_depth; + } while(ret.node->next_sibling==0); + lower: + ret.node=ret.node->next_sibling; + while(ret.node->first_child==0) { + if(ret.node->next_sibling==0) + goto upper; + ret.node=ret.node->next_sibling; + if(ret.node==0) return ret; + } + while(relative_depth<0 && ret.node->first_child!=0) { + ret.node=ret.node->first_child; + ++relative_depth; + } + if(relative_depth<0) { + if(ret.node->next_sibling==0) goto upper; + else goto lower; + } + } + return ret; + } + +template +template +iter tree::append_child(iter position) + { + assert(position.node!=head); + + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->last_child!=0) { + position.node->last_child->next_sibling=tmp; + } + else { + position.node->first_child=tmp; + } + tmp->prev_sibling=position.node->last_child; + position.node->last_child=tmp; + tmp->next_sibling=0; + return tmp; + } + +template +template +iter tree::append_child(iter position, const T& x) + { + // If your program fails here you probably used 'append_child' to add the top + // node to an empty tree. From version 1.45 the top element should be added + // using 'insert'. See the documentation for further information, and sorry about + // the API change. + assert(position.node!=head); + + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node; + if(position.node->last_child!=0) { + position.node->last_child->next_sibling=tmp; + } + else { + position.node->first_child=tmp; + } + tmp->prev_sibling=position.node->last_child; + position.node->last_child=tmp; + tmp->next_sibling=0; + return tmp; + } + +template +template +iter tree::append_child(iter position, iter other) + { + assert(position.node!=head); + + sibling_iterator aargh=append_child(position, value_type()); + return replace(aargh, other); + } + +template +template +iter tree::append_children(iter position, sibling_iterator from, sibling_iterator to) + { + iter ret=from; + + while(from!=to) { + insert_subtree(position.end(), from); + ++from; + } + return ret; + } + +template +typename tree::pre_order_iterator tree::set_head(const T& x) + { + assert(head->next_sibling==feet); + return insert(iterator(feet), x); + } + +template +template +iter tree::insert(iter position, const T& x) + { + if(position.node==0) { + position.node=feet; // Backward compatibility: when calling insert on a null node, + // insert before the feet. + } + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->next_sibling=position.node; + tmp->prev_sibling=position.node->prev_sibling; + position.node->prev_sibling=tmp; + + if(tmp->prev_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->first_child=tmp; + } + else + tmp->prev_sibling->next_sibling=tmp; + return tmp; + } + +template +typename tree::sibling_iterator tree::insert(sibling_iterator position, const T& x) + { + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->next_sibling=position.node; + if(position.node==0) { // iterator points to end of a subtree + tmp->parent=position.parent_; + tmp->prev_sibling=position.range_last(); + tmp->parent->last_child=tmp; + } + else { + tmp->parent=position.node->parent; + tmp->prev_sibling=position.node->prev_sibling; + position.node->prev_sibling=tmp; + } + + if(tmp->prev_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->first_child=tmp; + } + else + tmp->prev_sibling->next_sibling=tmp; + return tmp; + } + +template +template +iter tree::insert_after(iter position, const T& x) + { + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, x); + tmp->first_child=0; + tmp->last_child=0; + + tmp->parent=position.node->parent; + tmp->prev_sibling=position.node; + tmp->next_sibling=position.node->next_sibling; + position.node->next_sibling=tmp; + + if(tmp->next_sibling==0) { + if(tmp->parent) // when inserting nodes at the head, there is no parent + tmp->parent->last_child=tmp; + } + else { + tmp->next_sibling->prev_sibling=tmp; + } + return tmp; + } + +template +template +iter tree::insert_subtree(iter position, const iterator_base& subtree) + { + // insert dummy + iter it=insert(position, value_type()); + // replace dummy with subtree + return replace(it, subtree); + } + +// template +// template +// iter tree::insert_subtree(sibling_iterator position, iter subtree) +// { +// // insert dummy +// iter it(insert(position, value_type())); +// // replace dummy with subtree +// return replace(it, subtree); +// } + +template +template +iter tree::replace(iter position, const T& x) + { + kp::destructor(&position.node->data); + kp::constructor(&position.node->data, x); + return position; + } + +template +template +iter tree::replace(iter position, const iterator_base& from) + { + assert(position.node!=head); + tree_node *current_from=from.node; + tree_node *start_from=from.node; + tree_node *current_to =position.node; + + // replace the node at position with head of the replacement tree at from + erase_children(position); + tree_node* tmp = alloc_.allocate(1,0); + kp::constructor(&tmp->data, (*from)); + tmp->first_child=0; + tmp->last_child=0; + if(current_to->prev_sibling==0) { + current_to->parent->first_child=tmp; + } + else { + current_to->prev_sibling->next_sibling=tmp; + } + tmp->prev_sibling=current_to->prev_sibling; + if(current_to->next_sibling==0) { + current_to->parent->last_child=tmp; + } + else { + current_to->next_sibling->prev_sibling=tmp; + } + tmp->next_sibling=current_to->next_sibling; + tmp->parent=current_to->parent; + kp::destructor(¤t_to->data); + alloc_.deallocate(current_to,1); + current_to=tmp; + + // only at this stage can we fix 'last' + tree_node *last=from.node->next_sibling; + + pre_order_iterator toit=tmp; + // copy all children + do { + assert(current_from!=0); + if(current_from->first_child != 0) { + current_from=current_from->first_child; + toit=append_child(toit, current_from->data); + } + else { + while(current_from->next_sibling==0 && current_from!=start_from) { + current_from=current_from->parent; + toit=parent(toit); + assert(current_from!=0); + } + current_from=current_from->next_sibling; + if(current_from!=last) { + toit=append_child(parent(toit), current_from->data); + } + } + } while(current_from!=last); + + return current_to; + } + +template +typename tree::sibling_iterator tree::replace( + sibling_iterator orig_begin, + sibling_iterator orig_end, + sibling_iterator new_begin, + sibling_iterator new_end) + { + tree_node *orig_first=orig_begin.node; + tree_node *new_first=new_begin.node; + tree_node *orig_last=orig_first; + while((++orig_begin)!=orig_end) + orig_last=orig_last->next_sibling; + tree_node *new_last=new_first; + while((++new_begin)!=new_end) + new_last=new_last->next_sibling; + + // insert all siblings in new_first..new_last before orig_first + bool first=true; + pre_order_iterator ret; + while(1==1) { + pre_order_iterator tt=insert_subtree(pre_order_iterator(orig_first), pre_order_iterator(new_first)); + if(first) { + ret=tt; + first=false; + } + if(new_first==new_last) + break; + new_first=new_first->next_sibling; + } + + // erase old range of siblings + bool last=false; + tree_node *next=orig_first; + while(1==1) { + if(next==orig_last) + last=true; + next=next->next_sibling; + erase((pre_order_iterator)orig_first); + if(last) + break; + orig_first=next; + } + return ret; + } + +template +template +iter tree::flatten(iter position) + { + if(position.node->first_child==0) + return position; + + tree_node *tmp=position.node->first_child; + while(tmp) { + tmp->parent=position.node->parent; + tmp=tmp->next_sibling; + } + if(position.node->next_sibling) { + position.node->last_child->next_sibling=position.node->next_sibling; + position.node->next_sibling->prev_sibling=position.node->last_child; + } + else { + position.node->parent->last_child=position.node->last_child; + } + position.node->next_sibling=position.node->first_child; + position.node->next_sibling->prev_sibling=position.node; + position.node->first_child=0; + position.node->last_child=0; + + return position; + } + + +template +template +iter tree::reparent(iter position, sibling_iterator begin, sibling_iterator end) + { + tree_node *first=begin.node; + tree_node *last=first; + if(begin==end) return begin; + // determine last node + while((++begin)!=end) { + last=last->next_sibling; + } + // move subtree + if(first->prev_sibling==0) { + first->parent->first_child=last->next_sibling; + } + else { + first->prev_sibling->next_sibling=last->next_sibling; + } + if(last->next_sibling==0) { + last->parent->last_child=first->prev_sibling; + } + else { + last->next_sibling->prev_sibling=first->prev_sibling; + } + if(position.node->first_child==0) { + position.node->first_child=first; + position.node->last_child=last; + first->prev_sibling=0; + } + else { + position.node->last_child->next_sibling=first; + first->prev_sibling=position.node->last_child; + position.node->last_child=last; + } + last->next_sibling=0; + + tree_node *pos=first; + while(1==1) { + pos->parent=position.node; + if(pos==last) break; + pos=pos->next_sibling; + } + + return first; + } + +template +template iter tree::reparent(iter position, iter from) + { + if(from.node->first_child==0) return position; + return reparent(position, from.node->first_child, end(from)); + } + +template +template iter tree::move_before(iter target, iter source) + { + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return source; + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(dst->prev_sibling!=0) dst->prev_sibling->next_sibling=src; + else dst->parent->first_child=src; + src->prev_sibling=dst->prev_sibling; + dst->prev_sibling=src; + src->next_sibling=dst; + src->parent=dst->parent; + return src; + } + +template +template iter tree::move_ontop(iter target, iter source) + { + tree_node *dst=target.node; + tree_node *src=source.node; + assert(dst); + assert(src); + + if(dst==src) return source; + + // remember connection points + tree_node *b_prev_sibling=dst->prev_sibling; + tree_node *b_next_sibling=dst->next_sibling; + tree_node *b_parent=dst->parent; + + // remove target + erase(target); + + // take src out of the tree + if(src->prev_sibling!=0) src->prev_sibling->next_sibling=src->next_sibling; + else src->parent->first_child=src->next_sibling; + if(src->next_sibling!=0) src->next_sibling->prev_sibling=src->prev_sibling; + else src->parent->last_child=src->prev_sibling; + + // connect it to the new point + if(b_prev_sibling!=0) b_prev_sibling->next_sibling=src; + else b_parent->first_child=src; + if(b_next_sibling!=0) b_next_sibling->prev_sibling=src; + else b_parent->last_child=src; + src->prev_sibling=b_prev_sibling; + src->next_sibling=b_next_sibling; + src->parent=b_parent; + return src; + } + +template +void tree::merge(sibling_iterator to1, sibling_iterator to2, + sibling_iterator from1, sibling_iterator from2, + bool duplicate_leaves) + { + sibling_iterator fnd; + while(from1!=from2) { + if((fnd=std::find(to1, to2, (*from1))) != to2) { // element found + if(from1.begin()==from1.end()) { // full depth reached + if(duplicate_leaves) + append_child(parent(to1), (*from1)); + } + else { // descend further + merge(fnd.begin(), fnd.end(), from1.begin(), from1.end(), duplicate_leaves); + } + } + else { // element missing + insert_subtree(to2, from1); + } + ++from1; + } + } + + +template +void tree::sort(sibling_iterator from, sibling_iterator to, bool deep) + { + std::less comp; + sort(from, to, comp, deep); + } + +template +template +void tree::sort(sibling_iterator from, sibling_iterator to, + StrictWeakOrdering comp, bool deep) + { + if(from==to) return; + // make list of sorted nodes + // CHECK: if multiset stores equivalent nodes in the order in which they + // are inserted, then this routine should be called 'stable_sort'. + std::multiset > nodes; + sibling_iterator it=from, it2=to; + while(it != to) { + nodes.insert(it.node); + ++it; + } + // reassemble + --it2; + + // prev and next are the nodes before and after the sorted range + tree_node *prev=from.node->prev_sibling; + tree_node *next=it2.node->next_sibling; + typename std::multiset >::iterator nit=nodes.begin(), eit=nodes.end(); + if(prev==0) { + if((*nit)->parent!=0) // to catch "sorting the head" situations, when there is no parent + (*nit)->parent->first_child=(*nit); + } + else prev->next_sibling=(*nit); + + --eit; + while(nit!=eit) { + (*nit)->prev_sibling=prev; + if(prev) + prev->next_sibling=(*nit); + prev=(*nit); + ++nit; + } + // prev now points to the last-but-one node in the sorted range + if(prev) + prev->next_sibling=(*eit); + + // eit points to the last node in the sorted range. + (*eit)->next_sibling=next; + (*eit)->prev_sibling=prev; // missed in the loop above + if(next==0) { + if((*eit)->parent!=0) // to catch "sorting the head" situations, when there is no parent + (*eit)->parent->last_child=(*eit); + } + else next->prev_sibling=(*eit); + + if(deep) { // sort the children of each node too + sibling_iterator bcs(*nodes.begin()); + sibling_iterator ecs(*eit); + ++ecs; + while(bcs!=ecs) { + sort(begin(bcs), end(bcs), comp, deep); + ++bcs; + } + } + } + +template +template +bool tree::equal(const iter& one_, const iter& two, const iter& three_) const + { + std::equal_to comp; + return equal(one_, two, three_, comp); + } + +template +template +bool tree::equal_subtree(const iter& one_, const iter& two_) const + { + std::equal_to comp; + return equal_subtree(one_, two_, comp); + } + +template +template +bool tree::equal(const iter& one_, const iter& two, const iter& three_, BinaryPredicate fun) const + { + pre_order_iterator one(one_), three(three_); + +// if(one==two && is_valid(three) && three.number_of_children()!=0) +// return false; + while(one!=two && is_valid(three)) { + if(!fun(*one,*three)) + return false; + if(one.number_of_children()!=three.number_of_children()) + return false; + ++one; + ++three; + } + return true; + } + +template +template +bool tree::equal_subtree(const iter& one_, const iter& two_, BinaryPredicate fun) const + { + pre_order_iterator one(one_), two(two_); + + if(!fun(*one,*two)) return false; + if(number_of_children(one)!=number_of_children(two)) return false; + return equal(begin(one),end(one),begin(two),fun); + } + +template +tree tree::subtree(sibling_iterator from, sibling_iterator to) const + { + tree tmp; + tmp.set_head(value_type()); + tmp.replace(tmp.begin(), tmp.end(), from, to); + return tmp; + } + +template +void tree::subtree(tree& tmp, sibling_iterator from, sibling_iterator to) const + { + tmp.set_head(value_type()); + tmp.replace(tmp.begin(), tmp.end(), from, to); + } + +template +int tree::size() const + { + int i=0; + pre_order_iterator it=begin(), eit=end(); + while(it!=eit) { + ++i; + ++it; + } + return i; + } + +template +bool tree::empty() const + { + pre_order_iterator it=begin(), eit=end(); + return (it==eit); + } + +template +int tree::depth(const iterator_base& it) const + { + tree_node* pos=it.node; + assert(pos!=0); + int ret=0; + while(pos->parent!=0) { + pos=pos->parent; + ++ret; + } + return ret; + } + +template +unsigned int tree::number_of_children(const iterator_base& it) const + { + tree_node *pos=it.node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; +// while(pos!=it.node->last_child) { +// ++ret; +// pos=pos->next_sibling; +// } + while((pos=pos->next_sibling)) + ++ret; + return ret; + } + +template +unsigned int tree::number_of_siblings(const iterator_base& it) const + { + tree_node *pos=it.node; + unsigned int ret=0; + while(pos->next_sibling && + pos->next_sibling!=head && + pos->next_sibling!=feet) { + ++ret; + pos=pos->next_sibling; + } + return ret; + } + +template +void tree::swap(sibling_iterator it) + { + tree_node *nxt=it.node->next_sibling; + if(nxt) { + if(it.node->prev_sibling) + it.node->prev_sibling->next_sibling=nxt; + else + it.node->parent->first_child=nxt; + nxt->prev_sibling=it.node->prev_sibling; + tree_node *nxtnxt=nxt->next_sibling; + if(nxtnxt) + nxtnxt->prev_sibling=it.node; + else + it.node->parent->last_child=it.node; + nxt->next_sibling=it.node; + it.node->prev_sibling=nxt; + it.node->next_sibling=nxtnxt; + } + } + +// template +// tree::iterator tree::find_subtree( +// sibling_iterator subfrom, sibling_iterator subto, iterator from, iterator to, +// BinaryPredicate fun) const +// { +// assert(1==0); // this routine is not finished yet. +// while(from!=to) { +// if(fun(*subfrom, *from)) { +// +// } +// } +// return to; +// } + +template +bool tree::is_in_subtree(const iterator_base& it, const iterator_base& begin, + const iterator_base& end) const + { + // FIXME: this should be optimised. + pre_order_iterator tmp=begin; + while(tmp!=end) { + if(tmp==it) return true; + ++tmp; + } + return false; + } + +template +bool tree::is_valid(const iterator_base& it) const + { + if(it.node==0 || it.node==feet) return false; + else return true; + } + +template +unsigned int tree::index(sibling_iterator it) const + { + unsigned int ind=0; + if(it.node->parent==0) { + while(it.node->prev_sibling!=head) { + it.node=it.node->prev_sibling; + ++ind; + } + } + else { + while(it.node->prev_sibling!=0) { + it.node=it.node->prev_sibling; + ++ind; + } + } + return ind; + } + + +template +typename tree::sibling_iterator tree::child(const iterator_base& it, unsigned int num) const + { + tree_node *tmp=it.node->first_child; + while(num--) { + assert(tmp!=0); + tmp=tmp->next_sibling; + } + return tmp; + } + + + + +// Iterator base + +template +tree::iterator_base::iterator_base() + : node(0), skip_current_children_(false) + { + } + +template +tree::iterator_base::iterator_base(tree_node *tn) + : node(tn), skip_current_children_(false) + { + } + +template +T& tree::iterator_base::operator*() const + { + return node->data; + } + +template +T* tree::iterator_base::operator->() const + { + return &(node->data); + } + +template +bool tree::post_order_iterator::operator!=(const post_order_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::post_order_iterator::operator==(const post_order_iterator& other) const + { + if(other.node==this->node) return true; + else return false; + } + +template +bool tree::pre_order_iterator::operator!=(const pre_order_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::pre_order_iterator::operator==(const pre_order_iterator& other) const + { + if(other.node==this->node) return true; + else return false; + } + +template +bool tree::sibling_iterator::operator!=(const sibling_iterator& other) const + { + if(other.node!=this->node) return true; + else return false; + } + +template +bool tree::sibling_iterator::operator==(const sibling_iterator& other) const + { + if(other.node==this->node) return true; + else return false; + } + +template +typename tree::sibling_iterator tree::iterator_base::begin() const + { + sibling_iterator ret(node->first_child); + ret.parent_=this->node; + return ret; + } + +template +typename tree::sibling_iterator tree::iterator_base::end() const + { + sibling_iterator ret(0); + ret.parent_=node; + return ret; + } + +template +void tree::iterator_base::skip_children() + { + skip_current_children_=true; + } + +template +unsigned int tree::iterator_base::number_of_children() const + { + tree_node *pos=node->first_child; + if(pos==0) return 0; + + unsigned int ret=1; + while(pos!=node->last_child) { + ++ret; + pos=pos->next_sibling; + } + return ret; + } + + + +// Pre-order iterator + +template +tree::pre_order_iterator::pre_order_iterator() + : iterator_base(0) + { + } + +template +tree::pre_order_iterator::pre_order_iterator(tree_node *tn) + : iterator_base(tn) + { + } + +template +tree::pre_order_iterator::pre_order_iterator(const iterator_base &other) + : iterator_base(other.node) + { + } + +template +tree::pre_order_iterator::pre_order_iterator(const sibling_iterator& other) + : iterator_base(other.node) + { + if(this->node==0) { + if(other.range_last()!=0) + this->node=other.range_last(); + else + this->node=other.parent_; + this->skip_children(); + ++(*this); + } + } + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator++() + { + assert(this->node!=0); + if(!this->skip_current_children_ && this->node->first_child != 0) { + this->node=this->node->first_child; + } + else { + this->skip_current_children_=false; + while(this->node->next_sibling==0) { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + this->node=this->node->next_sibling; + } + return *this; + } + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator--() + { + assert(this->node!=0); + if(this->node->prev_sibling) { + this->node=this->node->prev_sibling; + while(this->node->last_child) + this->node=this->node->last_child; + } + else { + this->node=this->node->parent; + if(this->node==0) + return *this; + } + return *this; +} + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator++(int n) + { + pre_order_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::pre_order_iterator tree::pre_order_iterator::operator--(int n) +{ + pre_order_iterator copy = *this; + --(*this); + return copy; +} + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + +template +typename tree::pre_order_iterator& tree::pre_order_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --num; + } + return (*this); + } + + + +// Post-order iterator + +template +tree::post_order_iterator::post_order_iterator() + : iterator_base(0) + { + } + +template +tree::post_order_iterator::post_order_iterator(tree_node *tn) + : iterator_base(tn) + { + } + +template +tree::post_order_iterator::post_order_iterator(const iterator_base &other) + : iterator_base(other.node) + { + } + +template +tree::post_order_iterator::post_order_iterator(const sibling_iterator& other) + : iterator_base(other.node) + { + if(this->node==0) { + if(other.range_last()!=0) + this->node=other.range_last(); + else + this->node=other.parent_; + this->skip_children(); + ++(*this); + } + } + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator++() + { + assert(this->node!=0); + if(this->node->next_sibling==0) + this->node=this->node->parent; + else { + this->node=this->node->next_sibling; + if(this->skip_current_children_) { + this->skip_current_children_=false; + } + else { + while(this->node->first_child) + this->node=this->node->first_child; + } + } + return *this; + } + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator--() + { + assert(this->node!=0); + if(this->skip_current_children_ || this->node->last_child==0) { + this->skip_current_children_=false; + while(this->node->prev_sibling==0) + this->node=this->node->parent; + this->node=this->node->prev_sibling; + } + else { + this->node=this->node->last_child; + } + return *this; +} + +template +typename tree::post_order_iterator tree::post_order_iterator::operator++(int) + { + post_order_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::post_order_iterator tree::post_order_iterator::operator--(int) + { + post_order_iterator copy = *this; + --(*this); + return copy; + } + + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + +template +typename tree::post_order_iterator& tree::post_order_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --num; + } + return (*this); + } + +template +void tree::post_order_iterator::descend_all() + { + assert(this->node!=0); + while(this->node->first_child) + this->node=this->node->first_child; + } + + +// Fixed depth iterator + +template +tree::fixed_depth_iterator::fixed_depth_iterator() + : iterator_base() + { + set_first_parent_(); + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(tree_node *tn) + : iterator_base(tn) + { + set_first_parent_(); + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(const iterator_base& other) + : iterator_base(other.node) + { + set_first_parent_(); + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(const sibling_iterator& other) + : iterator_base(other.node), first_parent_(other.parent_) + { + find_leftmost_parent_(); + } + +template +tree::fixed_depth_iterator::fixed_depth_iterator(const fixed_depth_iterator& other) + : iterator_base(other.node), first_parent_(other.first_parent_) + { + } + +template +void tree::fixed_depth_iterator::set_first_parent_() + { + return; // FIXME: we do not use first_parent_ yet, and it actually needs some serious reworking if + // it is ever to work at the 'head' level. + first_parent_=0; + if(this->node==0) return; + if(this->node->parent!=0) + first_parent_=this->node->parent; + if(first_parent_) + find_leftmost_parent_(); + } + +template +void tree::fixed_depth_iterator::find_leftmost_parent_() + { + return; // FIXME: see 'set_first_parent()' + tree_node *tmppar=first_parent_; + while(tmppar->prev_sibling) { + tmppar=tmppar->prev_sibling; + if(tmppar->first_child) + first_parent_=tmppar; + } + } + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator++() + { + assert(this->node!=0); + + if(this->node->next_sibling) { + this->node=this->node->next_sibling; + } + else { + int relative_depth=0; + upper: + do { + this->node=this->node->parent; + if(this->node==0) return *this; + --relative_depth; + } while(this->node->next_sibling==0); + lower: + this->node=this->node->next_sibling; + while(this->node->first_child==0) { + if(this->node->next_sibling==0) + goto upper; + this->node=this->node->next_sibling; + if(this->node==0) return *this; + } + while(relative_depth<0 && this->node->first_child!=0) { + this->node=this->node->first_child; + ++relative_depth; + } + if(relative_depth<0) { + if(this->node->next_sibling==0) goto upper; + else goto lower; + } + } + return *this; + +// if(this->node->next_sibling!=0) { +// this->node=this->node->next_sibling; +// assert(this->node!=0); +// if(this->node->parent==0 && this->node->next_sibling==0) // feet element +// this->node=0; +// } +// else { +// tree_node *par=this->node->parent; +// do { +// par=par->next_sibling; +// if(par==0) { // FIXME: need to keep track of this! +// this->node=0; +// return *this; +// } +// } while(par->first_child==0); +// this->node=par->first_child; +// } + return *this; + } + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator--() + { + assert(this->node!=0); + if(this->node->prev_sibling!=0) { + this->node=this->node->prev_sibling; + assert(this->node!=0); + if(this->node->parent==0 && this->node->prev_sibling==0) // head element + this->node=0; + } + else { + tree_node *par=this->node->parent; + do { + par=par->prev_sibling; + if(par==0) { // FIXME: need to keep track of this! + this->node=0; + return *this; + } + } while(par->last_child==0); + this->node=par->last_child; + } + return *this; +} + +template +typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator++(int) + { + fixed_depth_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator--(int) +{ + fixed_depth_iterator copy = *this; + --(*this); + return copy; +} + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --(num); + } + return (*this); + } + +template +typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --(num); + } + return *this; + } + +// FIXME: add the other members of fixed_depth_iterator. + + +// Sibling iterator + +template +tree::sibling_iterator::sibling_iterator() + : iterator_base() + { + set_parent_(); + } + +template +tree::sibling_iterator::sibling_iterator(tree_node *tn) + : iterator_base(tn) + { + set_parent_(); + } + +template +tree::sibling_iterator::sibling_iterator(const iterator_base& other) + : iterator_base(other.node) + { + set_parent_(); + } + +template +tree::sibling_iterator::sibling_iterator(const sibling_iterator& other) + : iterator_base(other), parent_(other.parent_) + { + } + +template +void tree::sibling_iterator::set_parent_() + { + parent_=0; + if(this->node==0) return; + if(this->node->parent!=0) + parent_=this->node->parent; + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator++() + { + if(this->node) + this->node=this->node->next_sibling; + return *this; + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator--() + { + if(this->node) this->node=this->node->prev_sibling; + else { + assert(parent_); + this->node=parent_->last_child; + } + return *this; +} + +template +typename tree::sibling_iterator tree::sibling_iterator::operator++(int) + { + sibling_iterator copy = *this; + ++(*this); + return copy; + } + +template +typename tree::sibling_iterator tree::sibling_iterator::operator--(int) + { + sibling_iterator copy = *this; + --(*this); + return copy; + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator+=(unsigned int num) + { + while(num>0) { + ++(*this); + --num; + } + return (*this); + } + +template +typename tree::sibling_iterator& tree::sibling_iterator::operator-=(unsigned int num) + { + while(num>0) { + --(*this); + --num; + } + return (*this); + } + +template +typename tree::tree_node *tree::sibling_iterator::range_first() const + { + tree_node *tmp=parent_->first_child; + return tmp; + } + +template +typename tree::tree_node *tree::sibling_iterator::range_last() const + { + return parent_->last_child; + } + + +#endif + +// Local variables: +// default-tab-width: 3 +// End: